分享:STM32F407的ADC真的不够精准吗?教你设置STM32F407的ADC参数使其精度高于千分之一

2019-07-20 03:52发布

很多人都提到了STM32F407的ADC似乎精度不够。 原子的探索者开发教程里ADC一节最后也用红字提出了STM32F407的ADC精度不怎么好。
实际上STM32F407的ADC精准度真的不够吗?如果其精准度不够,那么其系统误差怎么测试计算?
实际上经过我一系列测试后发现:STM32F407的ADC足够精准,通过设置合理的参数之后,其ADC误差完全可以控制在±0.1%之内
下面先说一下我的测试原理和方法: 电路大概如下图:


上图有一个错误:右上面2K和1K分压之后接入的是STM32F407的Vref引脚,不是ADC
上面采样分压电阻选得比较大,是出于16选1芯片输出负载能力比较低,并且对测试电路有一定影响的考虑。 另外Vref采样分压电阻选的跟AD采样分压电阻不一致,本来想使用一致的值,后来发现STM32F407的Vref的输入阻抗相当低, 使用220K 和100K分压的话,Vref电压远比分压值低,这说明Rref || 100K远小于100K。手头上没有2.2K的电阻,只好用2K的 这也就使得本次测试AD没能达到“满量程”,当然,在经过分压之前,做了个电压跟随。
测试的方法:在STM32F407的main函数while中2分钟内不停的读取16选1的各个通道的AD值,统计其最高值和最低值。 通过设置不同的ADCCLK和采样保持周期,来分析比较,从而选出相对于电路一定的最合理参数。 程序如下 [mw_shl_code=c,true] u8 ucCnt = 0; u16 uwAdcBtmDrop = 9999; u16 uwAdcTopDrop = 0; unAdcTotal = 0; for(ucAdcAddr = 0; ucAdcAddr < 16; ucAdcAddr++) { SetAdcChl(ucAdcAddr); //设置16选1芯片的通道 uwAdcBtmDrop = 9999; uwAdcTopDrop = 0; unAdcTotal = 0; for(ucCnt = 0; ucCnt < 10; ucCnt++) { uwAdcRslt = GetAdcData(); //采集AD if(uwAdcBtmDrop > uwAdcRslt) { uwAdcBtmDrop = uwAdcRslt; } if(uwAdcTopDrop < uwAdcRslt) { uwAdcTopDrop = uwAdcRslt; } unAdcTotal += uwAdcRslt; } //去掉最小值、最大值,然后求平均 unAdcTotal -= uwAdcBtmDrop; unAdcTotal -= uwAdcTopDrop; unAdcTotal /= 8; if(unAdcTotal > uwAdcTop[ucAdcAddr]) { uwAdcTop[ucAdcAddr] = unAdcTotal; } if(unAdcTotal < uwAdcBtm[ucAdcAddr]) { uwAdcBtm[ucAdcAddr] = unAdcTotal; } }[/mw_shl_code]

最后是采集的结果:

呃,图片被压缩了,将就着看吧。
通过对上述结果做如下分析: 多次采集的最高值和最低值的差足够小的话,那么就能保证STM32F407的ADC足够稳定精准,比如采样保持设置为480个周期时, 多次采集的最高值和最低值的差都不大于3,相对于千分之一(±0.1%)的数值(大约是8),其精度约为0.0366%,远高于千分之一精度。
同时,还有一个现象:0通道的值在采样周期比较短(如3个周期)时,其最大和最小值都远高于0,从而得出如下结论: 1、STM32F407的AD引脚和地之间存在一定的分布电容,该分布电容使得使用220K 和100K分压时,不能将AD引脚的电压“及时地”拉低(因为上一个16选1选择的是16,通道电压最高) 2、STM32F407的AD引脚输入电流有一定要求,或者说AD引脚外部的dv/dt能力要足够高,电流太低将影响AD采集精度或时间。
针对上面第2个结论,我曾经考虑过在STM32F407的AD引脚输入之前添加一个电压跟随,结果电压跟随的dv/dt能力也不够(LM258),后来换成高速运放AD8024,结果使用AD8024后, 整个AD采集结果很差,Max-Min在所有的参数上都高于50,结果方案流产(估计买到假运放或者有哪个地方搞错了,比如运放的使用环境或者理论上出了问题)
最后选择一个合理的参数:通过对整个测量结果的比较,选出一个不影响精度的速度最快设置(也可以处于精度考虑,保留一定预留) 如上述采集结果中ADCCLK=14MHz(6分频),采集保持设置为112个周期时,采集时间最短,并且精度较精准,并且0通道的数值合理(0到2之间).如上面的图中绿 {MOD}标出部分


那么是不是大家直接使用该参数就一定适合自己的电路呢?肯定不是 因为大家的电路中外部要采集的数据的dv/dt能力与我的测试电路不一样,肯定会有不一样的“最合理”参数,建议大家跟我一样,做整个范围的测试,从中选出最合理的参数来。


至于原子哥提到的将AD引脚接地,读出的AD值也有几十,我估计电路板布线有一定影响。 我的布线是双层版,模拟输入周围接地,模拟线背面使用覆铜层接地,使得模拟输入线周围全部被“地”包围,最大限度减小干扰。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。