STM32 电池电压采集之低功耗设计

STM32 电池电压采集之低功耗设计

前言

最近在搞一个小项目用到了电池电量采集,工作时必须带有电池电压检测(3.3V-4.2V)。在网上1看到了一个低功耗产品教程可实现电池电压精确ADC采集,特此记录学习。
当我们利用单片机ADC采样功能,采集电流电压信号时,单片机的IO口输入电压范围是0~3.3V,所以为了保证安全,需要把测量电压保持在这个范围之内。


提示:以下是本篇文章正文内容,下面案例可供参考

一、ADC采集输入阻抗的问题

初始设计是用两个阻值相同电阻分压直接进行ADC采集,阻值1M,由该电路引起的待机电流为4.2/(1000 +1000)mA=2.1uA,此时比较合理。
在这里插入图片描述
编程采集数据时发现测试电压与实际电压有偏差,测试值总比实际值偏小一点。在软件上做补偿,把值修正了。
但是换一个板子测试的时候发现测试的电压又不准了,此时知道通过软件补偿这种方法行不通。那么只能从硬件找原因。
查找datasheet发现AD的输入阻抗最大只有50KΩ。
在这里插入图片描述
在这里插入图片描述
图中RAIN:外部输入阻抗,STM32L051芯片中这个值最大为50KΩ;STM32F1032芯片中这个值最大为350KΩ;
RADC:采样开关电阻,最大值为1KΩ;
CADC:内部采样和保持电容,最大值为8pF;STM32F1032这个值最大为12pF。
在ADC数据采集的时候需要有电流流入,那么RAIN会产生一个压降。阻容网络中的RADC和CADC上,对电容的充电由RADC控制。随着源电阻(RADC)的增加,对保持电容的充电时间也相应增加。
对CADC的充电由RAIN+RADC控制,因此充电时间常数为tc = (RADC + RAIN) × CADC。如果时间过短,ADC转换的数值会小于实际值。
通过以上数据知道,采集精度跟采集时间和输入阻抗有关。但是通过计算得知,如果输入阻抗为300KΩ,那么充电时间约为2.4uS。在软件上把采样周期调到最大(ADC_SampleTime_239_5Cycles,频率为12M,时间19.9uS),还是存在误差。说明此时跟周期不是主要原因。
问题出在输如阻抗大于IC里ADC允许的最大阻抗。充电时电流分两路,一路经过R1到R2到地,还有一路经过R1流入MCU的AD接口。(不知是不是IO口会有一定的漏电流到地,IL)此时相当于在R2旁边并了一个电阻到地,检测点的电压不是标准的1/2Vbat.

二、改进方法

下面介绍三个设计方案,方案一、二测试有效、方案三参考 TI 的 bq76930 产品说明书,仅供参考。

1.1加入运放同相放大(电压跟随器)

由上面调试可以确定是AD采集输入阻抗过大的问题,加入电压跟随器后的阻抗可以低至毫欧级,因此选用一个低功耗(待机600nA,输入阻抗1TΩ)的电压跟随器可以完美解决这个问题。
待机时U1的供电被切断,主要功耗来自R5,R6回路。待机电流为4.2/(2000 +2000)mA=1.05uA
此种方案成本较高,但稳定度和精确度高。
电路如下:
在这里插入图片描述

1.2加入运放差分放大

同样是利用运放进行电压,电流放大,采用差分放抗干扰能力比同相更高。
待机时U2的供电被切断,主要功耗来自R8,R9回路。待机电流为4.2/(2000 +2000)mA=1.05uA
电路如下:
在这里插入图片描述

2.休眠时控制参考地

分压电阻选用在阻抗以内的阻值,工作时采集电流高点可以忽略,休眠时通过单片机控制采集电路GND来减小功耗。单片机休眠时将PA4拉高,待机电流为(4.2-3.3)V/(50+50)mA=9uA。此种方案电路设计最为简单。
电路如下:
在这里插入图片描述

3.MOS管关断控制参考地

用MOS管控制电量采集开关,此种方法休眠时电流最小,几乎不计。休眠时PA4为低电平关断测量分压电阻不耗电,要测量前置高电平,在PA5测量电压。
电路如下:
在这里插入图片描述
在这里插入图片描述

总结

上面介绍三个设计方案,方案一、二测试有效、方案三参考其他博客大牛,还未验证,仅供参考。关于低功耗方面的硬件方案思路很多,各位小伙伴可以大胆构思,小心求证。


  1. 网上参考链接 ↩︎

  2. STM32F103芯片中这个值最大为350KΩ在这里插入图片描述
    在这里插入图片描述 ↩︎ ↩︎

### STM32 ADC用于电池电量监测与充放电管理 #### 使用ADC进行电池电量监测 STM32微控制器内置有高精度的模数转换器(ADC),能够实现对模拟信号的有效采集。对于锂电池电量检测而言,主要依赖于ADC读取分压电阻网络上的电压值来间接获取电池的实际电压水平[^3]。 为了提高测量准确性,在硬件电路设计上通常采用精密电阻构成分压回路连接至ADC输入端口;软件方面则需配置好相应的初始化参数并编写合适的算法处理采样得到的数据。具体来说: - **初始化设置**:开启时钟使能、选择通道、设定分辨率等; - **启动转换**:单次模式下手动触发或连续扫描方式自动循环工作; - **结果计算**:依据公式`Vbat=Vref*(ADCRawValue/MaxRawValue)*Rtotal/Rshunt`得出最终数值,其中各变量含义分别为参考电压、原始读数、最大量化级以及总阻抗和分流电阻之比。 ```c // 初始化函数定义 void Init_ADC(void){ // 配置GPIO引脚作为模拟输入 GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 设置ADC模块属性 ADC_ChannelConfTypeDef sConfig; hadc.Instance = ADC1; hadc.Init.ScanConvMode = DISABLE; hadc.Init.ContinuousConvMode = ENABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc)!= HAL_OK){Error_Handler();} sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; if(HAL_ADC_ConfigChannel(&hadc,&sConfig) != HAL_OK){Error_Handler();} } float GetBatteryVoltage(){ uint32_t raw_value; float voltage; HAL_ADC_Start(&hadc); HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY); raw_value = HAL_ADC_GetValue(&hadc); HAL_ADC_Stop(&hadc); // 假设 Vref为3.3V,Rtotal 和 Rshunt 已知情况下简化表达式 voltage=(raw_value*3.3)/4096 * ((Rtotal+Rshunt)/Rshunt); return voltage; } ``` #### 充放电状态判断逻辑 考虑到实际应用场景中可能存在的噪声干扰等因素影响到判定精准度,建议引入滤波机制平滑瞬态波动后再做进一步分析比较。一般做法是在每次获得新的样本之后更新移动平均窗口内的累积求和,并据此调整输出指示灯颜色变化或者触发声响警报等功能响应动作。 另外值得注意的是,针对不同型号规格的产品特性差异(比如额定容量大小),还需要预先校准好对应关系曲线以便更准确地映射百分比形式表示剩余可用能量比例[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝影影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值