思路,内部校准值为输入3.0V下的1.2V基准,这个值在一个固定地址中记为X1,读出来就可以
然后拿ADC去采内部基准得到记为X2,就可以反算输入电压VDDA了
VDDA=3*X1/X2.得到VDDA后可以把ADC计算式改为4096/VDDA,这样就精确了
校准的前提是VDDA要稳,如果输入变化,VDDA也在变,那初次校准值没有任何意义!!!
// ADC采样次数(可以自定义,建议大于等于5)
#define ADC_SAMPLES 10
uint16_t VREFINT_Samples[ADC_SAMPLES],VREFINT_Sum,VREFINT_Max=0,VREFINT_Min=0xFFFF;
uint16_t VREFINT_Calibration_Value; //内部记录值
float VREFINT_Avg=0;
float VDDA_Real=3.307f; //电压实际值
放在初始化函数内校准
/**ADC内部基准自校准**/
VREFINT_Calibration_Value = *(volatile uint16_t*)0x1FFF75AA; // 获取ST工厂校准值,3.00V下的
for (int i = 0; i < 10; i++) {
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) {
VREFINT_Samples[i] = HAL_ADC_GetValue(&hadc1);
} else {
VREFINT_Samples[i] = 0; // 出错则记为0
}
HAL_Delay(70);
}
// 统计最大最小值并计算总和
for (int i = 0; i < ADC_SAMPLES; i++) {
if (VREFINT_Samples[i] > VREFINT_Max) VREFINT_Max = VREFINT_Samples[i];
if (VREFINT_Samples[i] < VREFINT_Min) VREFINT_Min = VREFINT_Samples[i];
VREFINT_Sum += VREFINT_Samples[i];
}
VREFINT_Sum -= VREFINT_Max;
VREFINT_Sum -= VREFINT_Min;
VREFINT_Avg = VREFINT_Sum / (ADC_SAMPLES - 2);
VDDA_Real=3.00f*(float)VREFINT_Calibration_Value/VREFINT_Avg;
得到VDDA_Real值