BLOG8
跳转至

电池管理系统(BMS)设计实战

概述

电池管理系统(Battery Management System, BMS)是电池供电设备的核心组件,负责监测电池状态、控制充放电过程、保护电池安全、延长电池寿命。本教程将通过实战项目,深入讲解BMS的设计与实现。

什么是BMS

BMS是一个智能电子系统,用于管理可充电电池组,主要功能包括:

  1. 状态监测:
  2. 电压监测(单体/总压)
  3. 电流监测(充电/放电)
  4. 温度监测(多点测温)
  5. 电量估算(SOC计算)

  6. 安全保护:

  7. 过充保护
  8. 过放保护
  9. 过流保护
  10. 过温保护
  11. 短路保护

  12. 充放电控制:

  13. 充电管理
  14. 放电管理
  15. 预充电控制
  16. 充电均衡

  17. 通信接口:

  18. 与主控通信
  19. 数据上报
  20. 参数配置
  21. 故障诊断

BMS的重要性

为什么需要BMS:

1. 安全性
   - 防止电池过充/过放
   - 避免热失控
   - 防止短路起火
   - 保护人身安全

2. 可靠性
   - 延长电池寿命
   - 提高系统稳定性
   - 减少故障率
   - 降低维护成本

3. 性能优化
   - 准确的电量显示
   - 优化充放电策略
   - 提高能量利用率
   - 改善用户体验

4. 法规要求
   - 满足安全认证
   - 符合行业标准
   - 通过质量检测
   - 获得市场准入

应用场景

  • 消费电子:手机、平板、笔记本电脑
  • 电动工具:电钻、电锯、割草机
  • 电动车辆:电动自行车、电动汽车
  • 储能系统:家庭储能、UPS电源
  • 便携设备:移动电源、无人机

第一部分:BMS系统架构

硬件架构

典型BMS硬件组成:

BMS硬件架构:

┌─────────────────────────────────────────────────────┐
│                    主控MCU                           │
│  (STM32F103 / ESP32 / nRF52)                       │
│  - 核心控制逻辑                                      │
│  - 算法计算                                          │
│  - 通信管理                                          │
└──────┬──────────┬──────────┬──────────┬────────────┘
       │          │          │          │
   ┌───▼───┐  ┌──▼───┐  ┌──▼───┐  ┌──▼────┐
   │电压监测│  │电流监测│  │温度监测│  │充放电控制│
   │芯片    │  │电路    │  │电路    │  │MOSFET   │
   │(AFE)  │  │(霍尔)  │  │(NTC)  │  │驱动     │
   └───┬───┘  └──┬───┘  └──┬───┘  └──┬────┘
       │          │          │          │
   ┌───▼──────────▼──────────▼──────────▼────┐
   │              电池组                       │
   │  Cell1  Cell2  Cell3  ...  CellN        │
   └──────────────────────────────────────────┘

关键组件:
1. 主控MCU:STM32F103C8T6
2. 电压监测:BQ76920 (3-5串锂电池)
3. 电流检测:ACS712 (霍尔传感器)
4. 温度监测:NTC热敏电阻 × 2
5. 充放电控制:N-MOSFET × 2
6. 通信接口:UART/CAN/I2C

软件架构

BMS软件模块:

/**
 * @file    bms_architecture.h
 * @brief   BMS软件架构定义
 */

#ifndef BMS_ARCHITECTURE_H
#define BMS_ARCHITECTURE_H

#include <stdint.h>
#include <stdbool.h>

/**
 * @brief  BMS系统状态
 */
typedef enum {
    BMS_STATE_INIT = 0,        // 初始化
    BMS_STATE_IDLE,            // 空闲
    BMS_STATE_CHARGING,        // 充电中
    BMS_STATE_DISCHARGING,     // 放电中
    BMS_STATE_BALANCING,       // 均衡中
    BMS_STATE_FAULT,           // 故障
    BMS_STATE_SLEEP            // 休眠
} BMS_State_t;

/**
 * @brief  电池参数
 */
typedef struct {
    uint16_t cell_voltage[5];  // 单体电压 (mV)
    uint16_t pack_voltage;     // 总电压 (mV)
    int16_t  current;          // 电流 (mA, 正=充电, 负=放电)
    int16_t  temperature[2];   // 温度 (0.1°C)
    uint8_t  soc;              // 电量百分比 (0-100%)
    uint8_t  soh;              // 健康度 (0-100%)
    uint32_t capacity_mah;     // 剩余容量 (mAh)
} BMS_BatteryParams_t;

/**
 * @brief  保护状态
 */
typedef struct {
    bool overcharge;           // 过充保护
    bool overdischarge;        // 过放保护
    bool overcurrent_charge;   // 充电过流
    bool overcurrent_discharge;// 放电过流
    bool overtemperature;      // 过温保护
    bool undertemperature;     // 低温保护
    bool short_circuit;        // 短路保护
    bool cell_imbalance;       // 单体不均衡
} BMS_Protection_t;

/**
 * @brief  BMS配置参数
 */
typedef struct {
    uint16_t cell_overvoltage_mv;      // 单体过充电压 (mV)
    uint16_t cell_undervoltage_mv;     // 单体过放电压 (mV)
    uint16_t charge_overcurrent_ma;    // 充电过流阈值 (mA)
    uint16_t discharge_overcurrent_ma; // 放电过流阈值 (mA)
    int16_t  overtemperature_c;        // 过温阈值 (°C)
    int16_t  undertemperature_c;       // 低温阈值 (°C)
    uint16_t balance_voltage_diff_mv;  // 均衡电压差 (mV)
    uint32_t design_capacity_mah;      // 设计容量 (mAh)
} BMS_Config_t;

/**
 * @brief  BMS主数据结构
 */
typedef struct {
    BMS_State_t state;                 // 系统状态
    BMS_BatteryParams_t battery;       // 电池参数
    BMS_Protection_t protection;       // 保护状态
    BMS_Config_t config;               // 配置参数
    uint32_t timestamp_ms;             // 时间戳
    uint32_t cycle_count;              // 循环次数
} BMS_Handle_t;

#endif // BMS_ARCHITECTURE_H

第二部分:电量计算算法

SOC (State of Charge) 计算

SOC表示电池的剩余电量百分比,是BMS最重要的功能之一。

常用SOC计算方法:

SOC计算方法对比:

1. 开路电压法 (OCV)
   优点:简单、无需电流传感器
   缺点:需要静置、精度低
   适用:低成本应用

2. 安时积分法 (Coulomb Counting)
   优点:实时、精度高
   缺点:累积误差、需要校准
   适用:大多数应用

3. 卡尔曼滤波法
   优点:精度最高、自适应
   缺点:计算复杂、资源消耗大
   适用:高端应用

4. 混合算法
   优点:综合优势、精度高
   缺点:实现复杂
   适用:推荐方案

安时积分法实现

/**
 * @file    soc_calculation.c
 * @brief   SOC计算算法实现
 */

#include "bms_architecture.h"
#include <math.h>

/**
 * @brief  SOC计算器数据结构
 */
typedef struct {
    float soc_percent;              // 当前SOC (%)
    float remaining_capacity_mah;   // 剩余容量 (mAh)
    float full_capacity_mah;        // 满充容量 (mAh)
    uint32_t last_update_ms;        // 上次更新时间
    bool initialized;               // 是否已初始化
} SOC_Calculator_t;

static SOC_Calculator_t soc_calc = {0};

/**
 * @brief  初始化SOC计算器
 * @param  initial_soc: 初始SOC (%)
 * @param  capacity_mah: 电池容量 (mAh)
 */
void SOC_Init(float initial_soc, float capacity_mah) {
    soc_calc.soc_percent = initial_soc;
    soc_calc.full_capacity_mah = capacity_mah;
    soc_calc.remaining_capacity_mah = capacity_mah * initial_soc / 100.0f;
    soc_calc.last_update_ms = HAL_GetTick();
    soc_calc.initialized = true;

    printf("SOC初始化: %.1f%%, 容量: %.0f mAh\n", 
           initial_soc, capacity_mah);
}

/**
 * @brief  通过OCV估算初始SOC
 * @param  voltage_mv: 开路电压 (mV)
 * @retval 估算的SOC (%)
 */
