#ifndef __CHARGE_SM_H #define __CHARGE_SM_H #include "stm32f10x.h" /*=========================================================================== * 充电状态机 — LiPow 风格,C 语言实现 * * 设计原则: * - 状态机不直接操作 BQ25756 寄存器,只根据输入数据做决策 * - 输出决策结果(切换充电电流、切换电压、停充),由调用者执行 * - 所有阈值可配置,默认值适合 7S Li-ion * * 用法: * ChargeSM sm; * ChargeSM_Init(&sm, &cfg); * while (1) { * int32_t vbat = BQ25756_ReadVBAT_mV(); * int32_t ibat = BQ25756_ReadIBAT_mA(); * ChargeSM_Decision d = ChargeSM_Run(&sm, vbat, ibat); * // 根据 d.action 执行对应的寄存器操作 * } *===========================================================================*/ /*=========================================================================== * 状态枚举 *===========================================================================*/ typedef enum { CHARGE_STATE_IDLE = 0, CHARGE_STATE_PRECHARGE = 1, CHARGE_STATE_CC = 2, /* 恒流快充 */ CHARGE_STATE_CV = 3, /* 恒压 */ CHARGE_STATE_DONE = 4, /* 充电完成 */ CHARGE_STATE_FAULT = 5, /* 故障 */ CHARGE_STATE_NO_BATTERY = 6, /* 电池断连(VBAT 持续为 0) */ } ChargeState; /*=========================================================================== * 状态机配置 — 所有阈值可调 *===========================================================================*/ typedef struct { /* 电池参数 */ uint32_t full_voltage_mv; /* 满充电压(7S=29400mV) */ uint32_t precharge_thresh_mv; /* 低于此电压进入预充(默认 55% VFB) */ uint32_t recharge_hyst_mv; /* 再充电回滞(满充后压降到低于此值重启) */ /* 电流参数 */ uint16_t cc_current_ma; /* CC 阶段充电电流 */ uint16_t precharge_current_ma;/* 预充电电流 */ uint16_t term_current_ma; /* 终止电流(低于此值判满) */ /* 定时参数(秒),0 表示不启用 */ uint32_t precharge_timeout_s; /* 预充超时 */ uint32_t cc_cv_timeout_s; /* CC+CV 总超时 */ uint32_t cv_stable_time_s; /* CV 阶段电流稳定时间(电流小于 term 且持续此时间才判满)*/ /* 保护阈值 */ uint32_t vbat_overvoltage_mv; /* 电池过压 */ uint32_t ibat_overcurrent_ma; /* 充电过流 */ int8_t temp_max_c; /* 最高温度(<0 表示不检查) */ int8_t temp_min_c; /* 最低温度 */ /* 状态机周期 ms */ uint32_t tick_ms; /* Run() 调用周期,用于定时器累加 */ /* 电池断连检测 */ uint32_t no_battery_thresh_mv; /* VBAT 低于此值判定断连(默认 1000mV) */ uint32_t no_battery_hold_ms; /* 持续低于阈值多久判断连(默认 1000ms) */ } ChargeSM_Config; /*=========================================================================== * 状态机决策输出 *===========================================================================*/ typedef enum { SM_ACTION_NONE = 0, /* 无操作 */ SM_ACTION_SET_PRECHG = 1, /* 切换到预充(低电流) */ SM_ACTION_SET_CC = 2, /* 切换到 CC 快充 */ SM_ACTION_STOP = 3, /* 停止充电(充电完成或故障) */ SM_ACTION_RESTART = 4, /* 重新开始充电(再充电触发) */ } SMD_Action; typedef struct { SMD_Action action; uint32_t target_current_ma; /* 目标充电电流 */ char reason[32]; /* 决策原因描述 */ } ChargeSM_Decision; /*=========================================================================== * 状态机实例 *===========================================================================*/ typedef struct { ChargeState state; ChargeSM_Config cfg; /* 内部计时器(累加 tick_ms)*/ uint32_t elapsed_ms; /* 最后一次状态切换时间戳 */ uint32_t state_enter_ms; /* CV 阶段检测到电流低于终止阈值后已持续的时间 */ uint32_t term_hold_ms; /* 上一次输出的决策 */ SMD_Action last_action; /* 电池断连检测计时 */ uint32_t no_bat_hold_ms; } ChargeSM; /*=========================================================================== * 对外接口 *===========================================================================*/ /** * @brief 用默认 7S 参数初始化状态机 * 满充 29.4V,CC 1A,预充 200mA,终止 100mA */ void ChargeSM_InitDefault(ChargeSM *sm); /** * @brief 用自定义参数初始化 */ void ChargeSM_Init(ChargeSM *sm, const ChargeSM_Config *cfg); /** * @brief 主循环调用,输入 ADC 读数和 NTC 温度,输出决策 * @param vbat_mv: 电池电压 mV * @param ibat_ma: 充电电流 mA * @param temp_c: NTC 温度(无传感器传 25) * @return 决策结果(是否需要改变充电参数) */ ChargeSM_Decision ChargeSM_Run(ChargeSM *sm, int32_t vbat_mv, int32_t ibat_ma, int8_t temp_c); /** * @brief 手动触发故障(从外部故障指示器调用) */ void ChargeSM_ForceFault(ChargeSM *sm, const char *reason); /** * @brief 获取当前状态字符串 */ const char* ChargeSM_StateStr(ChargeState s); #endif