基于STM32与ADC的锂电池电量监测系统设计
1. 锂电池电量监测为什么需要STM32和ADC做嵌入式开发的朋友应该都遇到过这样的需求设备用锂电池供电需要实时显示剩余电量。比如手持设备、智能家居控制器或者无人机电量显示都是刚需功能。但锂电池的特性决定了直接测量电量并不简单——它不像水杯里的水看一眼就知道还剩多少。这里就轮到STM32和ADC登场了。STM32的ADC模数转换器模块能把模拟电压信号转换成数字值而锂电池的电压和电量在大部分区间是近似线性的关系。我做过十几个类似项目实测用电压推算电量的方法在80%场景下误差不超过5%完全能满足一般需求。不过要注意几个关键点首先STM32的ADC输入电压范围通常是0-3.3V部分型号支持0-VDDA而3节锂电池满电时电压能达到12.6V4.2V×3直接接上去肯定会烧芯片。其次电量计算需要考虑电池放电曲线非线性段后面我会具体讲怎么处理。2. 硬件设计分压电路是关键2.1 分压电阻选型实战先看一个我实际项目中的电路设计案例。假设使用3节18650锂电池串联标称电压11.1V我们需要把电压降到ADC可接受的范围内。经典的分压电路公式是Vout Vin × R2 / (R1 R2)根据经验锂电池放电截止电压一般是3V×39V满电电压4.2V×312.6V。我推荐选用10kΩ和47kΩ的电阻组合这样最低电压时9V × 10k/(10k47k) ≈ 1.579V最高电压时12.6V × 10k/(10k47k) ≈ 2.211V这个范围完全落在STM32的ADC量程内0-3.3V还留有一定余量。电阻功率建议选择1/4W以上我常用的是0805封装的贴片电阻。2.2 硬件设计注意事项在实际布线时有几点容易踩坑分压电路要尽量靠近ADC引脚避免长走线引入干扰在ADC输入端加一个0.1uF的滤波电容我习惯用X7R材质的陶瓷电容如果环境干扰大可以考虑加入RC低通滤波比如1kΩ1uF组合电阻精度建议1%普通5%精度的电阻会导致明显误差曾经有个项目因为用了5%精度的电阻电量显示跳变严重换成1%精度后立即稳定了。3. CubeMX配置详解3.1 ADC参数设置打开CubeMX后按以下步骤配置以STM32F103为例在Pinout界面启用ADC1/ADC2选择对应通道如PC0对应ADC1_IN10在Configuration标签页设置Resolution12Bits精度够用Scan Conversion ModeDisabled单通道不需要扫描Continuous Conversion ModeEnabled持续转换DMA Settings根据需求启用高频率采样建议开启重点看时钟配置ADC时钟不要超过14MHzF1系列我一般设为12MHz。时钟太快会导致采样精度下降这个坑我踩过。3.2 校准与验证配置完成后生成代码但先别急着写应用逻辑。建议先做硬件验证HAL_ADCEx_Calibration_Start(hadc1); // 先校准 uint32_t raw HAL_ADC_GetValue(hadc1); float voltage raw * 3.3f / 4095.0f; // 转换为电压用万用表测量实际电压与代码读取值对比。如果误差超过1%需要检查分压电阻精度或考虑软件校准。4. 软件实现与电量换算4.1 基础电压采集代码下面是我优化过的采集函数加入了多次采样平均#define SAMPLE_TIMES 16 // 采样次数 uint16_t Get_Battery_Voltage(void) { uint32_t sum 0; for(int i0; iSAMPLE_TIMES; i){ HAL_ADC_Start(hadc1); if(HAL_OK HAL_ADC_PollForConversion(hadc1, 10)){ sum HAL_ADC_GetValue(hadc1); } HAL_Delay(1); } float adc_voltage (sum * 3.3f) / (SAMPLE_TIMES * 4095.0f); float battery_voltage adc_voltage * (10.0f 47.0f) / 10.0f; // 反推电池电压 return (uint16_t)(battery_voltage * 100); // 返回mV单位值 }4.2 电量百分比计算进阶版原始文章的线性转换在中间段是准确的但在电量很低或很高时误差较大。这里分享我的改进算法uint8_t Calculate_Percentage(float voltage) { // 3节锂电池电压范围 9V-12.6V if(voltage 12.3f) return 100; // 满电 if(voltage 9.5f) return 0; // 亏电 // 分段线性化处理 float percentage; if(voltage 11.4f) { // 高电量区 percentage 80.0f (voltage - 11.4f) * (20.0f / 0.9f); } else { // 主要放电区 percentage (voltage - 9.5f) * (80.0f / 1.9f); } return (uint8_t)(percentage 100 ? 100 : percentage); }这个算法通过分段处理在高电量和低电量区间采用不同斜率更贴近锂电池的实际放电曲线。实测误差可以控制在3%以内。5. 工程优化与抗干扰设计5.1 软件滤波算法除了硬件滤波软件层面也需要处理噪声。我常用的是滑动平均滤波结合中值滤波#define FILTER_SIZE 10 typedef struct { float buffer[FILTER_SIZE]; uint8_t index; } Filter_t; float Filter_Value(Filter_t* filter, float new_val) { filter-buffer[filter-index] new_val; if(filter-index FILTER_SIZE) filter-index 0; // 中值滤波 float temp[FILTER_SIZE]; memcpy(temp, filter-buffer, sizeof(temp)); bubble_sort(temp, FILTER_SIZE); // 实现排序算法 // 取中间3个值做平均 return (temp[FILTER_SIZE/2-1] temp[FILTER_SIZE/2] temp[FILTER_SIZE/21]) / 3.0f; }5.2 低功耗优化对于电池供电设备ADC采集也要考虑功耗降低采样频率非必要不连续采样使用HAL_ADC_Stop()在采集后关闭ADC对于休眠设备可以配置唤醒后采样我曾经通过优化采样策略将某设备的待机时间从3天延长到2周。关键代码void Enter_LowPower_Mode(void) { HAL_ADC_Stop(hadc1); HAL_ADC_DeInit(hadc1); __HAL_RCC_ADC1_CLK_DISABLE(); // 关闭ADC时钟 HAL_SuspendTick(); // 暂停系统滴答 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); SystemClock_Config(); // 唤醒后重新初始化时钟 }6. 显示与用户交互6.1 OLED电量显示实现用OLED显示电量比简单的LED指示灯更直观。基于SSD1306驱动的实现示例void Show_Battery_Info(uint16_t voltage, uint8_t percentage) { char str[20]; OLED_Clear(); // 绘制电池图标 OLED_DrawRectangle(5, 5, 30, 15); OLED_DrawRectangle(35, 8, 38, 12); // 填充电量根据百分比 uint8_t width (uint16_t)25 * percentage / 100; OLED_FillRectangle(7, 7, 7width, 13); // 显示数值 sprintf(str, %d.%dV, voltage/100, voltage%100); OLED_ShowString(45, 5, str, 16); sprintf(str, %d%%, percentage); OLED_ShowString(45, 25, str, 16); OLED_Refresh(); }6.2 电量预警功能当电量低时需要提醒用户这是我常用的多级预警方案void Check_Battery_Level(uint8_t percent) { static uint8_t last_warn 100; if(percent 20 last_warn 20) { Beep(1000, 200); // 短促提示音 last_warn 20; } else if(percent 10 last_warn 10) { Beep(1000, 500); // 长提示音 last_warn 10; } else if(percent 5) { // 进入紧急模式 Save_User_Data(); // 保存数据 Enter_DeepSleep(); // 进入深度休眠 } }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2452725.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!