float SOC_EstimateFromOCV(uint16_t voltage_mv) {
    // 锂电池OCV-SOC曲线(3.7V标称电压)
    // 这是一个简化的线性近似,实际应使用查表法

    const uint16_t voltage_100 = 4200;  // 100% SOC电压
    const uint16_t voltage_0   = 3000;  // 0% SOC电压

    if (voltage_mv >= voltage_100) {
        return 100.0f;
    } else if (voltage_mv <= voltage_0) {
        return 0.0f;
    }

    // 线性插值
    float soc = (float)(voltage_mv - voltage_0) / 
                (voltage_100 - voltage_0) * 100.0f;

    return soc;
}

/**
 * @brief  更新SOC(安时积分法)
 * @param  current_ma: 当前电流 (mA, 正=充电, 负=放电)
 * @param  timestamp_ms: 当前时间戳 (ms)
 */
void SOC_Update(int16_t current_ma, uint32_t timestamp_ms) {
    if (!soc_calc.initialized) {
        printf("错误:SOC未初始化\n");
        return;
    }

    // 计算时间差 (小时)
    uint32_t delta_ms = timestamp_ms - soc_calc.last_update_ms;
    float delta_hours = delta_ms / 3600000.0f;

    // 计算电量变化 (mAh)
    // Q = I × t
    float delta_capacity = current_ma * delta_hours;

    // 更新剩余容量
    soc_calc.remaining_capacity_mah += delta_capacity;

    // 限制范围
    if (soc_calc.remaining_capacity_mah > soc_calc.full_capacity_mah) {
        soc_calc.remaining_capacity_mah = soc_calc.full_capacity_mah;
    } else if (soc_calc.remaining_capacity_mah < 0) {
        soc_calc.remaining_capacity_mah = 0;
    }

    // 计算SOC百分比
    soc_calc.soc_percent = soc_calc.remaining_capacity_mah / 
                           soc_calc.full_capacity_mah * 100.0f;

    // 更新时间戳
    soc_calc.last_update_ms = timestamp_ms;
}

/**
 * @brief  获取当前SOC
 * @retval SOC百分比 (0-100%)
 */
float SOC_GetPercent(void) {
    return soc_calc.soc_percent;
}

/**
 * @brief  获取剩余容量
 * @retval 剩余容量 (mAh)
 */
float SOC_GetRemainingCapacity(void) {
    return soc_calc.remaining_capacity_mah;
}

/**
 * @brief  SOC校准(充满时)
 */
void SOC_CalibrateFullCharge(void) {
    soc_calc.soc_percent = 100.0f;
    soc_calc.remaining_capacity_mah = soc_calc.full_capacity_mah;
    printf("SOC校准:充满 100%%\n");
}

/**
 * @brief  SOC校准(放空时)
 */
void SOC_CalibrateEmpty(void) {
    soc_calc.soc_percent = 0.0f;
    soc_calc.remaining_capacity_mah = 0.0f;
    printf("SOC校准:放空 0%%\n");
}

/**
 * @brief  混合SOC算法(安时积分 + OCV校准)
 * @param  current_ma: 电流 (mA)
 * @param  voltage_mv: 电压 (mV)
 * @param  timestamp_ms: 时间戳 (ms)
 */
void SOC_UpdateHybrid(int16_t current_ma, uint16_t voltage_mv, 
                      uint32_t timestamp_ms) {
    // 1. 安时积分更新
    SOC_Update(current_ma, timestamp_ms);

    // 2. 静置时使用OCV校准
    static uint32_t idle_start_ms = 0;
    const uint32_t IDLE_TIME_MS = 300000;  // 5分钟静置

    if (abs(current_ma) < 50) {  // 电流小于50mA视为静置
        if (idle_start_ms == 0) {
            idle_start_ms = timestamp_ms;
        } else if (timestamp_ms - idle_start_ms > IDLE_TIME_MS) {
            // 静置足够长时间,使用OCV校准
            float ocv_soc = SOC_EstimateFromOCV(voltage_mv);

            // 加权融合
            float weight_ocv = 0.3f;  // OCV权重
            float weight_cc = 0.7f;   // 安时积分权重

            soc_calc.soc_percent = soc_calc.soc_percent * weight_cc + 
                                   ocv_soc * weight_ocv;

            soc_calc.remaining_capacity_mah = soc_calc.soc_percent / 100.0f *
                                              soc_calc.full_capacity_mah;

            printf("SOC混合校准: CC=%.1f%%, OCV=%.1f%%, 融合=%.1f%%\n",
                   soc_calc.soc_percent * weight_cc / (weight_cc + weight_ocv),
                   ocv_soc,
                   soc_calc.soc_percent);

            idle_start_ms = 0;  // 重置静置计时
        }
    } else {
        idle_start_ms = 0;  // 有电流,重置静置计时
    }
}

第三部分:充放电控制

充电管理

充电阶段:

锂电池充电曲线(CC-CV):

电压
  │
4.2V├─────────────────────────┐
  │                           │ CV恒压阶段
  │                           │ (电流逐渐减小)
  │                           │
3.7V├──────────────┐          │
  │                │          │
  │  CC恒流阶段    │          │
  │  (恒定电流)    │          │
  │                │          │
3.0V├────────────────┴──────────┴─────→ 时间
    预充电  恒流充电(CC)  恒压充电(CV)  充满

充电阶段:
1. 预充电 (Pre-charge)
   - 条件:电压 < 3.0V
   - 电流:0.1C
   - 目的:激活深度放电的电池

2. 恒流充电 (CC)
   - 条件:3.0V < 电压 < 4.2V
   - 电流:0.5C - 1C
   - 目的:快速充电

3. 恒压充电 (CV)
   - 条件:电压 = 4.2V
   - 电流:逐渐减小
   - 目的:充满电池

4. 充电完成
   - 条件:电流 < 0.05C
   - 动作:停止充电

充电控制实现

/**
 * @file    charge_control.c
 * @brief   充电控制实现
 */

#include "bms_architecture.h"

/**
 * @brief  充电状态
 */
typedef enum {
    CHARGE_STATE_IDLE = 0,     // 空闲
    CHARGE_STATE_PRECHARGE,    // 预充电
    CHARGE_STATE_CC,           // 恒流充电
    CHARGE_STATE_CV,           // 恒压充电
    CHARGE_STATE_COMPLETE,     // 充电完成
    CHARGE_STATE_FAULT         // 故障
} ChargeState_t;

/**
 * @brief  充电控制器
 */
typedef struct {
    ChargeState_t state;       // 充电状态
    uint32_t charge_start_ms;  // 充电开始时间
    uint32_t state_start_ms;   // 当前状态开始时间
    float accumulated_mah;     // 累积充电量
} ChargeController_t;

static ChargeController_t charge_ctrl = {0};

/**
 * @brief  充电参数配置
 */
#define PRECHARGE_VOLTAGE_MV    3000   // 预充电电压阈值
#define CC_VOLTAGE_MV           4200   // 恒流充电目标电压
#define CV_VOLTAGE_MV           4200   // 恒压充电电压
#define PRECHARGE_CURRENT_MA    200    // 预充电电流 (0.1C for 2000mAh)
#define CC_CURRENT_MA           1000   // 恒流充电电流 (0.5C for 2000mAh)
#define CV_CUTOFF_CURRENT_MA    100    // 恒压截止电流 (0.05C)
#define CHARGE_TIMEOUT_MS       14400000  // 充电超时 (4小时)

/**
 * @brief  初始化充电控制器
 */
void Charge_Init(void) {
    charge_ctrl.state = CHARGE_STATE_IDLE;
    charge_ctrl.charge_start_ms = 0;
    charge_ctrl.state_start_ms = 0;
    charge_ctrl.accumulated_mah = 0;

    printf("充电控制器初始化完成\n");
}

/**
 * @brief  开始充电
 */
void Charge_Start(void) {
    charge_ctrl.state = CHARGE_STATE_PRECHARGE;
    charge_ctrl.charge_start_ms = HAL_GetTick();
    charge_ctrl.state_start_ms = HAL_GetTick();
    charge_ctrl.accumulated_mah = 0;

    printf("开始充电\n");
}

/**
 * @brief  停止充电
 */
void Charge_Stop(void) {
    charge_ctrl.state = CHARGE_STATE_IDLE;

    // 关闭充电MOSFET
    HAL_GPIO_WritePin(CHARGE_MOSFET_GPIO, CHARGE_MOSFET_PIN, GPIO_PIN_RESET);

    printf("停止充电\n");
}

/**
 * @brief  充电状态机
 * @param  bms: BMS句柄
 */
