[STM32F1]

使用STM32F103VCT6 的ADC过程中 采集的AD值跳变,不稳定

[复制链接]
18648|10
手机看帖
扫描二维码
随时随地手机跟帖
yuandm1|  楼主 | 2015-7-7 11:15 | 显示全部楼层 |阅读模式
本帖最后由 yuandm1 于 2015-7-7 13:02 编辑

使用STM32F103VCT6 的ADC 连接外部称重传感器。测量的模拟值一直在跳动,大约有20个AD的变化。
ADC的外部输入电压范围为0-3V。用示波器观察纹波后,发现波形还可以。如下图。 PIC_20150707_092705_4BE.jpg

展开以后的波形

展开以后的波形

程序如下:
void ADC_Configuration(void)
{
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        DMA_InitTypeDef DMA_InitStructure;

        /* Enable DMA clock */   //-------------------------------------------------------------------------RCC
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
   /* Enable ADC1 and GPIOC clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);

          /* DMA channel1 configuration */ //------------------------------------------------------------------DMA
        //使能DMA
        DMA_DeInit(DMA1_Channel1);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;                            //DMA外设ADC基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&(system1.Adc_Values);                    //DMA传送地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                            //传送方向
        DMA_InitStructure.DMA_BufferSize = M_SAMPLE_COUNT*M_ADC_NUMS;                                //传送内存大小   M_SAMPLE_COUNT*
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;         
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                         //传送内存地址递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;                //ADC1转换的数据是16位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                //传送的目的地址是16位宽度
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                        //循环模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;                //高优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                        // 不是内存到内存
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);

        /* 允许DMA1通道1传输结束中断 */
        //DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);
                //使能DMA通道1
        DMA_Cmd(DMA1_Channel1, ENABLE);

    //设置AD模拟输入端口 IO  //---------------------------------------------------------------------------IO
         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1 ;//PB0 是拉力传感器 PB1是虚拟限位传感器
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
         
        //ADC配置--------------------------------------------------------------------------------------------ADC
//        ADC_DeInit(ADC1);  //将外设 ADC1 的全部寄存器重设为缺省值
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC1工作在独立模式
        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数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = M_ADC_NUMS;               //规定了顺序进行规则转换的ADC通道的数目。这个数目的取值范围是1到16
        ADC_Init(ADC1, &ADC_InitStructure);
        //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间   
        ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_239Cycles5 );
        //使能ADC1 DMA
        ADC_DMACmd(ADC1, ENABLE);
        //使能ADC1
        ADC_Cmd(ADC1, ENABLE);        
        // 初始化ADC1校准寄存器
        ADC_ResetCalibration(ADC1);
        //检测ADC1校准寄存器初始化是否完成
        while(ADC_GetResetCalibrationStatus(ADC1));
        //开始校准ADC1
        ADC_StartCalibration(ADC1);
        //检测是否完成校准
        while(ADC_GetCalibrationStatus(ADC1));
        //ADC1转换启动
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);        
         
}

由于有上面的波动。虽然做了中值滤波,平均值滤波。可是效果还是不很好。
请问大家在做ADC的时候用的什么算法。谢谢。
mmuuss586| | 2015-7-7 13:05 | 显示全部楼层
提高电源稳定性看看;
最好用基准源供电;

使用特权

评论回复
mmuuss586| | 2015-7-7 13:06 | 显示全部楼层
滤波的话,最好加工频滤波算法;

使用特权

评论回复
yuandm1|  楼主 | 2015-7-7 14:32 | 显示全部楼层
谢谢解答,单片机部分供电我用的LM2576-Adj,模拟电路部分用的LM7812,模拟地和数字地用磁珠隔离开了。请问版主,一般正常情况下,使用ADC的时候,如果外部输入不变化,内部获取的数字量,变化多少算是正常值呢。谢谢啦

使用特权

评论回复
icecut| | 2015-7-7 14:36 | 显示全部楼层
贴代码干嘛?不是程序问题

使用特权

评论回复
yuandm1|  楼主 | 2015-7-7 14:39 | 显示全部楼层
icecut 发表于 2015-7-7 14:36
贴代码干嘛?不是程序问题

那就好,谢谢

使用特权

评论回复
Thor9| | 2015-7-7 19:02 | 显示全部楼层
是不是得需要加滤波,消除噪声干扰

使用特权

评论回复
375606426| | 2015-7-7 21:31 | 显示全部楼层
模拟电路和数字电路最好用0欧姆的电阻链接

使用特权

评论回复
fanxsd| | 2015-7-7 23:10 | 显示全部楼层
你这明显的是电源的问题,LM2576 前级电源是什么,高频开关电源吗。这部分有干扰 后级电源干扰直接带入了。

使用特权

评论回复
forrest11| | 2015-7-8 09:43 | 显示全部楼层
20AD的变化是指什么?是指数据变化范围20左右?
正常啊,芯片是12位的AD(?,我没查),3.3v参考电压? 那么一个LSB就大概0.8mv.  你的信号噪声幅值为25mv左右,所以对于采样值就是约30. 所以你现在结果已经很好了。因为如果考虑参考电压的噪声,ADC本身的噪声和误差。你的采样结果可能噪声更大。

使用特权

评论回复
amanda_s| | 2015-7-8 17:13 | 显示全部楼层
可以看看AN2834- How to get the best ADC accuracy

使用特权

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

本版积分规则

个人签名:善始善终,努力坚持

23

主题

177

帖子

1

粉丝