STM32L476在电池供电较低,如何保证还能精准测量电池电量,HAL编程DMA多通道采集ADC,内部基准修正。

1、项目背景概述

1.1、供电低于外部校准电压,导致ADC采集不准描述

        最近接触的项目是由3.6V(新电池)电池供电,需要在3.4V、3.2V、2.9V分别提示一级、二级、三级低电,低于2.9V认为掉电。同时还有一个7.2V(新电池)通信电池,也需要精准采集电压。项目需要LCD点阵液晶屏显示,要求可设开启或关闭背光灯。

        但是在开启背光灯的时候,电压采集很明显不准(偏高),原因是开启背光需要很大的电流,导线上也有点阻值,导致接入板子的电压只有3.4V,再经过二极管和稳压芯片后达不到理想的3.0V电压(实际只有2.7V)给单片机供电,其此电压也是连接STM32单片机的外部基准电压。如果电池电压实际低于3.6V可能检测结果更离谱。


        根据查阅芯片手册,可以采用STM32L476单片机内部基准电压修正,达到精准检测的目的。

1.2、理想状态

        想要的理想情况是,只要不低于单片机重启电压,对外部电池电压能精准的采集。如上图电路所示,若外接电池是3.2V,经过D95二极管再经过U90稳压芯片到系统供电(只有2.7V),不足理想的3.0V系统供电,但需要ADC采集电池电压是3.2V左右,而不是因为系统供电低而偏高这种错误情况出现。

        通过DMA多通道采集电压,HAL库编程。实验目的:

        ①DMA方式多通道采集电压。

        ②采用内部基准电压修正读取的电压值。

2、解决方案

2.1、解决方案描述

        这里直接拿出精简公式Vbat=(Vdda * (vrefint/4096)*(BATadc/VREadc))

        Vbat : 待求电池电压值

        Vdda: 单片机VDDA引脚接入的外部基准电压,我这边是3.0V。

        vrefint:单片机内部存储的参考电压值,STM32L476单片机存储地址在0x1FFF75AA~0x1FFF75AB

        BATadc:当前实际的电池的ADC值(我这选择的12bit)。

        VREadc:当前实际的内部通道的ADC值(我这选择的12bit),STM32L476单片机采集通道是ADC1_IN0

        其中4096表示选择12bit精度,如果选择10bit精度则是1024,具体原理参考博文STM32 ADC采样使用内部参考电压_stm32adc参考电压-CSDN博客

2.2、HAL库编程配置实现

1、打开debug调试,并配置系统时钟,我这边使用的内部高速时钟。

2、首先打开自己项目对应的通道(15通道3.6V电池,16通道7.2V通道),然后开启内部基准电压采集通道。

3、ADC1的通道参数配置,根据自己项目需求开打对应的通道配置。

4、采用的是DMA数据传输,如下配置。

2.3、HAL库编程程序实现

1、获取内部的基准电压值,用于修正读取的电压。

#define VREFINT_CAL		  (uint16_t)(*(__I uint16_t *)(0x1FFF75AA))//读取内部存储的基准值

 2、通过DMA读取三个通道的ADC值,并做计算得出电压值(扩大100倍的)。

void dong_start_adc()
{
	if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
	{
			Error_Handler();
	}
    
    //启动DMA
  if(HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_Values,ADC_MAX_NUM) != HAL_OK)
	{
			Error_Handler();
	}
//   while(!(__HAL_DMA_GET_FLAG(&hdma_adc1,DMA_FLAG_TC1))){;}//等待DMA转换完成
//	  __HAL_DMA_CLEAR_FLAG(&hdma_adc1,DMA_FLAG_TC1);//清楚DMA标志位
		HAL_DMA_PollForTransfer(&hdma_adc1,HAL_DMA_FULL_TRANSFER,1000);
		//	HAL_Delay (10);
		HAL_ADC_Stop_DMA(&hadc1);//停止ADC常规组转换,禁用ADC DMA传输
	
		uint32_t VBAT1_mV,VBAT2_mV;
		uint16_t vrefint = *((uint16_t*)0x1FFF75AA);//获取单片机内部校验电压值(固定不变的)
		double vrefint_f,bat1_t,bat2_t;
		
		vrefint_f = ADC_Values[2];        //读取当前的内部基准电压ad值
		bat1_t = ADC_Values[0];           //读取当前的3.6V电池电压ad值
		bat2_t = ADC_Values[1];           //读取当前的7.2V电池电压ad值
		
		VBAT1_mV = 3000*(3.0*(vrefint/4096.0))*(bat1_t/vrefint_f);//计算计量电池电压(默认扩大1000倍)
		
		VBAT2_mV = 6000*(3.0*(vrefint/4096.0))*(bat2_t/vrefint_f);//计算通讯电池电压(默认扩大1000倍)
	

		HAL_Delay(2000);
}

3、其中3000*公式 与 6000*公式,分别是根据硬件电路的分压公式。

4、看实际效果如下:

  • 33
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值