void Charge_StateMachine(BMS_Handle_t* bms) {
    uint16_t voltage = bms->battery.pack_voltage;
    int16_t current = bms->battery.current;
    uint32_t now_ms = HAL_GetTick();

    switch (charge_ctrl.state) {
        case CHARGE_STATE_IDLE:
            // 空闲状态,等待开始充电
            break;

        case CHARGE_STATE_PRECHARGE:
            printf("预充电阶段: 电压=%d mV, 电流=%d mA\n", voltage, current);

            // 设置预充电电流
            Charge_SetCurrent(PRECHARGE_CURRENT_MA);

            // 检查是否进入恒流充电
            if (voltage >= PRECHARGE_VOLTAGE_MV) {
                charge_ctrl.state = CHARGE_STATE_CC;
                charge_ctrl.state_start_ms = now_ms;
                printf("进入恒流充电阶段\n");
            }

            // 超时检查
            if (now_ms - charge_ctrl.state_start_ms > 1800000) {  // 30分钟
                printf("预充电超时\n");
                charge_ctrl.state = CHARGE_STATE_FAULT;
            }
            break;

        case CHARGE_STATE_CC:
            printf("恒流充电阶段: 电压=%d mV, 电流=%d mA\n", voltage, current);

            // 设置恒流充电电流
            Charge_SetCurrent(CC_CURRENT_MA);

            // 检查是否进入恒压充电
            if (voltage >= CC_VOLTAGE_MV) {
                charge_ctrl.state = CHARGE_STATE_CV;
                charge_ctrl.state_start_ms = now_ms;
                printf("进入恒压充电阶段\n");
            }

            // 超时检查
            if (now_ms - charge_ctrl.charge_start_ms > CHARGE_TIMEOUT_MS) {
                printf("充电超时\n");
                charge_ctrl.state = CHARGE_STATE_FAULT;
            }
            break;

        case CHARGE_STATE_CV:
            printf("恒压充电阶段: 电压=%d mV, 电流=%d mA\n", voltage, current);

            // 设置恒压充电电压
            Charge_SetVoltage(CV_VOLTAGE_MV);

            // 检查是否充电完成
            if (current < CV_CUTOFF_CURRENT_MA) {
                charge_ctrl.state = CHARGE_STATE_COMPLETE;
                charge_ctrl.state_start_ms = now_ms;
                printf("充电完成\n");

                // SOC校准为100%
                SOC_CalibrateFullCharge();
            }

            // 超时检查
            if (now_ms - charge_ctrl.charge_start_ms > CHARGE_TIMEOUT_MS) {
                printf("充电超时\n");
                charge_ctrl.state = CHARGE_STATE_FAULT;
            }
            break;

        case CHARGE_STATE_COMPLETE:
            // 充电完成,停止充电
            Charge_Stop();
            break;

        case CHARGE_STATE_FAULT:
            // 故障状态,停止充电
            Charge_Stop();
            printf("充电故障\n");
            break;
    }
}

/**
 * @brief  设置充电电流(硬件相关)
 * @param  current_ma: 目标电流 (mA)
 */
void Charge_SetCurrent(uint16_t current_ma) {
    // 这里需要根据实际硬件实现
    // 例如:通过DAC或PWM控制充电芯片的电流设置引脚

    // 示例:使用DAC输出控制电流
    // DAC_value = current_ma / 1000.0 * 4095 / 3.3;
    // HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, DAC_value);

    printf("设置充电电流: %d mA\n", current_ma);
}

/**
 * @brief  设置充电电压(硬件相关)
 * @param  voltage_mv: 目标电压 (mV)
 */
void Charge_SetVoltage(uint16_t voltage_mv) {
    // 这里需要根据实际硬件实现
    // 例如:通过DAC或PWM控制充电芯片的电压设置引脚

    printf("设置充电电压: %d mV\n", voltage_mv);
}

/**
 * @brief  获取充电状态
 * @retval 充电状态
 */
ChargeState_t Charge_GetState(void) {
    return charge_ctrl.state;
}

放电管理

/**
 * @file    discharge_control.c
 * @brief   放电控制实现
 */

/**
 * @brief  放电状态
 */
typedef enum {
    DISCHARGE_STATE_IDLE = 0,      // 空闲
    DISCHARGE_STATE_NORMAL,        // 正常放电
    DISCHARGE_STATE_LIMITED,       // 限流放电
    DISCHARGE_STATE_CUTOFF,        // 截止放电
    DISCHARGE_STATE_FAULT          // 故障
} DischargeState_t;

/**
 * @brief  放电控制器
 */
typedef struct {
    DischargeState_t state;        // 放电状态
    uint32_t discharge_start_ms;   // 放电开始时间
    float accumulated_mah;         // 累积放电量
    uint16_t current_limit_ma;     // 电流限制
} DischargeController_t;

static DischargeController_t discharge_ctrl = {0};

/**
 * @brief  放电参数配置
 */
#define DISCHARGE_CUTOFF_VOLTAGE_MV  3000   // 放电截止电压
#define DISCHARGE_MAX_CURRENT_MA     3000   // 最大放电电流
#define DISCHARGE_LIMIT_VOLTAGE_MV   3200   // 限流电压阈值
#define DISCHARGE_LIMITED_CURRENT_MA 1000   // 限流值

/**
 * @brief  初始化放电控制器
 */
void Discharge_Init(void) {
    discharge_ctrl.state = DISCHARGE_STATE_IDLE;
    discharge_ctrl.discharge_start_ms = 0;
    discharge_ctrl.accumulated_mah = 0;
    discharge_ctrl.current_limit_ma = DISCHARGE_MAX_CURRENT_MA;

    printf("放电控制器初始化完成\n");
}

/**
 * @brief  使能放电
 */
void Discharge_Enable(void) {
    discharge_ctrl.state = DISCHARGE_STATE_NORMAL;
    discharge_ctrl.discharge_start_ms = HAL_GetTick();

    // 打开放电MOSFET
    HAL_GPIO_WritePin(DISCHARGE_MOSFET_GPIO, DISCHARGE_MOSFET_PIN, GPIO_PIN_SET);

    printf("使能放电\n");
}

/**
 * @brief  禁止放电
 */
void Discharge_Disable(void) {
    discharge_ctrl.state = DISCHARGE_STATE_IDLE;

    // 关闭放电MOSFET
    HAL_GPIO_WritePin(DISCHARGE_MOSFET_GPIO, DISCHARGE_MOSFET_PIN, GPIO_PIN_RESET);

    printf("禁止放电\n");
}

/**
 * @brief  放电状态机
 * @param  bms: BMS句柄
 */
void Discharge_StateMachine(BMS_Handle_t* bms) {
    uint16_t voltage = bms->battery.pack_voltage;
    int16_t current = abs(bms->battery.current);  // 放电电流为负值,取绝对值

    switch (discharge_ctrl.state) {
        case DISCHARGE_STATE_IDLE:
            // 空闲状态
            break;

        case DISCHARGE_STATE_NORMAL:
            printf("正常放电: 电压=%d mV, 电流=%d mA\n", voltage, current);

            // 检查是否需要限流
            if (voltage < DISCHARGE_LIMIT_VOLTAGE_MV) {
                discharge_ctrl.state = DISCHARGE_STATE_LIMITED;
                discharge_ctrl.current_limit_ma = DISCHARGE_LIMITED_CURRENT_MA;
                printf("进入限流放电\n");
            }

            // 检查是否达到截止电压
            if (voltage < DISCHARGE_CUTOFF_VOLTAGE_MV) {
                discharge_ctrl.state = DISCHARGE_STATE_CUTOFF;
                Discharge_Disable();
                printf("达到放电截止电压\n");

                // SOC校准为0%
                SOC_CalibrateEmpty();
            }
            break;

        case DISCHARGE_STATE_LIMITED:
            printf("限流放电: 电压=%d mV, 电流=%d mA (限制=%d mA)\n",
                   voltage, current, discharge_ctrl.current_limit_ma);

            // 检查是否恢复正常
            if (voltage > DISCHARGE_LIMIT_VOLTAGE_MV + 100) {  // 加100mV滞回
                discharge_ctrl.state = DISCHARGE_STATE_NORMAL;
                discharge_ctrl.current_limit_ma = DISCHARGE_MAX_CURRENT_MA;
                printf("恢复正常放电\n");
            }

            // 检查是否达到截止电压
            if (voltage < DISCHARGE_CUTOFF_VOLTAGE_MV) {
                discharge_ctrl.state = DISCHARGE_STATE_CUTOFF;
                Discharge_Disable();
                printf("达到放电截止电压\n");
                SOC_CalibrateEmpty();
            }
            break;

        case DISCHARGE_STATE_CUTOFF:
            // 放电截止,已禁止放电
            break;

        case DISCHARGE_STATE_FAULT:
            // 故障状态
            Discharge_Disable();
            break;
    }
}

