[电池电源管理] 中颖 SH367309 锂电池保护板方案 —— 软件架构与关键模块深度解析

[复制链接]
261|1
Haizangwang 发表于 2025-11-5 17:15 | 显示全部楼层 |阅读模式
一、方案概述
1.1 定位
SH367309 是中颖微电子(Sino Wealth)面向 3~5 串锂离子/聚合物电池包推出的数字-模拟混合保护 IC。
官方参考设计包含:

硬件:原理图 + PCB(4 层,过流/短路/温度/平衡保护)
软件:Cortex-M3 内核,STM32F103 为主控,IAR 5.4 / Keil 5 双工程
协议:SMBus 1.1 兼容,支持 SBS 1.1 指令集(0x00~0x6F)
1.2 软件仓库结构
合并后共 135 个文件,总代码行 ≈ 2.1 万行。关键目录:

├─ CORE/ // CMSIS + 启动文件
├─ HARDWARE/ // 板级驱动(ADC、LCD、KEY、EXTI、FLASH…)
├─ USER/ // 业务逻辑(保护算法、SMBus、电量计、平衡)
├─ PROJECT/ // IAR / Keil 工程文件
└─ DOC/ // 寄存器手册、SMBus 指令表、校准方法

================================================================
二、硬件抽象层(HAL)设计
2.1 时钟与低功耗策略

运行频率:72 MHz(外部 8 M 晶振 + PLL)
低功耗顺序:
关闭外设时钟(ADC、DMA、LCD)
配置 Standby 模式,RTC 唤醒周期 5 s
唤醒源:ALARM 引脚(PB0 下降沿)+ RTC 闹钟
唤醒后 2 ms 内恢复 PLL,保证 SMBus 第一时间响应主机
2.2 关键外设驱动
ADC(adc.c)

3 通道循环采样:
CH0 → 电池组电压(分压 1/11)
CH1 → 充电电流(INA199,±50 A,增益 100)
CH4 → 温度(NTC 10 k,β=3435)
采样时序:定时器 6 触发,20 ms 周期,DMA 双缓冲,硬件平均 8 点
校准:2 点线性修正(增益 & 零点),系数保存在 Flash 0x0800_F000 固定表
Flash 模拟 EEPROM(stmflash.c)

采用“扇区交换 + 双备份”机制,保证掉电不丢数据
写流程:
读出整个 2 kB 扇区 → RAM
修改对应偏移 → CRC16 校验
擦除扇区 → 回写 → 第二备份区镜像
寿命:每扇区 10 k 次擦写,实测 25 °C 下 > 6 万次
LCD 驱动(lcd.c)

支持 9341/9325/5310/5510 等 8 种驱动 IC,自动识别 ID
提供快速打点函数 LCD_Fast_DrawPoint(),采用“寄存器地址连续写”模式,刷 320×240 全屏 < 120 ms
字体:12×6、16×8、24×12 三级点阵,支持 ASCII 与自定义图标(电量格、充放电箭头)
================================================================
三、保护算法与状态机
3.1 状态总览
整个电池包运行状态由主任务轮询 + 中断事件共同驱动,状态图如下:

    ┌──────────┐
    │  POWER_ON│
    └────┬─────┘
         │初始化
    ┌────▼─────┐
    │  STANDBY │◄──────────┐
    └────┬─────┘           │
         │按键/充电器插入  │I²C 指令
    ┌────▼─────┐           │
    │  NORMAL  │           │
    └────┬─────┘           │



故障检测 │ │
┌────▼─────┐ │
│ FAULT │───────────┘
└────┬─────┘ 清除故障
┌────▼─────┐
│ SLEEP │<-- 无通信 3 s
└──────────┘

3.2 保护项与阈值(可配置)
过充检测:

一级 4.23 V/3 s、二级 4.25 V/2 s、三级 4.30 V/1 s
恢复 4.10 V/3 s 滞后
过放检测:

一级 2.90 V/5 s、二级 2.80 V/3 s、三级 2.70 V/1 s
恢复 3.40 V/3 s 滞后
充/放电过流(软件):

充电 25 A/60 s、50 A/5 s
放电 105 A/122 s、140 A/32 s、175 A/12 s
采用 4 点滑动平均 + 峰值滤波,防止误触发
高低温:

充电高温 55 °C、低温 0 °C
放电高温 65 °C、低温 -20 °C
采用 10 k NTC,查表法(1 °C 步进)+ 线性插值
3.3 平衡算法

被动平衡,开启电压 4.10 V,压差 100 mV
策略:最高单体 > 开启电压 且 与最低单体差 > 压差 → 打开 MOSFET 旁路 200 mA
平衡期间采样保持,防止电压跌落误判
================================================================
四、SMBus 协议栈实现
4.1 链路层

物理层:PB8=SCL、PB9=SDA,开漏 5 V 容忍,上拉 4.7 k
速率:100 kHz 标准模式,7 位地址 0x16(可改 EEPROM)
中断:EV = I2C1_EV_IRQHandler、ER = I2C1_ER_IRQHandler,支持多主机仲裁
4.2 协议层

支持 Quick Command、Send Byte、Receive Byte、Write Byte/Word、Read Byte/Word、Block Read
寄存器映射兼容 SBS 1.1:
0x00~0x1F – 电量计(Voltage、Current、Temperature、RemainingCapacityAlarm…)
0x20~0x3F – 状态/控制(BatteryStatus、BatteryMode、ChargingCurrent…)
0x40~0x5F – 制造商信息(ManufacturerName、DeviceName、DeviceChemistry…)
0x60~0x6F – 扩展指令(SafetyAlert、SafetyStatus、PFAlert…)
4.3 代码流程
主机写:
Start → 地址+W → ACK → 命令码 → ACK → 数据低 → ACK → 数据高 → ACK → Stop
→ 触发 I2C1_EV_IRQHandler → 根据命令码查表 → 写入 RAM 缓存 → 置位 update_flag

