打印

STM32做AD时在输入小于50MV时采样到的值始终为0

[复制链接]
5950|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
killer523|  楼主 | 2013-3-1 16:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32做AD时在输入小于50MV时采样到的值始终为0
并且在逐渐提高输入值时采集到的AD值会逐渐缩小与输入值的差,当超过约2000MV时变成了采样到的值大于实际输入电压
沙发
airwill| | 2013-3-1 17:50 | 只看该作者
呵呵, 被楼主抓到缺陷了吗?
什么芯片, 什么电路, 软件是怎么配置的?
不大相信会有这样的问题.

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
killer523 + 3 赞一个!
板凳
killer523|  楼主 | 2013-3-1 19:11 | 只看该作者
我也很纳闷,以前遇到过类似问题,始终没解决,
AD+DMA

使用特权

评论回复
地板
killer523|  楼主 | 2013-3-1 19:16 | 只看该作者
/**************************************************************
ADC PB1_ADC9

***************************************************************/

#include "STM32Lib\\stm32f10x.h"
#include "STM32Lib\\stm32f10x_adc.h"
#include "STM32Lib\\stm32f10x_dma.h"
#include "main.h"
u16 ADCCov[caiyangdianshu*2];
volatile bool ADC_Ok=FALSE;
static DMA_InitTypeDef DMA_InitStructure;
//static ADC_InitTypeDef ADC_InitStructure;
void ADC_Configuration(void)
{
        ADC_InitTypeDef   ADC_InitStructure;
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        /* PA0,1*/
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0|GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        /* ADC1 */
        ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;                //独立模式
        ADC_InitStructure.ADC_ScanConvMode       = ENABLE;                                                //连续多通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                                                //连续转换
        ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None;        //转换不受外界决定
        ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;                        //右对齐
        ADC_InitStructure.ADC_NbrOfChannel       = 2;                                                        //扫描通道数
        ADC_Init(ADC1, &ADC_InitStructure);
       
        /* ADC1 Regular Channel1 Configuration                                      */
        ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);        //通道X,采用时间为55.5周期,1代表规则通道第1个
        ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);        //通道X,采用时间为55.5周期,2代表规则通道第2个
                /* 允许ADC1的DMA模式 */
        ADC_DMACmd(ADC1, ENABLE);

        ADC_Cmd   (ADC1, ENABLE);             /* Enable ADC1                        */
        ADC_SoftwareStartConvCmd(ADC1,ENABLE);/* Start ADC1 Software Conversion     */ //使能转换开始
}

       

//DMA的配置
void DMA_Configuration(void)
{
       
        /* 允许 DMA1 */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        /* DMA通道1*/
        DMA_DeInit(DMA1_Channel1);
        DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)( &(ADC1->DR));                //ADC1数据寄存器
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCCov;                                        //获取ADC的数组
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                        //片内外设作源头
        DMA_InitStructure.DMA_BufferSize = caiyangdianshu*2;                                                                //每次DMA16个数据
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设地址不增加
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                //内存地址增加
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;        //半字
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                        //半字
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                                //普通模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                                        //高优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                                                //非内存到内存
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
       
        DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);                                                                //DMA通道1传输完成中断
       
        /* Enable DMA1 channel1 */
        DMA_Cmd(DMA1_Channel1, ENABLE);
        ADC_Cmd   (ADC1, ENABLE);
                ADC_SoftwareStartConvCmd(ADC1,ENABLE);

}

//重新允许DMA,
void DMAReConfig(void)
{
        DMA_DeInit(DMA1_Channel1);
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
        DMA_Cmd(DMA1_Channel1, ENABLE);
}

用到PA0                         

使用特权

评论回复
5
logokfu| | 2013-3-1 19:59 | 只看该作者
楼主,你的AD没有进行软件校准啊。

使用特权

评论回复
6
killer523|  楼主 | 2013-3-1 20:29 | 只看该作者
        ADC1->CR2|=1<<0;     //开启AD转换器(此处也就是ADON=1)  
ADC1->CR2|=1<<3;        //使能复位校准  
while(ADC1->CR2&1<<3);  //等待校准结束     
    //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。   
ADC1->CR2|=1<<2;        //开启AD校准    (下面说了,校准前ADON必须为0,但上面已经设置了ADON=1)
while(ADC1->CR2&1<<2);  //等待校准结束
//该位由软件设置以开始校准,并在校准结束时由硬件清除
开机时校准了

使用特权

评论回复
7
killer523|  楼主 | 2013-3-2 11:00 | 只看该作者
问题已解决,程序配置有问题,现在AD相当准确

使用特权

评论回复
8
killer523|  楼主 | 2013-3-2 11:07 | 只看该作者
怎么结贴,怎么结不了

使用特权

评论回复
9
cjhk| | 2013-3-2 20:03 | 只看该作者
呵呵   一般片子出问题的概率很小的  呵呵      多逛21ic   没有搞不定的问题

使用特权

评论回复
10
hxm2013| | 2013-5-16 16:34 | 只看该作者
怎么配子的啊?分享一下啊

使用特权

评论回复
11
hawksabre| | 2013-5-16 18:56 | 只看该作者
楼主   问题解决了不错   希望你能共享一下你的解决方法   很多人遇到同样的问题时   还是不知道怎么解决

使用特权

评论回复
12
tangzhao_01| | 2013-11-3 16:00 | 只看该作者
楼主是哪里出问题了,程序配置上有什么问题???

使用特权

评论回复
13
tangzhao_01| | 2013-11-3 16:01 | 只看该作者
hawksabre 发表于 2013-5-16 18:56
楼主   问题解决了不错   希望你能共享一下你的解决方法   很多人遇到同样的问题时   还是不知道怎么解决  ...

你好,请问你的问题解决了吗?

使用特权

评论回复
14
stars_txx| | 2015-7-12 22:34 | 只看该作者
本帖最后由 stars_txx 于 2015-7-13 00:07 编辑

我也遇到同样的问题,由于楼主没有说明解决原因,摸索了两天后终于找到问题所在,我将过程记录下来给广大同仁做个参考。
硬件配置:STM32F105R8 64pin,由于64pin芯片没有REF端口,外配置一片REF3012做基准参考
电源:TPS5430+XL1509+LM1117分别输出12V,5V,3.3V,其中3.3V供MCU及外设
系统:uCOSII+FreeModbus
PC端软件:Modbus Poll 将ADC采集电压传输到PC监视

未整改前,ADC主要表现2个方面:
1、不断跳动,幅度达到±40LSB
2、50mV以下始终为零

整改一:
开始怀疑是开关电源纹波引起,换成线性稳压源供电后,采样跳动变为±2LSB,有很大改善,50mv零值下降到40mV
整改二:
所有ADC引脚加入RC滤波,1k电阻+104电容,采样跳动无明显改善,40mv零值下降到35mv,但一旦使用开关电源还是抖动厉害
整改三:
将模拟电源,模拟地单点接入入LM1117滤波电容两端,使用开关电源的抖动和线性电源一样,整改有效,但还是保持35mv以下采样为零,到此,无论如何调整电路和程序(降频,使用内部震荡,延长校准时间器等)都无任何明显改善,准备放弃使用片内ADC
整改四:
抱着死马当活马医的心态,换芯片,奇迹发生,直接采样到1mv以下,基准端采样跳动±1LSB,使用精密源表测试,0~3V最大误差保持在0.5%,达到设计要求


总结:
1、模拟地,数字地,模拟电源,数字电源必须分开布线
2、ADC输入端加入RC滤波




使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

96

帖子

0

粉丝