/**
 * @brief  获取放电电流限制
 * @retval 电流限制 (mA)
 */
uint16_t Discharge_GetCurrentLimit(void) {
    return discharge_ctrl.current_limit_ma;
}

第四部分:电池保护

保护功能实现

/**
 * @file    battery_protection.c
 * @brief   电池保护功能实现
 */

#include "bms_architecture.h"

/**
 * @brief  保护检查结果
 */
typedef struct {
    bool fault_detected;       // 是否检测到故障
    char fault_message[64];    // 故障信息
} ProtectionCheck_t;

/**
 * @brief  过充保护检查
 * @param  bms: BMS句柄
 * @retval 检查结果
 */
ProtectionCheck_t Protection_CheckOvercharge(BMS_Handle_t* bms) {
    ProtectionCheck_t result = {false, ""};

    // 检查单体电压
    for (int i = 0; i < 5; i++) {
        if (bms->battery.cell_voltage[i] > bms->config.cell_overvoltage_mv) {
            result.fault_detected = true;
            snprintf(result.fault_message, sizeof(result.fault_message),
                    "单体%d过充: %d mV > %d mV", 
                    i+1, 
                    bms->battery.cell_voltage[i],
                    bms->config.cell_overvoltage_mv);

            // 设置保护标志
            bms->protection.overcharge = true;

            // 停止充电
            Charge_Stop();

            printf("⚠ %s\n", result.fault_message);
            break;
        }
    }

    return result;
}

/**
 * @brief  过放保护检查
 * @param  bms: BMS句柄
 * @retval 检查结果
 */
ProtectionCheck_t Protection_CheckOverdischarge(BMS_Handle_t* bms) {
    ProtectionCheck_t result = {false, ""};

    // 检查单体电压
    for (int i = 0; i < 5; i++) {
        if (bms->battery.cell_voltage[i] < bms->config.cell_undervoltage_mv) {
            result.fault_detected = true;
            snprintf(result.fault_message, sizeof(result.fault_message),
                    "单体%d过放: %d mV < %d mV",
                    i+1,
                    bms->battery.cell_voltage[i],
                    bms->config.cell_undervoltage_mv);

            // 设置保护标志
            bms->protection.overdischarge = true;

            // 停止放电
            Discharge_Disable();

            printf("⚠ %s\n", result.fault_message);
            break;
        }
    }

    return result;
}

/**
 * @brief  过流保护检查
 * @param  bms: BMS句柄
 * @retval 检查结果
 */
ProtectionCheck_t Protection_CheckOvercurrent(BMS_Handle_t* bms) {
    ProtectionCheck_t result = {false, ""};
    int16_t current = bms->battery.current;

    // 检查充电过流
    if (current > 0 && current > bms->config.charge_overcurrent_ma) {
        result.fault_detected = true;
        snprintf(result.fault_message, sizeof(result.fault_message),
                "充电过流: %d mA > %d mA",
                current,
                bms->config.charge_overcurrent_ma);

        bms->protection.overcurrent_charge = true;
        Charge_Stop();

        printf("⚠ %s\n", result.fault_message);
    }

    // 检查放电过流
    if (current < 0 && abs(current) > bms->config.discharge_overcurrent_ma) {
        result.fault_detected = true;
        snprintf(result.fault_message, sizeof(result.fault_message),
                "放电过流: %d mA > %d mA",
                abs(current),
                bms->config.discharge_overcurrent_ma);

        bms->protection.overcurrent_discharge = true;
        Discharge_Disable();

        printf("⚠ %s\n", result.fault_message);
    }

    return result;
}

/**
 * @brief  温度保护检查
 * @param  bms: BMS句柄
 * @retval 检查结果
 */
ProtectionCheck_t Protection_CheckTemperature(BMS_Handle_t* bms) {
    ProtectionCheck_t result = {false, ""};

    for (int i = 0; i < 2; i++) {
        int16_t temp = bms->battery.temperature[i] / 10;  // 转换为°C

        // 检查过温
        if (temp > bms->config.overtemperature_c) {
            result.fault_detected = true;
            snprintf(result.fault_message, sizeof(result.fault_message),
                    "温度%d过高: %d°C > %d°C",
                    i+1, temp, bms->config.overtemperature_c);

            bms->protection.overtemperature = true;

            // 停止充放电
            Charge_Stop();
            Discharge_Disable();

            printf("⚠ %s\n", result.fault_message);
            break;
        }

        // 检查低温
        if (temp < bms->config.undertemperature_c) {
            result.fault_detected = true;
            snprintf(result.fault_message, sizeof(result.fault_message),
                    "温度%d过低: %d°C < %d°C",
                    i+1, temp, bms->config.undertemperature_c);

            bms->protection.undertemperature = true;

            // 低温禁止充电
            Charge_Stop();

            printf("⚠ %s\n", result.fault_message);
            break;
        }
    }

    return result;
}

/**
 * @brief  短路保护检查
 * @param  bms: BMS句柄
 * @retval 检查结果
 */
ProtectionCheck_t Protection_CheckShortCircuit(BMS_Handle_t* bms) {
    ProtectionCheck_t result = {false, ""};

    // 短路判断:电流突然超过阈值(例如10A)
    const int16_t SHORT_CIRCUIT_CURRENT_MA = 10000;

    if (abs(bms->battery.current) > SHORT_CIRCUIT_CURRENT_MA) {
        result.fault_detected = true;
        snprintf(result.fault_message, sizeof(result.fault_message),
                "检测到短路: 电流=%d mA", bms->battery.current);

        bms->protection.short_circuit = true;

        // 立即断开充放电
        Charge_Stop();
        Discharge_Disable();

        printf("⚠⚠⚠ %s\n", result.fault_message);
    }

    return result;
}

/**
 * @brief  单体不均衡检查
 * @param  bms: BMS句柄
 * @retval 检查结果
 */
ProtectionCheck_t Protection_CheckCellImbalance(BMS_Handle_t* bms) {
    ProtectionCheck_t result = {false, ""};

    // 找出最高和最低电压
    uint16_t max_voltage = 0;
    uint16_t min_voltage = 65535;
    uint8_t max_cell = 0;
    uint8_t min_cell = 0;

    for (int i = 0; i < 5; i++) {
        if (bms->battery.cell_voltage[i] > max_voltage) {
            max_voltage = bms->battery.cell_voltage[i];
            max_cell = i;
        }
        if (bms->battery.cell_voltage[i] < min_voltage) {
            min_voltage = bms->battery.cell_voltage[i];
            min_cell = i;
        }
    }

    // 计算电压差
    uint16_t voltage_diff = max_voltage - min_voltage;

    if (voltage_diff > bms->config.balance_voltage_diff_mv) {
        result.fault_detected = true;
        snprintf(result.fault_message, sizeof(result.fault_message),
                "单体不均衡: Cell%d(%d mV) - Cell%d(%d mV) = %d mV",
                max_cell+1, max_voltage,
                min_cell+1, min_voltage,
                voltage_diff);

        bms->protection.cell_imbalance = true;

        printf("⚠ %s\n", result.fault_message);
    }

    return result;
}

/**
 * @brief  执行所有保护检查
 * @param  bms: BMS句柄
 * @retval 是否检测到故障
 */
bool Protection_CheckAll(BMS_Handle_t* bms) {
    bool fault_detected = false;

    // 清除之前的保护标志
    memset(&bms->protection, 0, sizeof(BMS_Protection_t));

    // 执行各项检查
    if (Protection_CheckOvercharge(bms).fault_detected) {
        fault_detected = true;
    }

    if (Protection_CheckOverdischarge(bms).fault_detected) {
        fault_detected = true;
    }

    if (Protection_CheckOvercurrent(bms).fault_detected) {
        fault_detected = true;
    }

    if (Protection_CheckTemperature(bms).fault_detected) {
        fault_detected = true;
    }

    if (Protection_CheckShortCircuit(bms).fault_detected) {
        fault_detected = true;
    }

    if (Protection_CheckCellImbalance(bms).fault_detected) {
        fault_detected = true;
    }

    return fault_detected;
}

/**
 * @brief  清除保护故障(需要人工确认)
 * @param  bms: BMS句柄
 */
void Protection_ClearFaults(BMS_Handle_t* bms) {
    memset(&bms->protection, 0, sizeof(BMS_Protection_t));
    printf("保护故障已清除\n");
}

第五部分:均衡管理

