当前位置:   article > 正文

HAL库学习——ADC精度问题以及多通道采集_hal_adcex_calibration_start

hal_adcex_calibration_start

一、简介

      博主在使用ADC测量电池电压时,发现测出来的AD值转换为实际电压不匹配,偏差大,因此通过网上收集资料,最终得知ADC采集精度提升的方法。前半部分主要是涉及多通道电压值采集,CubeMx的配置以及代码实现,以采集ADC1通道0、通道8和内部基准电压为例。后半部分讲解使用内部基准电压计算精确度较高的电压值。

 

二、运行环境

  MCU: STM32L071CBT6

  配置工具:STM32CubeMx

  IDE:MDK5

 

三、CubeMx配置

时钟配置:

        使用RCC外部低速时钟。

ADC配置:

        开启ADC的通道0、通道8和内部电压通道。

         当使用多通道采集时,Discontinuous Conversion Mode(间断转换模式)要使能。

串口配置:

       博主所用的板子将LPUART1引出来当调试串口,用来打印ADC转换的AD值,以验证ADC转换成功,串口配置如下,波特率设为9600Bit/s,Word Length为8 Bit,其余设置不变。

 

四、代码实现

       上述配置完生成代码如下:

     

printf函数映射

  1. #include <stdio.h>
  2. //printf函数映射
  3. int fputc(int ch, FILE *f)
  4. {
  5. HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xffff);
  6. return ch;
  7. }

       为了使ADC采集值更准确,在ADC初始化完后使用HAL库函数HAL_ADCEx_Calibration_Start做自校准。

  1. MX_ADC_Init();
  2. if (HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED) != HAL_OK)
  3. {
  4. printf("校准失败\r\n");
  5. }

   采集数据并打印

  1. uint8_t i;
  2. uint16_t adValue[3];
  3. while (1)
  4. {
  5. /* USER CODE END WHILE */
  6. /* USER CODE BEGIN 3 */
  7. for (i = 0; i < 3; i ++)
  8. {
  9. if (HAL_ADC_Start(&hadc) != HAL_OK)
  10. {
  11. printf("ADC开启失败\r\n");
  12. }
  13. if (HAL_ADC_PollForConversion(&hadc, 10) != HAL_OK)//等待转换完成,第二个参数表示超时时间,单位ms
  14. {
  15. printf("ADC转换失败\r\n");
  16. }
  17. if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc), HAL_ADC_STATE_REG_EOC))
  18. {
  19. adValue[i] = HAL_ADC_GetValue(&hadc);
  20. printf("通道[%d]:%d\r\n", i, adValue[i]);
  21. }
  22. }
  23. HAL_ADC_Stop(&hadc);
  24. HAL_Delay(1000);
  25. }

串口助手输出如下

       通道[0]对应的为配置里的IN0,通道[1]对应的为配置里的IN8,通道[2]对应的为配置里的内部电压通道。由于通道[0]没有接任何输入电压,所以其采出来的AD值近乎为0,通道[1]通过外部做了1/2分压所以其采集出来的AD值为2326,通道[2]采集的是内部参考电压实际值,从数据手册可以得知内部参考电压的校准值存于地址0X1FF80078。

可将其值读出来:

  1. uint16_t VREFINT_CAL;
  2. VREFINT_CAL = *(__IO uint16_t *)(0X1FF80078);
  3. printf("VREFINT_CAL:%d\r\n",VREFINT_CAL);

VREFINT_CAL = 1674,该值是在25°C,输入电压为3V情况下得到得,实际板子供电电压并不是如此,因此得出来会有误差,但基本接近。通道1的电压是博主自己给的,通过万用表测量得实际电压为1.71V。而理论代入公式应为:

(通道[1]AD值 / 4096) * 3.3V = (2297 / 4096) * 3.3 = 1.85V

跟实际差太多。通过查阅资料得知,为了更准确的获得采集的电压,需要使用内部参考电压计算实际的供电电压,将电源相关的 ADC 测量值转换为绝对电压值。具体计算公式在参考手册中:

      VREFINT_CAL即为内部参考电压的校准值为1674,ADC_DATAx即为通道[1]测出来的AD值,VREFINT_DATA为内部参考电压实际值,即为通道[2]的值。所使用的单片机ADC分辨率为12位所以FULL_SCALE的值为4095。将上述值代入公式,用代码实现如下:

  1. float realVol;
  2. realVol = (float)(3 * VREFINT_CAL * adValue[1]) / (adValue[2] * 4095)
  3. printf("V = %.4f\r\n", realVol);

        最终得出的电压值在1.71V左右浮动,因此通过此方法可以测量出更精确的电压值。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/125992
推荐阅读
相关标签
  

闽ICP备14008679号