STM32的48脚的单片机因为没有Vref+,Vref-,所以我们使用一些高精度参考电压芯片来提高ADC的精度很不方便。这里还有一种方法可以参考下.
STM32内部有一个专门用于校准的稳压器VREFINT,,它由外部的VSSA供电,他的电压一般为1.2V左右。 ADC17通道用于检测这个基准电压,在每颗芯片出厂时 ,ST公司会给芯片的VSSA和VDDA加上一个高精度的3v电压, 然后读出此时的ADC17通道的值存放在芯片内部;我们可以利用这个值精确的算出外部VSSA的电压,然后进一步算出外部ADC的精确电压.
注意:要获得精确的电压还要注意ADC的取样时间要足够长,并且需要启动校准
实验过程:(我的VDDA和VDD是连接 在一起的大约3.2V左右)
1.读取ST在标准3v外加电压条件下的内部ADC基准电压采样值
我用的是STM32L051单片机,通过查询编程手册,我知道了内部基准电压存放在0x1FF80078这个地址.(不同的芯片存放地址可能不同)
定义一个变量
__IO uint16_t VREFINT_CAL=0;
VREFINT_CAL=*(__IO uint16_t *)(0x1FF80078); //得到一个16进制的
注意;这里需要地址对其,否则会进入硬件错误!!
我这里VREFINT_CAL读出来的值是0x65D,
2.读取自己的板子当前电压条件下的内部ADC基准电压采样值**
//第一步开启校准,这一步非常重要,如果不开可能误差较大
HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);
//开启ADC转换
HAL_ADC_Start(&hadc);
//等待转换完成
if(HAL_ADC_PollForConversion(&hadc, 200)== HAL_OK )
{
//获取在当前供电条件下的ADC采样值,我的VDDA和VDD是连接
// 在一起的大约3.2V左右
VREF_ADC1_17=HAL_ADC_GetValue(&hadc);
}
3.通过芯片手册提高的公式进行转换
VDDA=3VREFINT_CAL1000/VREF_ADC1_17; //因为单片机不好处理浮点型,我就*1000扩大了1000倍
到这里你的板子的VDDA就精确的算出来了. 我实验单片机测得的电压和万用表测试结果相差0.01,已经非常精准了!!
知道了精确的VDDA那么外部ADC电压就简单了,这里不再赘述
注意:检测ADC电压时检测时间一定要够长,外部ADC管脚的分压电阻不要太大,因为ADC还是需要一一定量电流的,而且开启校准.
如下:我采用时间选择最长,更加准确
hadc.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;