被动均衡原理

被动均衡(电阻放电):

高电压单体 ──→ [均衡电阻] ──→ 热量
                 ↓
              能量损耗

优点:
- 电路简单
- 成本低
- 可靠性高

缺点:
- 能量浪费
- 产生热量
- 均衡速度慢

主动均衡(能量转移):

高电压单体 ──→ [DC-DC转换器] ──→ 低电压单体
                 ↓
              能量转移

优点:
- 能量利用率高
- 均衡速度快
- 发热少

缺点:
- 电路复杂
- 成本高
- 可靠性相对低

被动均衡实现

/**
 * @file    cell_balancing.c
 * @brief   电池均衡管理实现
 */

#include "bms_architecture.h"

/**
 * @brief  均衡控制器
 */
typedef struct {
    bool balancing_active;         // 均衡是否激活
    uint8_t balance_cells;         // 需要均衡的单体(位掩码)
    uint32_t balance_start_ms;     // 均衡开始时间
    uint32_t balance_duration_ms;  // 均衡持续时间
} BalanceController_t;

static BalanceController_t balance_ctrl = {0};

/**
 * @brief  均衡参数配置
 */
#define BALANCE_VOLTAGE_THRESHOLD_MV  50    // 均衡电压差阈值
#define BALANCE_MIN_VOLTAGE_MV        3600  // 最低均衡电压
#define BALANCE_MAX_DURATION_MS       3600000  // 最大均衡时间(1小时)
#define BALANCE_CURRENT_MA            100   // 均衡电流(取决于均衡电阻)

/**
 * @brief  初始化均衡控制器
 */
void Balance_Init(void) {
    balance_ctrl.balancing_active = false;
    balance_ctrl.balance_cells = 0;
    balance_ctrl.balance_start_ms = 0;
    balance_ctrl.balance_duration_ms = 0;

    // 关闭所有均衡开关
    for (int i = 0; i < 5; i++) {
        Balance_SetCell(i, false);
    }

    printf("均衡控制器初始化完成\n");
}

/**
 * @brief  控制单体均衡开关
 * @param  cell_index: 单体索引 (0-4)
 * @param  enable: 使能/禁止
 */
void Balance_SetCell(uint8_t cell_index, bool enable) {
    // 这里需要根据实际硬件实现
    // 例如:通过GPIO控制MOSFET开关

    GPIO_TypeDef* gpio_port;
    uint16_t gpio_pin;

    switch (cell_index) {
        case 0: gpio_port = GPIOA; gpio_pin = GPIO_PIN_0; break;
        case 1: gpio_port = GPIOA; gpio_pin = GPIO_PIN_1; break;
        case 2: gpio_port = GPIOA; gpio_pin = GPIO_PIN_2; break;
        case 3: gpio_port = GPIOA; gpio_pin = GPIO_PIN_3; break;
        case 4: gpio_port = GPIOA; gpio_pin = GPIO_PIN_4; break;
        default: return;
    }

    HAL_GPIO_WritePin(gpio_port, gpio_pin, enable ? GPIO_PIN_SET : GPIO_PIN_RESET);

    printf("单体%d均衡: %s\n", cell_index+1, enable ? "开启" : "关闭");
}

/**
 * @brief  计算需要均衡的单体
 * @param  bms: BMS句柄
 * @retval 需要均衡的单体(位掩码)
 */
uint8_t Balance_CalculateTargets(BMS_Handle_t* bms) {
    uint8_t balance_targets = 0;

    // 找出最低电压
    uint16_t min_voltage = 65535;
    for (int i = 0; i < 5; i++) {
        if (bms->battery.cell_voltage[i] < min_voltage) {
            min_voltage = bms->battery.cell_voltage[i];
        }
    }

    // 标记需要均衡的单体(电压高于最低电压+阈值)
    for (int i = 0; i < 5; i++) {
        uint16_t voltage_diff = bms->battery.cell_voltage[i] - min_voltage;

        if (voltage_diff > BALANCE_VOLTAGE_THRESHOLD_MV &&
            bms->battery.cell_voltage[i] > BALANCE_MIN_VOLTAGE_MV) {
            balance_targets |= (1 << i);
            printf("单体%d需要均衡: %d mV (差值=%d mV)\n",
                   i+1, bms->battery.cell_voltage[i], voltage_diff);
        }
    }

    return balance_targets;
}

/**
 * @brief  开始均衡
 * @param  bms: BMS句柄
 */
void Balance_Start(BMS_Handle_t* bms) {
    // 计算需要均衡的单体
    balance_ctrl.balance_cells = Balance_CalculateTargets(bms);

    if (balance_ctrl.balance_cells == 0) {
        printf("无需均衡\n");
        return;
    }

    // 开启均衡
    balance_ctrl.balancing_active = true;
    balance_ctrl.balance_start_ms = HAL_GetTick();

    // 使能对应单体的均衡
    for (int i = 0; i < 5; i++) {
        if (balance_ctrl.balance_cells & (1 << i)) {
            Balance_SetCell(i, true);
        }
    }

    printf("开始均衡,目标单体: 0x%02X\n", balance_ctrl.balance_cells);
}

/**
 * @brief  停止均衡
 */
void Balance_Stop(void) {
    // 关闭所有均衡开关
    for (int i = 0; i < 5; i++) {
        Balance_SetCell(i, false);
    }

    balance_ctrl.balancing_active = false;
    balance_ctrl.balance_cells = 0;

    printf("停止均衡\n");
}

/**
 * @brief  均衡状态机
 * @param  bms: BMS句柄
 */
void Balance_StateMachine(BMS_Handle_t* bms) {
    if (!balance_ctrl.balancing_active) {
        return;
    }

    uint32_t now_ms = HAL_GetTick();
    uint32_t elapsed_ms = now_ms - balance_ctrl.balance_start_ms;

    // 检查是否超时
    if (elapsed_ms > BALANCE_MAX_DURATION_MS) {
        printf("均衡超时,停止均衡\n");
        Balance_Stop();
        return;
    }

    // 检查是否均衡完成
    uint8_t new_targets = Balance_CalculateTargets(bms);

    if (new_targets == 0) {
        printf("均衡完成,耗时: %.1f 分钟\n", elapsed_ms / 60000.0f);
        Balance_Stop();
        return;
    }

    // 更新均衡目标(可能有单体已经均衡完成)
    if (new_targets != balance_ctrl.balance_cells) {
        printf("更新均衡目标: 0x%02X -> 0x%02X\n",
               balance_ctrl.balance_cells, new_targets);

        // 关闭已完成的单体
        for (int i = 0; i < 5; i++) {
            if ((balance_ctrl.balance_cells & (1 << i)) &&
                !(new_targets & (1 << i))) {
                Balance_SetCell(i, false);
                printf("单体%d均衡完成\n", i+1);
            }
        }

        balance_ctrl.balance_cells = new_targets;
    }

    // 定期打印均衡进度
    static uint32_t last_print_ms = 0;
    if (now_ms - last_print_ms > 10000) {  // 每10秒打印一次
        printf("均衡进行中... 已耗时: %.1f 分钟\n", elapsed_ms / 60000.0f);

        for (int i = 0; i < 5; i++) {
            printf("  单体%d: %d mV %s\n",
                   i+1,
                   bms->battery.cell_voltage[i],
                   (balance_ctrl.balance_cells & (1 << i)) ? "[均衡中]" : "");
        }

        last_print_ms = now_ms;
    }
}

/**
 * @brief  判断是否需要均衡
 * @param  bms: BMS句柄
 * @retval true=需要均衡, false=不需要
 */
bool Balance_IsNeeded(BMS_Handle_t* bms) {
    uint8_t targets = Balance_CalculateTargets(bms);
    return (targets != 0);
}

/**
 * @brief  获取均衡状态
 * @retval true=均衡中, false=未均衡
 */
bool Balance_IsActive(void) {
    return balance_ctrl.balancing_active;
}

第六部分:通信接口

UART通信协议

/**
 * @file    bms_communication.c
 * @brief   BMS通信接口实现
 */

#include "bms_architecture.h"
#include <string.h>

/**
 * @brief  通信协议定义
 */
#define COMM_START_BYTE     0xAA
#define COMM_END_BYTE       0x55
#define COMM_MAX_DATA_LEN   64

/**
 * @brief  命令类型
 */