主机读:
Start → 地址+R → ACK → 返回数据低 → ACK → 数据高 → NACK → Stop
→ 事先在 update_flag 为真时把数据准备好,中断里直接取

================================================================
五、电量计量(Coulomb Counter)
5.1 电流采样

16 bit ADC,±50 A 量程,LSB = 1.526 mA
硬件 8 点平均后,软件再做 4 点滑动平均,有效分辨率 ≈ 0.1 mA
零偏校准:休眠前 1 s 平均电流 < 5 mA 即视为“零”,写入 EEPROM 偏移
5.2 容量学习

满充学习:
条件:单体 4.20 V + 电流 < 0.05 C + 温度 10~45 °C
动作:将 FCC(FullChargeCapacity)更新为 RemainingCapacity
满放学习:
条件:单体 2.75 V + 电流 < 0.1 C
动作:将 DesignCapacity 与 PassedCharge 比较,修正 CC Gain
周期计数:每完成 1 次 DOD>60% 的循环,CycleCount++,同时衰减 FCC(默认 80%@500 次)
5.3 温度补偿

容量温度系数:-0.5%/°C(<25 °C)、-0.3%/°C(>25 °C)
内阻温度系数:-0.7%/°C,用于预测最大允许电流
================================================================
六、Flash 数据映射(0x0800_F000)
扇区 0(1 kB)—— 系统参数
扇区 1(1 kB)—— 用户校准
扇区 2(1 kB)—— 平衡历史
扇区 3(1 kB)—— 循环计数 & 异常日志

关键数据结构(共 512 B,双备份)见 flash.c 中 const dataflash[],包含:

设计容量 / 满充容量 / 循环阈值
单节过充、过放、过流、温度阈值
AFE MTP 区域 26 B(SH367309 内部寄存器初值)
校准系数:电压增益、电流增益、零点、温度偏移
制造商字符串、序列号、生产日期(BCD 码)
尾部 2 B 校验:0x5AA5,上电 CRC 校验失败则恢复出厂默认值
================================================================
七、启动流程与异常处理
7.1 上电时序(startup_stm32f10x_hd.s)
① 初始化 MSP = __initial_sp(0x2000_0800)
② 调用 SystemInit() → 打开 HSE → PLL 9 倍频 → 72 MHz
③ 复制 .data → RAM,清空 .bss
④ 调用 __main → 最终进入 main()

7.2 main() 主循环(伪代码)

int main(void)
{
    InitClock();        // 72 MHz
    InitGPIO();         // 高驱 MOSFET 引脚
    InitADC();          // 3 通道 DMA
    InitSMBus();        // 100 kHz
    InitLCD();          // 显示 **
    ReadFlashParam();   // 加载 0x0800_F000
    SH367309_Init();    // AFE 寄存器 + MTP
    while (1)
    {
        RefreshADC();   // 20 ms
        ProtectFSM();   // 过充/过放/过流/温度
        BalanceCtrl();  // 需要平衡?
        UpdateSOC();    // 库仑计
        RefreshLCD();   // 1 s
        EnterSleep();   // 无通信 3 s
    }
}



7.3 异常向量

HardFault:保存 R0~R3、MSP、PSP 到 Backup SRAM,重启
NMI:SH367309 ALARM 中断,标记 bAFE** = 1,主循环读取 AFE 状态寄存器
I²C 错误:总线死锁检测,超过 5 ms 无应答则复位 I2C 外设
================================================================
八、开发与调试指南
8.1 编译选项

IAR:Options → General Options → Library Configuration → Full
Keil:Target → Use MicroLIB 取消,否则 printf 重定向异常
优化等级:建议 -O2,若需单步调试请改为 -O0
8.2 在线升级

预留 8 kB BootLoader(0x0800_0000~0x0800_1FFF),支持 SMBus 0x7E 进入 ISP
升级流程:
① 主机发送 0x7E 0x02 0x00 0x00 0x00 0x00
② Boot 返回 0x55 0xAA 就绪
③ 每帧 64 B,带包序号 + CRC16,失败重传 3 次
④ 升级完成写入 MagicWord(0x0800_1FF0 = 0x55AA),软复位
8.3 常见问题速查

LCD 白屏:ID 识别失败 → 检查 SPI 模式(9341 需 8 位 SPI + 16 位并口)
电流漂移:零偏未校准 → 进入休眠前确保 < 5 mA,重新 Learn Zero
SMBus 无应答:上拉电阻过大 → 改为 3.3 V 供电时 2.2 k
平衡不开启:压差未到 100 mV → 调低阈值或延长采样窗口
================================================================
九、结语
本文从源码级对 SH367309 锂电池保护板的 CMSIS 层、板级驱动、保护算法、SMBus 协议、电量计量、Flash 数据映射及异常处理进行了全流程梳理。
开发者可据此快速定位业务逻辑、二次开发新保护项或移植到更高串数平台。如需进一步深入(如 SH367309 寄存器级配置、NTC 查表生成脚本、BootLoader 源码),可继续基于“0x0800_F000”固定表与“protect_fsm()”状态机进行扩展。


————————————————
版权声明:本文为CSDN博主「QQ27699885」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/2501_93693767/article/details/153770988

我是一颗胖蘑菇 发表于 2025-11-6 15:44 | 显示全部楼层
保护算法和状态机的设计非常关键,这篇文章提供了清晰的流程图和详细的参数设置,有助于理解整个保护机制。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

95

主题

300

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部