本文分享一个嵌入式设备中常用的电池状态监测函数,通过AD采样获取电池电压,经滤波和计算后得到电量百分比,并在OLED屏幕上动态显示电量图标及百分比数值。适用于STM32等单片机的电池管理模块,代码可直接移植使用。
AD 采样→电压计算→容量转换→OLED 显示

- 开机时:PB12 是低电平、PB13 是高电平 → 触发 "AD 采样→电量显示" 流程,设备正常检测、显示电池电量;
- 关机时:PB12 变为高电平、PB13 变为低电平 → 关闭 "AD 采样→电量显示" 流程,设备不再检测电量,降低功耗;
- 上电初始化:刚通电时,PB12 初始化为低电平、PB13 初始化为高电平 → 直接进入 "开机" 模式,确保电量检测能工作。
- 通过AD读取电压值,转化为电压
若 AD 为 12 位(最大 4095),参考电压 3.3V,且无分压电路
实际电压 = (ADValue / 4095.0) × 3.3
2,由于电压值不稳定,设计进行滤波
循环多次(如 3000 次)调用AD_GetValue(),累加采样值后取平均值。
3,动态显示
计算电池的百分比
Battery_Capacity=(ADValue-3276)*100/819;
(ADValue - 3276):计算当前 AD 值与最低电压 AD 值的差值,代表当前电压在有效范围内的偏移量
除以819:将偏移量归一化到 0-1 的范围,得到相对满电的比例
乘以100:转换为百分比形式
当 ADValue=3276 时,计算结果为 0%(电池放空)
当 ADValue=3276+819=4095 时,计算结果为 100%(电池满电)
4.OLED 显示逻辑设计
-
显示内容:电量百分比(数字 +%)、动态电池图标。
-
分情况处理 :
- 电量 100%:显示完整电池图标,直接输出 "100%"。
- 电量 10%~99%:显示基础图标,按比例清除部分区域(模拟电量条),如 50% 时清除一半区域。
- 电量<10%:显示基础图标,清除大部分区域(突出低电量),调整数字显示位置避免残留。
uint16_t ADValue; //AD采样原始数据
float VBAT; //计算后的电池电压
int Battery_Capacity; //电池容量百分比(0-100%)void Show_Battery(void)
{
int sum=0;
//AD采样滤波(3000次采样平均,减少噪声)
for(int i=0;i<3000;i++)
{
ADValue=AD_GetValue(); //得到AD值
sum+=ADValue;} ADValue=sum/3000; //平均滤波后的AD值 //计算电池的电压 VBAT=(float)ADValue/4095*3.3; //计算电量百分比(线性转换) Battery_Capacity=(ADValue-3276)*100/819; if(Battery_Capacity<0)Battery_Capacity=0; //OLED_ShowNum(64,0,ADValue,4,OLED_6X8); //OLED_Printf(64,8,OLED_6X8,"VBAT:%.2f",VBAT); OLED_ShowNum(85,4,Battery_Capacity,3,OLED_6X8); OLED_ShowChar(103,4,'%',OLED_6X8); //根据电池的动态显示电池的图标 if(Battery_Capacity==100)OLED_ShowImage(110,0,16,16,Battery); else if(Battery_Capacity>=10&&Battery_Capacity<100) { OLED_ShowImage(110,0,16,16,Battery); OLED_ClearArea((112+Battery_Capacity/10),5,(10-Battery_Capacity/10),6); OLED_ClearArea(85,4,6,8); } else { OLED_ShowImage(110,0,16,16,Battery); OLED_ClearArea(112,5,10,6); OLED_ClearArea(85,4,12,8); }
}
void Show_Clock_UI(void)
{
MyRTC_ReadTime();
OLED_Printf(0,0,OLED_6X8,"%d-%d-%d",MyRTC_Time[0],MyRTC_Time[1],MyRTC_Time[2]);
OLED_Printf(16,16,OLED_12X24,"%02d:%02d:%02d",MyRTC_Time[3],MyRTC_Time[4],MyRTC_Time[5]);
OLED_ShowString(0,48,"菜单",OLED_8X16);
OLED_ShowString(96,48,"设置",OLED_8X16);Show_Battery();
}