typedef enum {
    CMD_GET_STATUS = 0x01,         // 获取状态
    CMD_GET_VOLTAGE = 0x02,        // 获取电压
    CMD_GET_CURRENT = 0x03,        // 获取电流
    CMD_GET_TEMPERATURE = 0x04,    // 获取温度
    CMD_GET_SOC = 0x05,            // 获取SOC
    CMD_START_CHARGE = 0x10,       // 开始充电
    CMD_STOP_CHARGE = 0x11,        // 停止充电
    CMD_START_BALANCE = 0x12,      // 开始均衡
    CMD_STOP_BALANCE = 0x13,       // 停止均衡
    CMD_CLEAR_FAULTS = 0x14,       // 清除故障
    CMD_SET_CONFIG = 0x20,         // 设置配置
    CMD_GET_CONFIG = 0x21          // 获取配置
} CommCommand_t;

/**
 * @brief  通信数据包结构
 */
typedef struct {
    uint8_t start;                 // 起始字节 (0xAA)
    uint8_t command;               // 命令字节
    uint8_t length;                // 数据长度
    uint8_t data[COMM_MAX_DATA_LEN]; // 数据
    uint8_t checksum;              // 校验和
    uint8_t end;                   // 结束字节 (0x55)
} __attribute__((packed)) CommPacket_t;

/**
 * @brief  计算校验和
 * @param  data: 数据指针
 * @param  length: 数据长度
 * @retval 校验和
 */
uint8_t Comm_CalculateChecksum(uint8_t* data, uint8_t length) {
    uint8_t checksum = 0;
    for (uint8_t i = 0; i < length; i++) {
        checksum += data[i];
    }
    return checksum;
}

/**
 * @brief  发送数据包
 * @param  command: 命令
 * @param  data: 数据
 * @param  length: 数据长度
 */
void Comm_SendPacket(uint8_t command, uint8_t* data, uint8_t length) {
    CommPacket_t packet;

    packet.start = COMM_START_BYTE;
    packet.command = command;
    packet.length = length;

    if (length > 0 && data != NULL) {
        memcpy(packet.data, data, length);
    }

    // 计算校验和(命令 + 长度 + 数据)
    uint8_t checksum_data[2 + COMM_MAX_DATA_LEN];
    checksum_data[0] = packet.command;
    checksum_data[1] = packet.length;
    memcpy(&checksum_data[2], packet.data, length);
    packet.checksum = Comm_CalculateChecksum(checksum_data, 2 + length);

    packet.end = COMM_END_BYTE;

    // 发送数据包
    uint8_t packet_size = 5 + length;  // start + cmd + len + data + checksum + end
    HAL_UART_Transmit(&huart1, (uint8_t*)&packet, packet_size, 1000);
}

/**
 * @brief  处理接收到的命令
 * @param  bms: BMS句柄
 * @param  packet: 接收到的数据包
 */
void Comm_ProcessCommand(BMS_Handle_t* bms, CommPacket_t* packet) {
    uint8_t response_data[COMM_MAX_DATA_LEN];
    uint8_t response_length = 0;

    switch (packet->command) {
        case CMD_GET_STATUS:
            // 返回系统状态
            response_data[0] = bms->state;
            response_data[1] = bms->protection.overcharge ? 1 : 0;
            response_data[2] = bms->protection.overdischarge ? 1 : 0;
            response_data[3] = bms->protection.overcurrent_charge ? 1 : 0;
            response_data[4] = bms->protection.overcurrent_discharge ? 1 : 0;
            response_data[5] = bms->protection.overtemperature ? 1 : 0;
            response_length = 6;
            break;

        case CMD_GET_VOLTAGE:
            // 返回电压信息
            for (int i = 0; i < 5; i++) {
                response_data[i*2] = (bms->battery.cell_voltage[i] >> 8) & 0xFF;
                response_data[i*2+1] = bms->battery.cell_voltage[i] & 0xFF;
            }
            response_data[10] = (bms->battery.pack_voltage >> 8) & 0xFF;
            response_data[11] = bms->battery.pack_voltage & 0xFF;
            response_length = 12;
            break;

        case CMD_GET_CURRENT:
            // 返回电流信息
            response_data[0] = (bms->battery.current >> 8) & 0xFF;
            response_data[1] = bms->battery.current & 0xFF;
            response_length = 2;
            break;

        case CMD_GET_TEMPERATURE:
            // 返回温度信息
            for (int i = 0; i < 2; i++) {
                response_data[i*2] = (bms->battery.temperature[i] >> 8) & 0xFF;
                response_data[i*2+1] = bms->battery.temperature[i] & 0xFF;
            }
            response_length = 4;
            break;

        case CMD_GET_SOC:
            // 返回SOC信息
            response_data[0] = bms->battery.soc;
            response_data[1] = bms->battery.soh;
            response_data[2] = (bms->battery.capacity_mah >> 24) & 0xFF;
            response_data[3] = (bms->battery.capacity_mah >> 16) & 0xFF;
            response_data[4] = (bms->battery.capacity_mah >> 8) & 0xFF;
            response_data[5] = bms->battery.capacity_mah & 0xFF;
            response_length = 6;
            break;

        case CMD_START_CHARGE:
            // 开始充电
            Charge_Start();
            response_data[0] = 0x00;  // 成功
            response_length = 1;
            break;

        case CMD_STOP_CHARGE:
            // 停止充电
            Charge_Stop();
            response_data[0] = 0x00;  // 成功
            response_length = 1;
            break;

        case CMD_START_BALANCE:
            // 开始均衡
            Balance_Start(bms);
            response_data[0] = 0x00;  // 成功
            response_length = 1;
            break;

        case CMD_STOP_BALANCE:
            // 停止均衡
            Balance_Stop();
            response_data[0] = 0x00;  // 成功
            response_length = 1;
            break;

        case CMD_CLEAR_FAULTS:
            // 清除故障
            Protection_ClearFaults(bms);
            response_data[0] = 0x00;  // 成功
            response_length = 1;
            break;

        default:
            // 未知命令
            response_data[0] = 0xFF;  // 错误
            response_length = 1;
            break;
    }

    // 发送响应
    Comm_SendPacket(packet->command, response_data, response_length);
}

/**
 * @brief  接收数据包(中断回调)
 * @param  bms: BMS句柄
 * @param  rx_data: 接收缓冲区
 * @param  rx_length: 接收长度
 */
void Comm_ReceiveCallback(BMS_Handle_t* bms, uint8_t* rx_data, uint16_t rx_length) {
    static uint8_t rx_buffer[256];
    static uint16_t rx_index = 0;

    // 将接收数据添加到缓冲区
    for (uint16_t i = 0; i < rx_length; i++) {
        rx_buffer[rx_index++] = rx_data[i];

        // 防止缓冲区溢出
        if (rx_index >= sizeof(rx_buffer)) {
            rx_index = 0;
        }
    }

    // 查找完整的数据包
    for (uint16_t i = 0; i < rx_index - 5; i++) {
        if (rx_buffer[i] == COMM_START_BYTE) {
            uint8_t length = rx_buffer[i + 2];
            uint16_t packet_size = 5 + length;

            if (i + packet_size <= rx_index &&
                rx_buffer[i + packet_size - 1] == COMM_END_BYTE) {

                // 找到完整数据包
                CommPacket_t* packet = (CommPacket_t*)&rx_buffer[i];

                // 验证校验和
                uint8_t checksum_data[2 + COMM_MAX_DATA_LEN];
                checksum_data[0] = packet->command;
                checksum_data[1] = packet->length;
                memcpy(&checksum_data[2], packet->data, length);
                uint8_t calculated_checksum = Comm_CalculateChecksum(checksum_data, 2 + length);

                if (calculated_checksum == packet->checksum) {
                    // 校验通过,处理命令
                    Comm_ProcessCommand(bms, packet);
                } else {
                    printf("校验和错误\n");
                }

                // 移除已处理的数据包
                memmove(rx_buffer, &rx_buffer[i + packet_size], rx_index - i - packet_size);
                rx_index -= (i + packet_size);
                i = 0;
            }
        }
    }
}

/**
 * @brief  定期上报数据
 * @param  bms: BMS句柄
 */
