【极海APM32替代笔记】HAL库ADC测量精度提高方案(利用内部参考电压VREFINT计算VDDA来提高精度)
多数STM32的MCU 都没有内部基准电压 如L496系列
但在外接VDDA时(一般与VCC 3.3V连接) 有可能VCC不稳定 导致参考电压不确定 从而使ADC测量不准确
STM32内置一个测量VREFINT的ADC通道 且在寄存器VREFINT_CAL中会存储在3.0V标准电压的情况下 该VREFINT的ADC测量数据结果(12位精度)
STM32L496的VREFINT_CAL地址如图 该值为16位数据
读取时:
#define VREFINT_CAL (uint16_t)(*(__I uint16_t *)(0x1FFF75AA))
我读出来是1655
该值表示此芯片在30℃ 3.0V的标准电压下的VREFINT测量结果
根据手册:
由公式3即可校准ADC的测量
比如我对VREFINT的ADC测量出来是1400
我要测的ADC通道是1500
则实际被测ADC通道实测值为:
3.0f*1655*1500/1400/4095
代码示例:
我用ADC1来测量VREFINT 一定要配置为12位精度 方便计算
另外 ADC2 通道9是我要测的电压
STM32的ADC最大的转换速率为1MHz,也就是说最快转换时间为1us,为了保证ADC转换结果的准确性,ADC的时钟最好不超过14M。
其中 T = 采样时间 + 12.5个周期,其中1周期为1/ADCCLK
例如,当 ADCCLK=14Mhz 的时候,并设置 1.5 个周期的采样时间,则得到: Tcovn=1.5+12.5=14 个周期=1us。
当ADCCLK=50Mhz的时候,设置37.5个采样周期 37.5+12.5=50
/*!
* @brief 开启ADC通道,返回ADC值
*
* @param [in] hadc: ADC_HandleTypeDef 变量地址
*
* @return ADC_Value: ADC平均值结果
*/
uint16_t Get_ADC_Value(ADC_HandleTypeDef *hadc)
{
uint16_t ADC_Value=0;
HAL_ADCEx_Calibration_Start(hadc,ADC_SINGLE_ENDED);
HAL_ADC_Start(hadc); //启动ADC转换
HAL_ADC_PollForConversion(hadc, 5); //等待转换完成,5为最大等待时间,单位为ms
if(HAL_IS_BIT_SET(HAL_ADC_GetState(hadc), HAL_ADC_STATE_REG_EOC))
{
ADC_Value = HAL_ADC_GetValue(hadc); //获取AD值
}
return ADC_Value;
}
/*!
* @brief 计算ADC的真实值,包含VREFINT校准后的结果
*
* @param [in] hadc: ADC_HandleTypeDef 变量地址
*
* @return ADC_Real_Value: ADC校准后的真实值
*/
float Get_Real_ADC_Value(ADC_HandleTypeDef *hadc)
{
uint16_t VREFINT_DATA = Get_ADC_Value(&hadc1);
uint16_t ADC_DATA = Get_ADC_Value(hadc);
float ADC_Real_Value = 3.0f*VREFINT_CAL*ADC_DATA/VREFINT_DATA/4095.0f;
return ADC_Real_Value;
}
两个通用函数
float ADC = Get_Real_ADC_Value(&hadc2);
调用方式
这样测出来就不用考虑VDDA电压是否稳定了 在一定范围内还是相对来说比较精确的