引言
在新能源领域飞速发展的今天,电池管理系统(BMS)作为核心组件,直接决定了电池组的安全性、可靠性与使用寿命。对于 12 串(12S)锂电池组应用,如轻型电动车、工业储能设备、便携式电源等,选择一款高性能的模拟前端(AFE)芯片是 BMS 设计的关键。TI 推出的 BQ7694003 凭借其强大的多串电池监测能力、完善的硬件保护机制、灵活的通信接口及低功耗设计,成为 12S BMS 前端设计的优选方案。
BQ7694003 作为 bq769x0 家族的核心成员,支持 9-15 串锂电池监测,完美适配 12S 电池组需求。其集成了 14 位高精度 ADC、16 位库仑计数器、内置均衡驱动、多重硬件保护及 I2C 通信接口,能实现对电池组电压、电流、温度的精准监测,同时提供过压、欠压、过流、短路等全方位保护。本文将结合 TI 官方技术文档,从硬件设计、软件驱动两大维度,详细拆解 BQ7694003 实现 12S BMS 前端 AFE 的完整方案,内容涵盖硬件架构、关键参数、电路设计、PCB 布局、寄存器配置、驱动代码实现等,为工程师提供一站式设计参考。
一、BQ7694003 核心特性与 12S 应用适配性分析
1.1 芯片核心特性总览
BQ7694003 作为高集成度 AFE 芯片,其特性完美匹配 12S BMS 设计需求,核心参数如下表所示:
| 电池串数支持 | 9-15 串锂离子 / 磷酸铁锂电池 | 直接覆盖 12S 配置,无需额外扩展 |
| 电压监测精度 | 25℃时 ±10mV(3.6-4.3V),全温域 ±40mV | 确保 12S 电池组单体电压均衡性监测精准 |
| ADC 分辨率 | 14 位差分 ADC,LSB=382µV | 微小电压变化可识别,提升均衡控制精度 |
| 电流监测 | 16 位库仑计数器,LSB=8.44µV,量程 ±270mV | 精准计量 12S 电池组充放电容量,误差 < 1% |
| 温度监测 | 支持 3 路外部热敏电阻 + 1 路内部芯片温度 | 全面覆盖 12S 电池组关键测温点 |
| 均衡功能 | 内置均衡 FET,支持外部均衡扩展,均衡电流可达 5mA | 满足 12S 电池组单体均衡需求,延长循环寿命 |
| 硬件保护 | 过压(OV)、欠压(UV)、过流放电(OCD)、短路放电(SCD)、二次保护检测 | 多重保护 12S 电池组安全,避免热失控 |
| 通信接口 | I2C 兼容接口(支持 CRC 校验),速率高达 100kHz | 稳定传输 12S 电池组监测数据,抗干扰能力强 |
| 工作电压 | 单节电池 2.0-5.0V,总电压最高 108V | 适配 12S 锂电池 42V(满电)工作范围 |
| 功耗特性 | 正常模式(ADC+CC 开启)典型 130µA,SHIP 模式 0.6µA | 降低 12S 电池组静态功耗,延长待机时间 |
| 封装形式 | 44 引脚 TSSOP 封装(11.0mm×4.4mm) | 小尺寸设计,适合 BMS 紧凑布局 |
1.2 12S 应用适配性关键分析
12S 锂电池组(以锂离子电池为例)的典型参数为:单节标称电压 3.6V,满电电压 4.2V,总满电电压 50.4V;单节欠压阈值 2.5V,总欠压阈值 30V。BQ7694003 的硬件参数与 12S 电池组特性高度匹配:
- 电压范围适配:芯片单节电池监测范围 2.0-5.0V,完全覆盖 12S 电池组单节工作电压区间,总电压支持最高 108V,满足 50.4V 满电需求。
- 精度适配:14 位 ADC 分辨率可精准识别单节电池 0.382mV 的电压变化,配合 ±10mV 的测量精度,能有效监测 12S 电池组的单体电压不均衡问题,为均衡控制提供可靠依据。
- 保护功能适配:支持可编程 OV/UV 阈值(OV:3.15-4.7V,UV:1.58-3.1V),可针对 12S 电池组特性设置合适的保护阈值(如 OV=4.3V,UV=2.5V);OCD/SCD 保护支持宽范围阈值设置,适配 12S 电池组不同应用场景的电流保护需求。
- 均衡功能适配:内置均衡驱动支持每节电池独立均衡,均衡占空比约 70%(每 250ms 周期),可有效消除 12S 电池组单体电压差异,提升电池组容量利用率。
二、12S BMS 前端 AFE 硬件设计详解
2.1 硬件架构总体设计
BQ7694003 基于 “监测 – 保护 – 通信 – 均衡” 一体化架构,12S BMS 前端硬件架构如下图所示,核心包括电池连接接口、电源电路、监测电路(电压 / 电流 / 温度)、均衡电路、保护电路、通信电路及辅助电路。
硬件架构各模块功能分工如下表:
| 电池连接接口 | 实现 12S 电池组与芯片的可靠连接 | 电池正负极端子、防反接二极管 |
| 电源电路 | 为芯片及外围电路提供稳定电源 | REGSRC 供电电路、LDO 输出电路、滤波电容 |
| 电压监测电路 | 采集 12S 单体电池电压及总电压 | 分压电阻、滤波电容、TVS 管 |
| 电流监测电路 | 采集电池组充放电电流 | 采样电阻、滤波电路、差分放大电路(可选) |
| 温度监测电路 | 采集电池组及芯片温度 | 10kΩ NTC 热敏电阻、下拉电阻 |
| 均衡电路 | 实现单体电池均衡放电 | 内置均衡 FET、外部均衡电阻(可选) |
| 保护电路 | 硬件级故障响应 | 放电 / 充电 FET 驱动、熔断丝、TVS 管 |
| 通信电路 | 与 MCU 进行数据交互 | I2C 总线、上拉电阻、ESD 保护器件 |
| 辅助电路 | 芯片复位、Boot 启动 | Boot 按键、复位电路、滤波电容 |
2.2 关键参数确定(12S 配置)
在硬件设计前,需根据 12S 电池组特性(以锂离子电池为例)确定 BQ7694003 的关键配置参数,确保芯片工作在最优状态:
| 单节电池电压范围 | 2.5V(欠压)-4.3V(过压) | 芯片 UV_TRIP/OV_TRIP 寄存器编程依据 |
| 总电压范围 | 30V(欠压)-51.6V(过压) | 芯片 BAT 引脚耐压(最高 108V)满足需求 |
| 充放电电流 | 持续放电 10A,峰值放电 20A,充电 5A | 采样电阻选型、OCD/SCD 阈值设置依据 |
| 均衡电流 | 5mA(内置)/20mA(外部扩展) | 均衡电阻选型依据(内置均衡时 R=V/I≈800Ω) |
| 温度监测范围 | -40℃-85℃ | 适配 NTC 热敏电阻(103AT)特性 |
| I2C 通信速率 | 100kHz(标准模式) | 芯片默认支持,兼容多数 MCU |
| 工作模式功耗 | 正常模式 < 200µA,休眠模式 < 1µA | 满足 BMS 低功耗需求 |
2.3 核心硬件电路设计
2.3.1 电池连接与电压监测电路
12S 电池组通过 VC0-VC15 引脚与 BQ7694003 连接,芯片采用 5 单元组结构(VC1-VC5、VC6-VC10、VC11-VC15),12S 配置需使用前 12 个单体电压监测通道(VC0-VC11),其中 VC0 为参考地,VC1-VC11 分别对应 12S 电池组的 1-12 节正极。
电路设计要点:
- 每节电池串联限流电阻 Rc(建议 40-1kΩ),用于限制输入电流,保护芯片引脚;
- 并联滤波电容 Cc(0.1-1µF),滤除电压噪声,确保 ADC 采样稳定;
- 在电池组正负极及关键节点并联 TVS 管(如 SMBJ60A),防止 ESD 冲击;
- 组间节点(如 VC5、VC10)需遵循芯片 5 单元组架构,确保电源域隔离。
12S 电压监测电路参数表:
| 限流电阻 Rc | 100Ω/0805/1% | 限制单体电压输入电流 | 靠近芯片 VC 引脚,减小寄生电感 |
| 滤波电容 Cc | 0.1µF/50V/X7R | 滤除电压纹波 | 紧邻 Rc 与 GND,短路径布线 |
| TVS 管 | SMBJ60A(单节)、SMBJ60CA(总压) | ESD 保护 | 靠近电池接口,并联在电源与 GND 之间 |
| 组间隔离二极管 | 1N4148W | 防止组间电压串扰 | 串联在 VC5、VC10 节点 |
2.3.2 电流监测电路
BQ7694003 通过 SRP(负电流采样)和 SRN(正电流采样)引脚监测电池组充放电电流,采用串联采样电阻 Rsns 的方案,电流流过 Rsns 产生的压差被芯片内部 16 位库仑计数器采集,进而计算充放电容量。
电路设计公式:
- 采样电阻 Rsns 选型:Rsns = V_FSR / I_Max,其中 V_FSR 为芯片电流采样满量程(±200mV),I_Max 为 12S 电池组最大放电电流;
- 示例:12S 电池组最大放电电流 20A,Rsns=200mV/20A=10mΩ,选型 10mΩ/2W/1% 合金电阻。
电流监测电路组件表:
| 采样电阻 Rsns | 10mΩ/2W/1% | 产生电流采样压差 | 采用低温度系数合金电阻,大电流路径短而宽 |
| 滤波电阻 Rfilt | 100Ω | 滤除电流噪声 | 串联在 SRP/SRN 引脚与 Rsns 之间 |
| 滤波电容 Cfilt | 0.1µF | 稳定采样电压 | 并联在 SRP-SRN 之间,靠近芯片引脚 |
| ESD 保护 | TVS 管 SMBJ6.5CA | 保护采样引脚 | 并联在 SRP、SRN 与 GND 之间 |
2.3.3 温度监测电路
BQ7694003 支持 3 路外部热敏电阻(TS1-TS3),12S BMS 建议配置 2-3 路温度监测:TS1 监测电池组中部温度,TS2 监测放电 FET 温度,TS3 监测芯片自身温度(可选)。
电路设计要点:
- 采用 10kΩ NTC 热敏电阻(103AT),符合芯片内置 10kΩ 上拉电阻匹配;
- 热敏电阻串联 1kΩ 限流电阻,防止引脚过流;
- 布线远离功率器件,避免热传导干扰;
- TS1-TS3 分别对应芯片 TS1、TS2、TS3 引脚,参考地分别为 VSS、VC5X、VC10X。
温度监测电路参数表:
| NTC 热敏电阻 | 103AT(25℃时 10kΩ) | 电池组中部、FET 附近 | 一端接 TS 引脚,一端接对应参考地 |
| 限流电阻 | 1kΩ/0805/1% | PCB 板上靠近 TS 引脚 | 串联在 TS 引脚与热敏电阻之间 |
| 滤波电容 | 0.01µF/25V | 紧邻热敏电阻 | 并联在热敏电阻两端 |
2.3.4 电源与复位电路
BQ7694003 的电源供应包括 BAT 引脚(电池组总压输入)和 REGSRC 引脚(内部 LDO 输入),12S 电池组总压约 30-51.6V,需通过电源电路为芯片提供稳定供电。
电源电路设计:
- BAT 引脚:串联滤波电阻 Rf(100Ω)和并联滤波电容 Cf(10µF),滤除总压噪声;
- REGSRC 引脚:对于 12S 配置,推荐使用源极跟随器电路(N 沟道 MOSFET + 稳压二极管),将 BAT 电压降至 12-15V,为内部 LDO 供电;
- REGOUT 引脚:输出 2.5V 或 3.3V(工厂预设),为外部 MCU 或辅助电路供电,需并联 4.7µF 滤波电容;
- Boot 电路:通过 TS1 引脚实现芯片启动,配置 Boot 按键(按下时 TS1 引脚电压 > 300mV),用于从 SHIP 模式唤醒芯片。
电源电路组件表:
| BAT 滤波电阻 Rf | 100Ω/1W | 限制总压输入电流 | 靠近 BAT 引脚,串联在电池正极与 BAT 之间 |
| BAT 滤波电容 Cf | 10µF/63V/X7R | 滤除总压纹波 | 紧邻 BAT 引脚与 VSS,低 ESR 电容 |
| 源极跟随器 MOSFET | BSS123(N 沟道) | 降压至 REGSRC 电压 | VGS 阈值 < 4V,导通电阻 < 1Ω |
| 稳压二极管 | MMSZ15T1G(15V) | 稳定 REGSRC 电压 | 并联在 MOSFET 栅极与 VC5X 之间 |
| Boot 按键 | 6×6mm 轻触开关 | 芯片启动唤醒 | 一端接 TS1,一端接 VSS,串联 10kΩ 电阻 |
2.3.5 均衡电路
BQ7694003 内置 15 路均衡 FET,支持每节电池独立均衡,12S 配置需启用前 12 路均衡通道(对应 VC1-VC11)。均衡电路通过将高电压单体的电能通过均衡电阻释放,实现各单体电压均衡。
电路设计方案:
- 内置均衡:利用芯片内部均衡 FET,外部串联均衡电阻 Rbal(建议 1k-10kΩ),均衡电流 Ibal=V_Cell/Rbal,典型值 5mA;
- 外部均衡扩展(可选):对于需要更大均衡电流(如 20mA)的场景,可外接 P 沟道 MOSFET(如 FDY1002PZ),由芯片 VC 引脚电压控制 MOSFET 导通。
12S 均衡电路参数表:
| 内置均衡 | Rbal=2kΩ/1W | 约 2mA | 轻度不均衡(电压差 < 0.1V) |
| 内置均衡 | Rbal=1kΩ/2W | 约 4mA | 中度不均衡(电压差 0.1-0.3V) |
| 外部均衡 | MOSFET:FDY1002PZ,Rbal=470Ω/3W | 约 8mA | 重度不均衡(电压差 > 0.3V) |
2.3.6 保护与驱动电路
BQ7694003 提供 CHG(充电 FET 驱动)和 DSG(放电 FET 驱动)引脚,通过驱动外部 N 沟道 MOSFET 实现充放电回路的通断控制,配合芯片内部硬件保护机制,在故障时快速切断回路。
驱动电路设计要点:
- 选用低导通电阻(RDS (ON)<10mΩ)的 MOSFET,如 AOB290L(100V/18A);
- 栅极串联限流电阻 Rg(10-100Ω),限制栅极充电电流,防止 MOSFET 损坏;
- 并联续流二极管(如 MURS360T3G),保护 MOSFET 免受反向电压冲击;
- CHG 引脚需配置钳位电路(齐纳二极管 + 电阻),防止栅极过压。
保护驱动电路组件表:
| 放电 MOSFET | AOB290L(N 沟道) | 控制放电回路 | 并联 2 颗以增大电流容量,源极接地 |
| 充电 MOSFET | AOB290L(N 沟道) | 控制充电回路 | 串联在充电回路,漏极接电池正极 |
| 栅极电阻 Rg | 47Ω/0805 | 限制栅极电流 | 靠近 MOSFET 栅极,短路径布线 |
| 续流二极管 | MURS360T3G(600V/3A) | 吸收反向尖峰电压 | 并联在 MOSFET 漏源极之间 |
| 钳位齐纳二极管 | MMSZ16T1G(16V) | 保护 CHG/DSG 引脚 | 并联在 CHG/DSG 引脚与 VSS 之间 |
2.3.7 通信电路
BQ7694003 采用 I2C 兼容接口与 MCU 通信,支持 7 位从机地址(默认 0x08,可通过工厂配置为 0x18),支持 CRC 校验功能,提升通信可靠性。
通信电路设计要点:
- SDA(P41)和 SCL(P40)引脚串联 22Ω 限流电阻,防止总线电流过大;
- 并联 10kΩ 上拉电阻至 REGOUT(2.5V/3.3V),确保总线空闲时为高电平;
- 靠近芯片引脚放置 0.1µF 滤波电容,滤除通信噪声;
- 总线长度超过 10cm 时,需在总线两端并联 120Ω 终端电阻。
通信电路组件表:
| 限流电阻 | 22Ω/0805 | 保护 I2C 引脚 | 靠近芯片 SDA/SCL 引脚 |
| 上拉电阻 | 10kΩ/0805/1% | 确保总线空闲电平 | 靠近 MCU I2C 引脚,缩短供电路径 |
| 滤波电容 | 0.01µF/25V | 滤除通信噪声 | 并联在 SDA/SCL 与 GND 之间 |
| 终端电阻 | 120Ω/0805 | 匹配总线阻抗 | 仅在长距离通信时添加,位于总线两端 |
2.4 PCB 布局设计指南
BQ7694003 的 PCB 布局直接影响 12S BMS 的性能与稳定性,需遵循 “分区布局、短路径布线、强弱电隔离” 原则,核心布局要求如下:
2.4.1 布局分区设计
| 模拟区 | 芯片 BQ7694003、电压采样电路、温度监测电路 | PCB 中心区域 | 与功率区隔离≥2mm |
| 功率区 | 充放电 MOSFET、采样电阻 Rsns、电池接口 | PCB 边缘区域 | 大功率器件远离模拟区,预留散热空间 |
| 通信区 | I2C 总线、MCU 接口、辅助电路 | 靠近 MCU 一侧 | 通信线远离功率线,避免干扰 |
| 电源区 | REGSRC 供电电路、LDO 输出电路 | 靠近芯片电源引脚 | 电源滤波电容紧邻芯片,短路径供电 |
2.4.2 关键布局规则
2.4.3 12S BMS PCB 布局检查表
| 模拟地与功率地隔离 | 隔离距离≥2mm,单点接地 | 视觉检查 + 万用表测量 |
| 功率路径铜箔宽度 | ≥5mm(20A 电流),厚度≥2oz | 卡尺测量 + 电流测试 |
| 采样电阻布局 | 两端铜箔对称,远离发热器件 | 视觉检查 + 温度测试 |
| 滤波电容布局 | Cc 紧邻 Rc 与 GND,ESR<100mΩ | 阻抗分析仪测量 |
| 通信线长度 | I2C 总线长度≤15cm,无直角布线 | 视觉检查 + 示波器测量 |
| 散热设计 | MOSFET 温度≤85℃(20A 放电) | 红外测温仪测量 |
三、BQ7694003 软件驱动设计(基于 MCU)
BQ7694003 的软件驱动核心是通过 I2C 接口与芯片寄存器交互,实现电池组参数采集、均衡控制、保护配置、故障处理等功能。本节以 STM32F103C8T6 为例,详细介绍驱动软件的架构设计、寄存器配置、核心功能代码实现。
3.1 软件驱动架构总览
驱动软件采用分层设计,分为底层驱动层、寄存器操作层、功能应用层,架构如下表所示:
| 底层驱动层 | I2C 通信驱动、GPIO 配置、延时函数 | I2C 初始化、I2C 读写函数、CRC 计算函数 |
| 寄存器操作层 | 寄存器读写、位操作、参数解析 | 电压 / 电流 / 温度读取函数、保护阈值配置函数 |
| 功能应用层 | 数据采集、均衡控制、故障处理、状态机管理 | 电池组状态监测、均衡策略执行、保护响应函数 |
驱动软件运行流程:
3.2 核心寄存器配置(12S 专用)
BQ7694003 的寄存器分为状态寄存器、控制寄存器、保护寄存器、数据寄存器等,12S 配置需重点配置以下寄存器:
3.2.1 寄存器地址与功能表(核心部分)
| 0x00 | SYS_STAT | 系统状态寄存器,显示故障信息 | 0x00(无故障) |
| 0x01 | CELLBAL1 | 1-5 节均衡控制 | 0x00(默认关闭) |
| 0x02 | CELLBAL2 | 6-10 节均衡控制 | 0x00(默认关闭) |
| 0x03 | CELLBAL3 | 11-15 节均衡控制 | 0x00(默认关闭) |
| 0x04 | SYS_CTRL1 | 系统控制 1:ADC 使能、温度源选择 | 0x10(ADC 使能,外部热敏电阻) |
| 0x05 | SYS_CTRL2 | 系统控制 2:CC 使能、FET 控制 | 0x63(CC 使能,CHG/DSG 使能) |
| 0x06 | PROTECT1 | 保护 1:SCD 阈值 / 延迟配置 | 0x8C(SCD 阈值 56mV,延迟 100µs) |
| 0x07 | PROTECT2 | 保护 2:OCD 阈值 / 延迟配置 | 0x5B(OCD 阈值 36mV,延迟 320ms) |
| 0x08 | PROTECT3 | 保护 3:OV/UV 延迟配置 | 0x50(OV 延迟 2s,UV 延迟 4s) |
| 0x09 | OV_TRIP | 过压阈值配置 | 0xC9(对应 4.3V 单节过压) |
| 0x0A | UV_TRIP | 欠压阈值配置 | 0x1A(对应 2.5V 单节欠压) |
| 0x0B | CC_CFG | 库仑计数器配置 | 0x19(默认最优配置) |
| 0x0C-0x29 | VC1-VC15 电压数据 | 单体电压原始数据 | 只读,需转换为实际电压 |
| 0x2A-0x2B | BAT 电压数据 | 总电压原始数据 | 只读,= 单体电压之和 |
| 0x2C-0x31 | TS1-TS3 温度数据 | 温度原始数据 | 只读,需转换为实际温度 |
| 0x32-0x33 | CC 数据 | 库仑计数原始数据 | 只读,需转换为实际容量 |
| 0x50-0x51 | ADCGAIN/ADCOFFSET | ADC 校准参数 | 工厂预设,只读 |
3.2.2 12S 配置关键寄存器详解
SYS_CTRL1(0x04):
- 位 4(ADC_EN):1 = 启用 ADC,0 = 禁用;12S 配置需置 1,确保电压 / 温度采样;
- 位 3(TEMP_SEL):0 = 内部温度,1 = 外部热敏电阻;12S 配置置 1,使用 TS1-TS3 监测外部温度;
- 位 1-0(SHUT_A/SHUT_B):关机控制位,需按特定序列写入进入 SHIP 模式。
SYS_CTRL2(0x05):
- 位 6(CC_EN):1 = 启用库仑计数器,0 = 禁用;12S 配置置 1,确保容量计量;
- 位 5(CC_ONESHOT):1 = 单次计数模式,0 = 连续计数模式;12S 配置置 0,持续监测电流;
- 位 1-0(DSG_ON/CHG_ON):1 = 启用放电 / 充电 FET,0 = 禁用;正常工作时置 1。
PROTECT1(0x06):
- 位 7(RSNS):0 = 低量程,1 = 高量程;12S 配置置 1,OCD/SCD 阈值翻倍;
- 位 4-3(SCD_D1-D0):SCD 延迟配置,0x01=100µs;
- 位 2-0(SCD_T2-T0):SCD 阈值配置,0x03=56mV(RSNS=1 时)。
PROTECT2(0x07):
- 位 6-4(OCD_D2-D0):OCD 延迟配置,0x05=320ms;
- 位 3-0(OCD_T3-T0):OCD 阈值配置,0x0A=36mV(RSNS=1 时)。
OV_TRIP(0x09)与UV_TRIP(0x0A):
- OV_TRIP 为过压阈值的 8 位中间值,映射关系:OV_Voltage = (OV_TRIP << 4 | 0x08) * GAIN + OFFSET;
- UV_TRIP 为欠压阈值的 8 位中间值,映射关系:UV_Voltage = (UV_TRIP << 4) * GAIN + OFFSET;
- 12S 配置推荐:OV_TRIP=0xC9(4.3V),UV_TRIP=0x1A(2.5V)。
3.3 底层驱动实现(I2C+CRC)
3.3.1 I2C 接口配置
STM32F103C8T6 的 I2C1 接口(PB6=SCL,PB7=SDA)与 BQ7694003 通信,配置步骤如下:
c
运行
#include "stm32f10x.h"
#include "i2c.h"
// I2C初始化函数
void I2C1_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef I2C_InitStruct;
// 使能GPIO和I2C时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// 配置PB6(SCL)和PB7(SDA)为复用开漏输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// I2C配置
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0x00; // 主机模式,无需自身地址
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_ClockSpeed = 100000; // 100kHz
I2C_Init(I2C1, &I2C_InitStruct);
// 使能I2C1
I2C_Cmd(I2C1, ENABLE);
}
3.3.2 I2C 读写函数实现
BQ7694003 支持字节读写、字读写、块读写,且支持 CRC 校验,核心读写函数如下:
c
运行
#define BQ76940_ADDR 0x08 << 1 // I2C从机地址(7位地址左移1位,最低位为读写位)
// I2C写字节函数(无CRC)
void BQ76940_WriteByte(uint8_t regAddr, uint8_t data) {
// 等待I2C总线空闲
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
// 发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送从机地址+写命令
I2C_Send7bitAddress(I2C1, BQ76940_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// 发送寄存器地址
I2C_SendData(I2C1, regAddr);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送数据
I2C_SendData(I2C1, data);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送停止信号
I2C_GenerateSTOP(I2C1, ENABLE);
}
// I2C读字节函数(无CRC)
uint8_t BQ76940_ReadByte(uint8_t regAddr) {
uint8_t data = 0;
// 等待I2C总线空闲
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
// 发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送从机地址+写命令(写寄存器地址)
I2C_Send7bitAddress(I2C1, BQ76940_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// 发送寄存器地址
I2C_SendData(I2C1, regAddr);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 重新发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送从机地址+读命令
I2C_Send7bitAddress(I2C1, BQ76940_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
// 读取数据(关闭ACK,发送停止信号)
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
// 接收数据
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
data = I2C_ReceiveData(I2C1);
// 恢复ACK使能
I2C_AcknowledgeConfig(I2C1, ENABLE);
return data;
}
// I2C读字函数(16位数据,无CRC)
uint16_t BQ76940_ReadWord(uint8_t regAddr) {
uint16_t data = 0;
uint8_t highByte = 0, lowByte = 0;
highByte = BQ76940_ReadByte(regAddr); // 读取高8位
lowByte = BQ76940_ReadByte(regAddr + 1); // 读取低8位
data = (highByte << 8) | lowByte;
return data;
}
3.3.3 CRC 校验函数实现
BQ7694003 支持 8 位 CRC 校验,多项式为 X⁸+X²+X+1(密钥 0x07),用于增强 I2C 通信可靠性,CRC 计算函数如下:
c
运行
// CRC8计算函数(多项式:X^8 + X^2 + X + 1,密钥0x07)
uint8_t CRC8_Calculate(uint8_t *ptr, uint8_t len, uint8_t key) {
uint8_t crc = 0;
uint8_t i, j;
for(i = 0; i < len; i++) {
crc ^= ptr[i];
for(j = 0; j < 8; j++) {
if(crc & 0x80) {
crc = (crc << 1) ^ key;
} else {
crc <<= 1;
}
}
}
return crc;
}
// 带CRC的I2C写字节函数
void BQ76940_WriteByteWithCRC(uint8_t regAddr, uint8_t data) {
uint8_t crcBuf[3];
uint8_t crc;
// 构造CRC计算缓冲区:从机地址(写)、寄存器地址、数据
crcBuf[0] = BQ76940_ADDR;
crcBuf[1] = regAddr;
crcBuf[2] = data;
// 计算CRC
crc = CRC8_Calculate(crcBuf, 3, 0x07);
// 等待I2C总线空闲
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
// 发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送从机地址+写命令
I2C_Send7bitAddress(I2C1, BQ76940_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// 发送寄存器地址
I2C_SendData(I2C1, regAddr);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送数据
I2C_SendData(I2C1, data);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送CRC值
I2C_SendData(I2C1, crc);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送停止信号
I2C_GenerateSTOP(I2C1, ENABLE);
}
// 带CRC的I2C读字节函数
uint8_t BQ76940_ReadByteWithCRC(uint8_t regAddr) {
uint8_t data = 0, crc = 0;
uint8_t crcBuf[2];
// 等待I2C总线空闲
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
// 发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送从机地址+写命令(写寄存器地址)
I2C_Send7bitAddress(I2C1, BQ76940_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// 发送寄存器地址
I2C_SendData(I2C1, regAddr);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 重新发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送从机地址+读命令
I2C_Send7bitAddress(I2C1, BQ76940_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
// 读取数据
I2C_AcknowledgeConfig(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
data = I2C_ReceiveData(I2C1);
// 读取CRC值(关闭ACK,发送停止信号)
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
crc = I2C_ReceiveData(I2C1);
// 验证CRC
crcBuf[0] = BQ76940_ADDR | 0x01; // 从机地址+读命令
crcBuf[1] = data;
if(CRC8_Calculate(crcBuf, 2, 0x07) != crc) {
return 0xFF; // CRC校验失败,返回错误码
}
// 恢复ACK使能
I2C_AcknowledgeConfig(I2C1, ENABLE);
return data;
}
3.4 核心功能驱动实现
3.4.1 芯片初始化函数
芯片初始化包括唤醒芯片、配置保护阈值、启用 ADC 和库仑计数器等,12S 配置初始化函数如下:
c
运行
// BQ7694003 12S配置初始化函数
uint8_t BQ76940_Init(void) {
uint8_t ret = 0;
// 1. 唤醒芯片(通过TS1引脚发送Boot信号,此处假设MCU通过GPIO控制)
GPIO_SetBits(GPIOA, GPIO_Pin_0); // TS1引脚置高(>300mV)
Delay_ms(10); // 保持10ms
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // TS1引脚置低
// 2. 等待芯片启动完成(约10ms)
Delay_ms(20);
// 3. 读取芯片ID(可选,验证通信)
uint8_t sysStat = BQ76940_ReadByte(0x00);
if(sysStat == 0xFF) {
return 1; // 通信失败
}
// 4. 配置SYS_CTRL1:ADC使能,外部温度源
BQ76940_WriteByte(0x04, 0x10);
// 5. 配置SYS_CTRL2:CC使能,连续计数模式,CHG/DSG使能
BQ76940_WriteByte(0x05, 0x63);
// 6. 配置PROTECT1:SCD阈值56mV,延迟100µs,高量程
BQ76940_WriteByte(0x06, 0x8C);
// 7. 配置PROTECT2:OCD阈值36mV,延迟320ms
BQ76940_WriteByte(0x07, 0x5B);
// 8. 配置PROTECT3:OV延迟2s,UV延迟4s
BQ76940_WriteByte(0x08, 0x50);
// 9. 配置OV_TRIP:4.3V单节过压
BQ76940_WriteByte(0x09, 0xC9);
// 10. 配置UV_TRIP:2.5V单节欠压
BQ76940_WriteByte(0x0A, 0x1A);
// 11. 配置CC_CFG:默认最优配置0x19
BQ76940_WriteByte(0x0B, 0x19);
// 12. 清除故障状态
BQ76940_WriteByte(0x00, 0xFF); // 写入1清除所有故障位
return ret;
}
3.4.2 电压采集函数
12S 电池组电压采集包括 12 节单体电压和总电压,需读取 VC1-VC12 对应的寄存器(0x0C-0x1F),并通过 ADC 校准参数(GAIN/OFFSET)转换为实际电压:
c
运行
// 存储12节单体电压(单位:mV)
uint16_t cellVoltages[12] = {0};
// 存储总电压(单位:mV)
uint32_t totalVoltage = 0;
// 读取ADC校准参数(GAIN和OFFSET)
void BQ76940_ReadCalibParams(uint16_t *gain, int8_t *offset) {
uint8_t gain1 = BQ76940_ReadByte(0x50);
uint8_t gain2 = BQ76940_ReadByte(0x59);
uint8_t offsetReg = BQ76940_ReadByte(0x51);
// 计算GAIN:365 + (ADCGAIN<4:0>)*1 µV/LSB
uint16_t adcGain = ((gain1 & 0x0C) << 2) | ((gain2 & 0xE0) >> 5);
*gain = 365 + adcGain;
// 计算OFFSET:补码转换为mV
*offset = (int8_t)offsetReg;
}
// 采集12S单体电压
uint8_t BQ76940_ReadCellVoltages(void) {
uint16_t gain = 0;
int8_t offset = 0;
uint16_t adcValue = 0;
uint8_t i;
// 读取校准参数
BQ76940_ReadCalibParams(&gain, &offset);
// 读取12节单体电压(VC1-VC12对应寄存器0x0C-0x1F)
for(i = 0; i < 12; i++) {
adcValue = BQ76940_ReadWord(0x0C + 2*i); // 每节电压占2个寄存器
// 转换公式:V(mV) = (ADC值 * GAIN(µV/LSB) / 1000) + OFFSET(mV)
cellVoltages[i] = (adcValue * gain) / 1000 + offset;
// 电压范围校验(2000mV-4500mV)
if(cellVoltages[i] < 2000 || cellVoltages[i] > 4500) {
return 1; // 电压异常
}
}
// 计算总电压
totalVoltage = 0;
for(i = 0; i < 12; i++) {
totalVoltage += cellVoltages[i];
}
return 0;
}
3.4.3 电流采集函数
电流采集通过读取库仑计数器数据(0x32-0x33),转换为实际电流值,同时计算充放电容量:
c
运行
// 采样电阻值(单位:mΩ)
#define RSNS_MOHM 10
// 存储当前电流(单位:mA,正值放电,负值充电)
int32_t current = 0;
// 存储剩余容量(单位:mAh)
int32_t remainingCapacity = 0;
// 库仑计数器满量程(±270mV)
#define CC_FSR_MV 270
// 库仑计数器LSB(8.44µV)
#define CC_LSB_UW 8.44
// 采集电流值
uint8_t BQ76940_ReadCurrent(void) {
int16_t ccValue = 0;
int32_t voltage = 0;
// 读取库仑计数器16位数据(补码格式)
ccValue = (int16_t)BQ76940_ReadWord(0x32);
// 转换为采样电压:电压(µV) = ccValue * CC_LSB_UW
voltage = ccValue * CC_LSB_UW;
// 转换为电流:电流(mA) = 电压(µV) / 采样电阻(mΩ)
current = voltage / RSNS_MOHM;
// 电流范围校验(-30000mA~30000mA)
if(current < -30000 || current > 30000) {
return 1; // 电流异常
}
return 0;
}
// 计算剩余容量(假设Qmax=2000mAh)
void BQ76940_CalculateCapacity(void) {
static uint32_t lastTick = 0;
uint32_t currentTick = GetTickCount(); // 获取系统滴答计数器值(ms)
uint32_t deltaTime = currentTick – lastTick;
if(deltaTime > 0 && deltaTime < 1000) { // 每1ms更新一次容量
// 容量变化 = 电流(mA) * 时间(h) = 电流(mA) * deltaTime(s) / 3600
int32_t deltaCapacity = current * deltaTime / 3600;
remainingCapacity -= deltaCapacity;
// 容量限制在0~Qmax之间
if(remainingCapacity < 0) {
remainingCapacity = 0;
} else if(remainingCapacity > 2000) {
remainingCapacity = 2000;
}
lastTick = currentTick;
}
}
3.4.4 温度采集函数
温度采集支持 3 路外部热敏电阻,通过 14 位 ADC 数据转换为实际温度,采用 Steinhart-Hart 方程提高精度:
c
运行
// 存储3路温度(单位:℃)
int16_t temperatures[3] = {0};
// 热敏电阻参数(103AT:25℃时10kΩ,B值3950)
#define B_VALUE 3950
#define R_REF 10000 // 内部上拉电阻(10kΩ)
#define T_REF 298.15 // 参考温度(25℃,单位:K)
// ADC值转换为电阻值
uint32_t BQ76940_AdcToResistance(uint16_t adcValue) {
uint16_t gain = 0;
int8_t offset = 0;
uint32_t voltage = 0;
// 读取校准参数
BQ76940_ReadCalibParams(&gain, &offset);
// 转换为电压值(mV)
voltage = (adcValue * gain) / 1000 + offset;
// 计算热敏电阻电阻值:Rntc = R_REF * voltage / (V_REF – voltage),V_REF=3300mV
return (uint32_t)(R_REF * voltage / (3300 – voltage));
}
// 电阻值转换为温度(℃)
int16_t BQ76940_ResistanceToTemperature(uint32_t resistance) {
double tempK = 0;
double tempC = 0;
// B值方程:1/T = 1/T_REF + (1/B_VALUE) * ln(Rntc/R_REF)
tempK = 1 / (1/T_REF + log((double)resistance/R_REF)/B_VALUE);
tempC = tempK – 273.15;
return (int16_t)(tempC * 10); // 保留1位小数,单位:0.1℃
}
// 采集3路温度
uint8_t BQ76940_ReadTemperatures(void) {
uint16_t adcValue = 0;
uint32_t resistance = 0;
uint8_t i;
// 读取3路温度ADC数据(TS1-TS3对应寄存器0x2C-0x31)
for(i = 0; i < 3; i++) {
adcValue = BQ76940_ReadWord(0x2C + 2*i);
// 转换为电阻值
resistance = BQ76940_AdcToResistance(adcValue);
// 转换为温度
temperatures[i] = BQ76940_ResistanceToTemperature(resistance);
// 温度范围校验(-40℃~85℃)
if(temperatures[i] < -400 || temperatures[i] > 850) {
return 1; // 温度异常
}
}
return 0;
}
3.4.5 均衡控制函数
12S 电池组均衡控制采用 “电压差阈值触发” 策略,当单体电压差超过 50mV 时,启动高电压单体的均衡功能,均衡时间根据电压差动态调整:
c
运行
// 均衡阈值(单位:mV)
#define BALANCE_THRESHOLD 50
// 均衡使能标志
uint8_t balanceEnable = 1;
// 查找最高/最低电压及索引
void BQ76940_FindVoltageExtremes(uint16_t *maxVolt, uint8_t *maxIdx, uint16_t *minVolt, uint8_t *minIdx) {
uint8_t i;
*maxVolt = cellVoltages[0];
*maxIdx = 0;
*minVolt = cellVoltages[0];
*minIdx = 0;
for(i = 1; i < 12; i++) {
if(cellVoltages[i] > *maxVolt) {
*maxVolt = cellVoltages[i];
*maxIdx = i;
}
if(cellVoltages[i] < *minVolt) {
*minVolt = cellVoltages[i];
*minIdx = i;
}
}
}
// 均衡控制函数
void BQ76940_BalanceControl(void) {
uint16_t maxVolt = 0, minVolt = 0;
uint8_t maxIdx = 0, minIdx = 0;
uint8_t balanceReg1 = 0, balanceReg2 = 0, balanceReg3 = 0;
if(!balanceEnable) {
// 禁用均衡,关闭所有均衡通道
BQ76940_WriteByte(0x01, 0x00);
BQ76940_WriteByte(0x02, 0x00);
BQ76940_WriteByte(0x03, 0x00);
return;
}
// 查找最高/最低电压
BQ76940_FindVoltageExtremes(&maxVolt, &maxIdx, &minVolt, &minIdx);
// 电压差小于阈值,关闭均衡
if((maxVolt – minVolt) < BALANCE_THRESHOLD) {
BQ76940_WriteByte(0x01, 0x00);
BQ76940_WriteByte(0x02, 0x00);
BQ76940_WriteByte(0x03, 0x00);
return;
}
// 根据最高电压索引设置均衡通道
if(maxIdx < 5) {
// 1-5节,对应CELLBAL1(0x01)
balanceReg1 = 1 << maxIdx;
BQ76940_WriteByte(0x01, balanceReg1);
BQ76940_WriteByte(0x02, 0x00);
BQ76940_WriteByte(0x03, 0x00);
} else if(maxIdx < 10) {
// 6-10节,对应CELLBAL2(0x02)
balanceReg2 = 1 << (maxIdx – 5);
BQ76940_WriteByte(0x01, 0x00);
BQ76940_WriteByte(0x02, balanceReg2);
BQ76940_WriteByte(0x03, 0x00);
} else {
// 11-12节,对应CELLBAL3(0x03)
balanceReg3 = 1 << (maxIdx – 10);
BQ76940_WriteByte(0x01, 0x00);
BQ76940_WriteByte(0x02, 0x00);
BQ76940_WriteByte(0x03, balanceReg3);
}
// 均衡时间控制(每5秒检查一次电压差)
static uint32_t balanceTick = 0;
if(GetTickCount() – balanceTick > 5000) {
balanceTick = GetTickCount();
// 重新采集电压,检查均衡效果
BQ76940_ReadCellVoltages();
}
}
3.4.6 故障处理函数
故障处理通过读取 SYS_STAT 寄存器(0x00)识别故障类型,执行相应的保护动作(切断充放电 FET、上报故障等):
c
运行
// 故障状态枚举
typedef enum {
FAULT_NONE = 0,
FAULT_OV = 1 << 2, // 过压故障
FAULT_UV = 1 << 3, // 欠压故障
FAULT_OCD = 1 << 0, // 过流放电故障
FAULT_SCD = 1 << 1, // 短路放电故障
FAULT_XREADY = 1 << 5,// 内部芯片故障
FAULT_OVRD_ALERT = 1 << 4 // 外部Alert覆盖故障
} FaultType;
// 故障处理函数
void BQ76940_FaultHandler(void) {
uint8_t faultStat = BQ76940_ReadByte(0x00);
// 无故障
if(faultStat == FAULT_NONE) {
// 启用充放电FET
BQ76940_WriteByte(0x05, 0x63);
return;
}
// 过压故障:切断充电FET
if(faultStat & FAULT_OV) {
BQ76940_WriteByte(0x05, 0x61); // CHG_ON=0,DSG_ON=1
// 上报过压故障
printf("OV Fault! Cell Voltage: %d mV\\r\\n", cellVoltages[0]);
}
// 欠压故障:切断放电FET
if(faultStat & FAULT_UV) {
BQ76940_WriteByte(0x05, 0x62); // CHG_ON=1,DSG_ON=0
// 上报欠压故障
printf("UV Fault! Cell Voltage: %d mV\\r\\n", cellVoltages[0]);
}
// 过流/短路故障:切断充放电FET
if(faultStat & (FAULT_OCD | FAULT_SCD)) {
BQ76940_WriteByte(0x05, 0x60); // CHG_ON=0,DSG_ON=0
// 上报过流/短路故障
printf("OCD/SCD Fault! Current: %d mA\\r\\n", current);
}
// 内部芯片故障:复位芯片
if(faultStat & FAULT_XREADY) {
BQ76940_WriteByte(0x00, 0xFF); // 清除故障
Delay_ms(100);
BQ76940_Init(); // 重新初始化
// 上报内部故障
printf("XREADY Fault! Reset Chip\\r\\n");
}
// 清除故障(需在故障排除后执行)
Delay_ms(1000);
BQ76940_WriteByte(0x00, faultStat); // 写入故障位清除故障
}
3.5 主函数与状态机实现
主函数通过状态机管理 BMS 工作流程,包括初始化状态、正常工作状态、故障状态,周期性执行数据采集、均衡控制、故障处理:
c
运行
// BMS工作状态枚举
typedef enum {
BMS_STATE_INIT = 0,
BMS_STATE_NORMAL,
BMS_STATE_FAULT
} BmsState;
int main(void) {
BmsState bmsState = BMS_STATE_INIT;
uint8_t initRet = 0;
// 系统初始化
SystemInit();
SysTick_Config(SystemCoreClock / 1000); // 滴答定时器初始化,1ms中断
USART1_Init(115200); // 串口初始化,用于打印日志
I2C1_Init(); // I2C初始化
GPIO_Init(); // GPIO初始化(包括Boot引脚、LED等)
while(1) {
switch(bmsState) {
case BMS_STATE_INIT:
// 初始化BQ7694003
initRet = BQ76940_Init();
if(initRet == 0) {
printf("BQ76940 Init Success!\\r\\n");
bmsState = BMS_STATE_NORMAL;
} else {
printf("BQ76940 Init Fail! Retry…\\r\\n");
Delay_ms(1000);
}
break;
case BMS_STATE_NORMAL:
// 1. 采集单体电压(周期250ms)
static uint32_t voltageTick = 0;
if(GetTickCount() – voltageTick > 250) {
voltageTick = GetTickCount();
if(BQ76940_ReadCellVoltages() == 0) {
printf("Cell Voltages: ");
for(uint8_t i = 0; i < 12; i++) {
printf("%d ", cellVoltages[i]);
}
printf("Total: %d mV\\r\\n", totalVoltage);
} else {
printf("Cell Voltage Read Error!\\r\\n");
bmsState = BMS_STATE_FAULT;
}
}
// 2. 采集电流(周期100ms)
static uint32_t currentTick = 0;
if(GetTickCount() – currentTick > 100) {
currentTick = GetTickCount();
if(BQ76940_ReadCurrent() == 0) {
printf("Current: %d mA\\r\\n", current);
BQ76940_CalculateCapacity();
printf("Remaining Capacity: %d mAh\\r\\n", remainingCapacity);
} else {
printf("Current Read Error!\\r\\n");
bmsState = BMS_STATE_FAULT;
}
}
// 3. 采集温度(周期1000ms)
static uint32_t tempTick = 0;
if(GetTickCount() – tempTick > 1000) {
tempTick = GetTickCount();
if(BQ76940_ReadTemperatures() == 0) {
printf("Temperatures: %d.%d℃, %d.%d℃, %d.%d℃\\r\\n",
temperatures[0]/10, temperatures[0]%10,
temperatures[1]/10, temperatures[1]%10,
temperatures[2]/10, temperatures[2]%10);
} else {
printf("Temperature Read Error!\\r\\n");
bmsState = BMS_STATE_FAULT;
}
}
// 4. 均衡控制(周期500ms)
static uint32_t balanceTick = 0;
if(GetTickCount() – balanceTick > 500) {
balanceTick = GetTickCount();
BQ76940_BalanceControl();
}
// 5. 故障监测(周期200ms)
static uint32_t faultTick = 0;
if(GetTickCount() – faultTick > 200) {
faultTick = GetTickCount();
BQ76940_FaultHandler();
// 检查故障状态
uint8_t faultStat = BQ76940_ReadByte(0x00);
if(faultStat != FAULT_NONE) {
bmsState = BMS_STATE_FAULT;
}
}
break;
case BMS_STATE_FAULT:
// 故障处理:关闭充放电FET,上报故障
BQ76940_WriteByte(0x05, 0x60);
printf("BMS Enter Fault State! Fault Stat: 0x%02X\\r\\n", BQ76940_ReadByte(0x00));
// 尝试恢复(每5秒重试一次)
static uint32_t recoverTick = 0;
if(GetTickCount() – recoverTick > 5000) {
recoverTick = GetTickCount();
BQ76940_WriteByte(0x00, 0xFF); // 清除故障
Delay_ms(100);
bmsState = BMS_STATE_INIT; // 重新初始化
}
break;
default:
bmsState = BMS_STATE_INIT;
break;
}
}
}