void Comm_PeriodicReport(BMS_Handle_t* bms) {
    static uint32_t last_report_ms = 0;
    uint32_t now_ms = HAL_GetTick();

    // 每秒上报一次
    if (now_ms - last_report_ms >= 1000) {
        // 上报电压
        uint8_t voltage_data[12];
        for (int i = 0; i < 5; i++) {
            voltage_data[i*2] = (bms->battery.cell_voltage[i] >> 8) & 0xFF;
            voltage_data[i*2+1] = bms->battery.cell_voltage[i] & 0xFF;
        }
        voltage_data[10] = (bms->battery.pack_voltage >> 8) & 0xFF;
        voltage_data[11] = bms->battery.pack_voltage & 0xFF;
        Comm_SendPacket(CMD_GET_VOLTAGE, voltage_data, 12);

        // 上报SOC
        uint8_t soc_data[6];
        soc_data[0] = bms->battery.soc;
        soc_data[1] = bms->battery.soh;
        soc_data[2] = (bms->battery.capacity_mah >> 24) & 0xFF;
        soc_data[3] = (bms->battery.capacity_mah >> 16) & 0xFF;
        soc_data[4] = (bms->battery.capacity_mah >> 8) & 0xFF;
        soc_data[5] = bms->battery.capacity_mah & 0xFF;
        Comm_SendPacket(CMD_GET_SOC, soc_data, 6);

        last_report_ms = now_ms;
    }
}

第七部分:完整BMS主程序

主程序实现

/**
 * @file    bms_main.c
 * @brief   BMS主程序
 */

#include "bms_architecture.h"

// 全局BMS句柄
BMS_Handle_t g_bms = {0};

/**
 * @brief  BMS初始化
 */
void BMS_Init(void) {
    printf("\n═══════════════════════════════════════════\n");
    printf("    电池管理系统 (BMS) 初始化\n");
    printf("═══════════════════════════════════════════\n\n");

    // 初始化状态
    g_bms.state = BMS_STATE_INIT;

    // 初始化配置参数
    g_bms.config.cell_overvoltage_mv = 4250;       // 4.25V
    g_bms.config.cell_undervoltage_mv = 2800;      // 2.8V
    g_bms.config.charge_overcurrent_ma = 2000;     // 2A
    g_bms.config.discharge_overcurrent_ma = 5000;  // 5A
    g_bms.config.overtemperature_c = 60;           // 60°C
    g_bms.config.undertemperature_c = 0;           // 0°C
    g_bms.config.balance_voltage_diff_mv = 50;     // 50mV
    g_bms.config.design_capacity_mah = 2000;       // 2000mAh

    printf("配置参数:\n");
    printf("  过充电压: %d mV\n", g_bms.config.cell_overvoltage_mv);
    printf("  过放电压: %d mV\n", g_bms.config.cell_undervoltage_mv);
    printf("  充电过流: %d mA\n", g_bms.config.charge_overcurrent_ma);
    printf("  放电过流: %d mA\n", g_bms.config.discharge_overcurrent_ma);
    printf("  设计容量: %d mAh\n\n", g_bms.config.design_capacity_mah);

    // 初始化各模块
    SOC_Init(50.0f, g_bms.config.design_capacity_mah);
    Charge_Init();
    Discharge_Init();
    Balance_Init();

    // 初始化硬件
    BMS_HardwareInit();

    // 读取初始电池参数
    BMS_ReadBatteryParams(&g_bms);

    // 根据电压估算初始SOC
    float initial_soc = SOC_EstimateFromOCV(g_bms.battery.pack_voltage / 5);
    SOC_Init(initial_soc, g_bms.config.design_capacity_mah);

    printf("初始电池状态:\n");
    printf("  总电压: %d mV\n", g_bms.battery.pack_voltage);
    printf("  电流: %d mA\n", g_bms.battery.current);
    printf("  温度: %.1f°C\n", g_bms.battery.temperature[0] / 10.0f);
    printf("  SOC: %.1f%%\n\n", initial_soc);

    // 进入空闲状态
    g_bms.state = BMS_STATE_IDLE;

    printf("BMS初始化完成\n");
    printf("═══════════════════════════════════════════\n\n");
}

/**
 * @brief  硬件初始化
 */
void BMS_HardwareInit(void) {
    // 初始化GPIO
    // 充电MOSFET控制引脚
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = CHARGE_MOSFET_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CHARGE_MOSFET_GPIO, &GPIO_InitStruct);

    // 放电MOSFET控制引脚
    GPIO_InitStruct.Pin = DISCHARGE_MOSFET_PIN;
    HAL_GPIO_Init(DISCHARGE_MOSFET_GPIO, &GPIO_InitStruct);

    // 初始化ADC(用于电压/电流/温度采集)
    HAL_ADC_Start(&hadc1);

    // 初始化UART(用于通信)
    // 已在main.c中初始化

    printf("硬件初始化完成\n");
}

/**
 * @brief  读取电池参数
 * @param  bms: BMS句柄
 */
void BMS_ReadBatteryParams(BMS_Handle_t* bms) {
    // 读取单体电压(通过AFE芯片,如BQ76920)
    // 这里使用模拟数据,实际应从AFE芯片读取
    bms->battery.cell_voltage[0] = 3750;  // mV
    bms->battery.cell_voltage[1] = 3760;
    bms->battery.cell_voltage[2] = 3755;
    bms->battery.cell_voltage[3] = 3765;
    bms->battery.cell_voltage[4] = 3770;

    // 计算总电压
    bms->battery.pack_voltage = 0;
    for (int i = 0; i < 5; i++) {
        bms->battery.pack_voltage += bms->battery.cell_voltage[i];
    }

    // 读取电流(通过霍尔传感器)
    // 这里使用模拟数据
    bms->battery.current = 0;  // mA (正=充电, 负=放电)

    // 读取温度(通过NTC热敏电阻)
    // 这里使用模拟数据
    bms->battery.temperature[0] = 250;  // 25.0°C
    bms->battery.temperature[1] = 260;  // 26.0°C

    // 更新SOC
    bms->battery.soc = (uint8_t)SOC_GetPercent();
    bms->battery.capacity_mah = (uint32_t)SOC_GetRemainingCapacity();

    // 更新SOH(简化实现,实际需要复杂算法)
    bms->battery.soh = 100;  // 100%

    // 更新时间戳
    bms->timestamp_ms = HAL_GetTick();
}

/**
 * @brief  BMS主循环
 */
void BMS_MainLoop(void) {
    static uint32_t last_update_ms = 0;
    uint32_t now_ms = HAL_GetTick();

    // 每100ms更新一次
    if (now_ms - last_update_ms >= 100) {
        // 读取电池参数
        BMS_ReadBatteryParams(&g_bms);

        // 更新SOC
        SOC_UpdateHybrid(g_bms.battery.current,
                        g_bms.battery.pack_voltage / 5,
                        now_ms);

        // 执行保护检查
        bool fault = Protection_CheckAll(&g_bms);

        if (fault) {
            g_bms.state = BMS_STATE_FAULT;
        }

        // 执行充电状态机
        if (g_bms.state == BMS_STATE_CHARGING) {
            Charge_StateMachine(&g_bms);
        }

        // 执行放电状态机
        if (g_bms.state == BMS_STATE_DISCHARGING) {
            Discharge_StateMachine(&g_bms);
        }

        // 执行均衡状态机
        if (g_bms.state == BMS_STATE_BALANCING) {
            Balance_StateMachine(&g_bms);
        }

        last_update_ms = now_ms;
    }

    // 处理通信
    Comm_PeriodicReport(&g_bms);
}

/**
 * @brief  打印BMS状态
 */
void BMS_PrintStatus(void) {
    printf("\n═══════════════════════════════════════════\n");
    printf("           BMS 状态报告\n");
    printf("═══════════════════════════════════════════\n");

    // 系统状态
    const char* state_str[] = {
        "初始化", "空闲", "充电中", "放电中", "均衡中", "故障", "休眠"
    };
    printf("系统状态: %s\n", state_str[g_bms.state]);

    // 电池参数
    printf("\n电池参数:\n");
    printf("  单体电压:\n");
    for (int i = 0; i < 5; i++) {
        printf("    Cell%d: %d mV\n", i+1, g_bms.battery.cell_voltage[i]);
    }
    printf("  总电压: %d mV\n", g_bms.battery.pack_voltage);
    printf("  电流: %d mA %s\n",
           abs(g_bms.battery.current),
           g_bms.battery.current > 0 ? "(充电)" :
           g_bms.battery.current < 0 ? "(放电)" : "(静置)");
    printf("  温度1: %.1f°C\n", g_bms.battery.temperature[0] / 10.0f);
    printf("  温度2: %.1f°C\n", g_bms.battery.temperature[1] / 10.0f);
    printf("  SOC: %d%%\n", g_bms.battery.soc);
    printf("  SOH: %d%%\n", g_bms.battery.soh);
    printf("  剩余容量: %d mAh\n", g_bms.battery.capacity_mah);

    // 保护状态
    printf("\n保护状态:\n");
    printf("  过充保护: %s\n", g_bms.protection.overcharge ? "触发" : "正常");
    printf("  过放保护: %s\n", g_bms.protection.overdischarge ? "触发" : "正常");
    printf("  充电过流: %s\n", g_bms.protection.overcurrent_charge ? "触发" : "正常");
    printf("  放电过流: %s\n", g_bms.protection.overcurrent_discharge ? "触发" : "正常");
    printf("  过温保护: %s\n", g_bms.protection.overtemperature ? "触发" : "正常");
    printf("  低温保护: %s\n", g_bms.protection.undertemperature ? "触发" : "正常");
    printf("  短路保护: %s\n", g_bms.protection.short_circuit ? "触发" : "正常");
    printf("  单体不均衡: %s\n", g_bms.protection.cell_imbalance ? "是" : "否");

    // 运行时间
    printf("\n运行时间: %.1f 小时\n", g_bms.timestamp_ms / 3600000.0f);
    printf("循环次数: %d\n", g_bms.cycle_count);

    printf("═══════════════════════════════════════════\n\n");
}

