STC8H 锂电池电量检测程序

#include "STC8H.h"
#include <stdio.h>
#include <math.h>

// 定义ADC通道(根据实际连接修改)
#define BAT_ADC_CHANNEL 0

// 电池参数
#define FULL_VOLTAGE 4.2f    // 满电电压(4.2V)
#define EMPTY_VOLTAGE 3.3f    // 空电电压(3.3V)
#define VOLTAGE_DIVIDER_RATIO 2.0f // 分压电阻比例 (R1+R2)/R2

// 电量状态
typedef enum {
    BATTERY_EMPTY = 0,
    BATTERY_LOW,
    BATTERY_MEDIUM,
    BATTERY_HIGH,
    BATTERY_FULL
} BatteryStatus;

// 全局变量
float battery_voltage = 0.0f;
int battery_percentage = 0;
int is_charging = 0;          // 充电状态标志
float last_valid_voltage = 3.7f; // 上次有效电压值

// 初始化ADC
void ADC_Init() {
    P1M0 &= ~(1 << BAT_ADC_CHANNEL);  // 设置P1.x为高阻输入
    P1M1 |= (1 << BAT_ADC_CHANNEL);
    
    ADCCFG = 0x0F;           // 设置ADC时钟为系统时钟/2/16
    ADC_CONTR = 0x80;        // 打开ADC电源
    __nop(); __nop(); __nop(); __nop(); // 等待ADC电源稳定
}

// 读取ADC值
unsigned int ADC_Read(unsigned char channel) {
    ADC_CONTR = 0x80 | channel; // 选择通道并启动ADC
    __nop(); __nop(); __nop(); __nop(); // 等待转换完成
    while (!(ADC_CONTR & 0x20)); // 等待ADC完成
    ADC_CONTR &= ~0x20;      // 清除完成标志
    return (ADC_RES << 8) | ADC_RESL; // 返回10位ADC结果
}

// 获取电池电压(带滤波)
float Get_Battery_Voltage() {
    unsigned int adc_sum = 0;
    float voltage;
    int i;
    
    // 多次采样取平均
    for (i = 0; i < 16; i++) {
        adc_sum += ADC_Read(BAT_ADC_CHANNEL);
        // 短延时
        for (volatile int j = 0; j < 100; j++);
    }
    
    // 计算电压值
    voltage = (adc_sum / 16.0f) * (5.0f / 1024.0f) * VOLTAGE_DIVIDER_RATIO;
    
    return voltage;
}

// 更新电池电量百分比
void Update_Battery_Percentage() {
    float current_voltage = Get_Battery_Voltage();
    
    // 简单的抗干扰处理:如果变化过大,则认为是干扰
    if (fabs(current_voltage - battery_voltage) > 0.5f) {
        current_voltage = battery_voltage; // 忽略这次读数
    }
    
    // 充电状态下可以更新电压
    if (is_charging) {
        battery_voltage = current_voltage;
        last_valid_voltage = current_voltage;
    } 
    // 非充电状态下,电压只能下降
    else {
        if (current_voltage < last_valid_voltage) {
            battery_voltage = current_voltage;
            last_valid_voltage = current_voltage;
        }
    }
    
    // 计算电量百分比 (线性估算)
    if (battery_voltage >= FULL_VOLTAGE) {
        battery_percentage = 100;
    } else if (battery_voltage <= EMPTY_VOLTAGE) {
        battery_percentage = 0;
    } else {
        battery_percentage = (int)((battery_voltage - EMPTY_VOLTAGE) / 
                                 (FULL_VOLTAGE - EMPTY_VOLTAGE) * 100.0f);
        battery_percentage = battery_percentage > 100 ? 100 : battery_percentage;
    }
}

// 获取电池状态
BatteryStatus Get_Battery_Status() {
    if (battery_percentage <= 10) return BATTERY_EMPTY;
    if (battery_percentage <= 30) return BATTERY_LOW;
    if (battery_percentage <= 70) return BATTERY_MEDIUM;
    if (battery_percentage < 100) return BATTERY_HIGH;
    return BATTERY_FULL;
}

// 检测充电状态(根据实际硬件连接修改)
void Check_Charging_Status() {
    // 这里需要根据实际硬件连接来检测充电状态
    // 例如通过检测充电IC的状态引脚或USB连接状态
    // 这里只是示例,实际需要修改
    is_charging = 0; // 假设默认不在充电
}

void main() {
    // 初始化
    ADC_Init();
    
    // 初始读取
    battery_voltage = Get_Battery_Voltage();
    last_valid_voltage = battery_voltage;
    Update_Battery_Percentage();
    
    while (1) {
        // 检测充电状态
        Check_Charging_Status();
        
        // 更新电池信息
        Update_Battery_Percentage();
        
        // 这里可以添加显示电量或其他处理
        // ...
        
        // 延时一段时间后再次检测
        Delay_ms(1000); // 需要实现延时函数
    }
}

// 简单的延时函数
void Delay_ms(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++) {
        for (j = 0; j < 1000; j++) {
            __nop();
        }
    }
}

程序说明

  1. ADC初始化:配置ADC通道和参数,用于读取电池电压。

  2. 电压读取与滤波

    • 采用16次采样取平均的方法减少随机噪声

    • 通过分压电阻比例计算实际电池电压

  3. 抗干扰处理

    • 如果当前电压与上次电压差值过大(>0.5V),则认为是干扰,忽略本次读数

    • 非充电状态下,电压只能下降不能上升

  4. 电量计算

    • 采用线性估算方法,根据满电和空电电压计算百分比

    • 电量百分比限制在0-100%范围内

  5. 充电状态检测

    • 需要根据实际硬件连接实现充电状态检测

使用注意事项

  1. 需要根据实际硬件修改:

    • ADC通道号

    • 分压电阻比例(VOLTAGE_DIVIDER_RATIO)

    • 充电状态检测逻辑

  2. 可以通过修改FULL_VOLTAGE和EMPTY_VOLTAGE来适应不同的锂电池特性

  3. 如需更精确的电量检测,可以考虑:

    • 使用库仑计芯片

    • 实现更复杂的电池放电曲线算法

    • 增加温度补偿

  4. 延时函数需要根据实际时钟频率调整

这个程序提供了基本的电池电量检测功能,并确保了在非充电状态下电量只降不升的特性,同时具有一定的抗干扰能力。

posted @ 2025-04-16 16:40  FBshark  阅读(365)  评论(0)    收藏  举报