stm32 adc 多通道切换与采样精度

一、运行环境

  • stm32f070
  • STM32F0xx_StdPeriph_Lib

二、多采样通道切换

在之前的项目中,涉及有多个采样通道的采样,一直采用adc + dma的方式。后来因为需求的问题,要改成每次只采样一个通道。但是却发现,无论切换哪个通道,读取回来的参数都是一样的,明显跟实际不符合。

库函数提供的切换通道的函数
ADC_ChannelConfig ( ADC1, ADC_Channel_11, ADC_SampleTime_239_5Cycles )
里面的实现有一点与我所理解的不一样:
ADCx->CHSELR |= (uint32_t)ADC_Channel;
这里用的是 或 而不是赋值符号。所以每次切换通道的时候,上一次的通道其实还在采样。
我的修改方法:

ADC_ChannelConfig ( ADC1, ADC_Channel_11, ADC_SampleTime_239_5Cycles )
ADC1->CHSELR = ADC_Channel_11

三、采样精度问题

3. 1 一些基础概念

  • VDDA: 模拟供电引脚(外部输入)
  • VSSA: 模拟地
  • Vrefint:内部参考电压。Vrefint 在单片机内部直接接到ADC_IN17,通过采样该通道的电压,可以计算出Vrefint。
最小值 典型值 最大值
1.2v 1.23v 1.25v

3.2 遇到的问题

adc 采样回来的电压跟实际电压偏差比较大。

问题分析:

  1. 采样时间短。
  2. 单片机供电电压不是稳定的3.3v。单片机虽然有模拟供电引脚,但是为了省成本,模拟供电引脚接了VDD。

解决办法:

采样时间的问题

一开始的采样周期选择的是ADC_SampleTime_13_5Cycles,但是误差一直比较大,选择最大的采样周期(ADC_SampleTime_239_5Cycles )后,误差才达标。

针对供电电压不稳的问题
  1. 使用标准电压芯片作为VDD,VDDA。

  2. 或者想办法计算出真正的模拟输入电压,也就是VDDA。
    2. 1 官方提供的计算VDDA 的公式
    在这里插入图片描述
    2.2 其中VREFINT_CAL 是每个芯片出厂的时候,厂家校正好的参数,存放在flash中的某个只读区域。针对我这款单片机,存放地址是0x1FFF F7BA- 0x1FFF F7BB 长度为两个byte
    在这里插入图片描述

    2.3 VREFINT_DATA 是从ADC_CHN17 读取到的内部参考电压adc值。
    2.4 我现在测试使用的单片机的实测数据:VDDA = 3.3v * 1524 /1615 ,即是3.144v。用万用表测到的vdd参数是3.150v。精确到0.01v。
    2.5 示例代码

#define BSP_ADC_RD_VREFINT_CAL()           (*(__IO uint16_t *)(0x1FFFF7BA)) //VREF_CAL 值

uint16_t bsp_adc_read_vrefint_data(void)
{
    ADC_ChannelConfig ( ADC1, ADC_Channel_Vrefint, ADC_SampleTime_239_5Cycles );
    ADC1->CHSELR = ADC_Channel_Vrefint;
    ADC_VrefintCmd ( ENABLE );
    ADC_StartOfConversion ( ADC1 );
    while (  ADC_GetFlagStatus ( ADC1, ADC_FLAG_EOC ) == RESET )
        ;
    return ADC_GetConversionValue ( ADC1 );
}
uint16_t bsp_adc_calc_vdda(void)
{
    return (uint16_t)(3.3 * BSP_ADC_RD_VREFINT_CAL() /  bsp_adc_read_vrefint_data());
}

四、参考文章

STM32如何通过内部VREF得到实际的VDDA值

发布了52 篇原创文章 · 获赞 0 · 访问量 845
App 阅读领勋章
微信扫码 下载APP
阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览