/**
 * @brief  主函数
 */
int main(void) {
    // HAL库初始化
    HAL_Init();
    SystemClock_Config();

    // 初始化外设
    MX_GPIO_Init();
    MX_ADC1_Init();
    MX_USART1_UART_Init();

    // 初始化BMS
    BMS_Init();

    // 主循环
    while (1) {
        BMS_MainLoop();

        // 定期打印状态(每10秒)
        static uint32_t last_print_ms = 0;
        if (HAL_GetTick() - last_print_ms >= 10000) {
            BMS_PrintStatus();
            last_print_ms = HAL_GetTick();
        }

        HAL_Delay(10);
    }
}

实践建议

开发流程

1. 硬件准备: - 开发板(STM32F103) - 电池组(5串锂电池) - AFE芯片(BQ76920) - 电流传感器(ACS712) - NTC热敏电阻 - MOSFET开关 - 调试工具(ST-Link)

2. 软件开发步骤:

开发顺序:

第一阶段:基础功能
1. 搭建硬件平台
2. 实现电压采集
3. 实现电流采集
4. 实现温度采集
5. 验证数据准确性

第二阶段:核心算法
1. 实现SOC计算
2. 实现充电控制
3. 实现放电控制
4. 测试充放电流程

第三阶段:保护功能
1. 实现各项保护
2. 测试保护触发
3. 验证保护可靠性
4. 优化保护参数

第四阶段:高级功能
1. 实现均衡管理
2. 实现通信接口
3. 添加数据记录
4. 优化用户体验

第五阶段:测试验证
1. 功能测试
2. 压力测试
3. 长期测试
4. 认证测试

调试技巧

1. 电压测量校准:

/**
 * @brief  电压校准
 */
void BMS_CalibrateVoltage(void) {
    printf("电压校准程序\n");
    printf("请使用万用表测量实际电压\n\n");

    for (int i = 0; i < 5; i++) {
        uint16_t measured_mv = BMS_ReadCellVoltage(i);

        printf("单体%d:\n", i+1);
        printf("  测量值: %d mV\n", measured_mv);
        printf("  请输入万用表读数(mV): ");

        uint16_t actual_mv;
        scanf("%d", &actual_mv);

        // 计算校准系数
        float calibration_factor = (float)actual_mv / measured_mv;

        printf("  校准系数: %.4f\n\n", calibration_factor);

        // 保存校准系数到EEPROM
        BMS_SaveCalibration(i, calibration_factor);
    }

    printf("电压校准完成\n");
}

2. 电流传感器校准:

/**
 * @brief  电流校准
 */
void BMS_CalibrateCurrent(void) {
    printf("电流校准程序\n");
    printf("请确保电池无负载\n");
    printf("按任意键开始零点校准...\n");
    getchar();

    // 零点校准
    int32_t zero_offset = 0;
    for (int i = 0; i < 100; i++) {
        zero_offset += BMS_ReadCurrentRaw();
        HAL_Delay(10);
    }
    zero_offset /= 100;

    printf("零点偏移: %d\n", zero_offset);

    // 满量程校准
    printf("\n请连接已知负载(例如1A)\n");
    printf("按任意键继续...\n");
    getchar();

    int32_t load_reading = 0;
    for (int i = 0; i < 100; i++) {
        load_reading += BMS_ReadCurrentRaw();
        HAL_Delay(10);
    }
    load_reading /= 100;

    printf("负载读数: %d\n", load_reading);
    printf("请输入实际电流(mA): ");

    int16_t actual_current;
    scanf("%d", &actual_current);

    // 计算校准系数
    float current_scale = (float)actual_current / (load_reading - zero_offset);

    printf("电流比例: %.4f mA/LSB\n", current_scale);

    // 保存校准参数
    BMS_SaveCurrentCalibration(zero_offset, current_scale);

    printf("电流校准完成\n");
}

常见问题

问题1:SOC不准确

原因分析:
1. 初始SOC估算不准
2. 电流测量误差
3. 累积误差
4. 温度影响

解决方案:
1. 使用OCV校准初始SOC
2. 定期使用OCV校准
3. 充满/放空时重新校准
4. 考虑温度补偿
5. 使用卡尔曼滤波

问题2:保护误触发

原因分析:
1. 阈值设置过严
2. 测量噪声
3. 瞬态干扰
4. 传感器故障

解决方案:
1. 调整保护阈值
2. 添加滤波算法
3. 增加延时判断
4. 多次采样确认
5. 添加滞回机制

问题3:均衡效果差

原因分析:
1. 均衡电流太小
2. 均衡时间不足
3. 电池老化不一致
4. 温度影响

解决方案:
1. 增大均衡电阻功率
2. 延长均衡时间
3. 考虑主动均衡
4. 定期维护
5. 更换老化电池

性能优化

1. 降低功耗:

/**
 * @brief  低功耗模式
 */
void BMS_EnterLowPowerMode(void) {
    // 关闭不必要的外设
    HAL_ADC_Stop(&hadc1);

    // 降低采样频率
    // 从100ms改为1s

    // 关闭LED指示
    HAL_GPIO_WritePin(LED_GPIO, LED_PIN, GPIO_PIN_RESET);

    // 进入睡眠模式
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
}

2. 提高响应速度:

/**
 * @brief  快速保护响应
 */
void BMS_FastProtection(void) {
    // 使用硬件比较器
    // 过流时立即断开MOSFET

    // 配置比较器
    HAL_COMP_Start(&hcomp1);

    // 配置中断
    HAL_NVIC_SetPriority(COMP_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(COMP_IRQn);
}

/**
 * @brief  比较器中断
 */
void COMP_IRQHandler(void) {
    // 立即断开MOSFET
    HAL_GPIO_WritePin(DISCHARGE_MOSFET_GPIO, 
                     DISCHARGE_MOSFET_PIN, 
                     GPIO_PIN_RESET);

    // 设置故障标志
    g_bms.protection.overcurrent_discharge = true;

    printf("过流保护触发!\n");
}

总结

关键要点

  1. 系统架构:
  2. 模块化设计
  3. 清晰的接口
  4. 状态机管理
  5. 分层架构

  6. 核心算法:

  7. SOC计算(安时积分 + OCV校准)
  8. 充电管理(CC-CV)
  9. 放电控制(限流保护)
  10. 均衡管理(被动/主动)

  11. 安全保护:

  12. 多重保护机制
  13. 快速响应
  14. 可靠性设计
  15. 故障诊断

  16. 通信接口:

  17. 标准协议
  18. 数据上报
  19. 远程控制
  20. 参数配置

进阶学习

完成本教程后,建议继续学习:

  • 动态电源管理(DPM)技术:学习更高级的功耗管理
  • 超低功耗传感器节点设计:应用BMS技术到IoT设备
  • 电源完整性分析与优化:深入理解电源系统设计
  • 锂电池化学特性:理解电池工作原理

参考资源

标准和规范: - IEC 62133:锂电池安全标准 - UL 2054:电池安全认证 - GB/T 31485:电动汽车BMS标准

芯片厂商资料: - TI BQ系列BMS芯片 - Analog Devices LTC系列 - Maxim MAX系列 - NXP BMS解决方案

开源项目: - DieBieMS:开源BMS项目 - LibreSolar:太阳能BMS - VESC BMS:电动车BMS

在线资源: - Battery University:电池知识库 - TI BMS设计指南 - Analog Devices BMS教程


作者: 嵌入式知识平台内容团队
最后更新: 2026-03-07
版本: 1.0.0