● BMS工程代码全面知识提炼 — 博客专题写作提纲
专题一:BMS系统架构总览
博客标题建议:《工业级BMS系统架构设计:从硬件选型到软件分层》
提纲要点:
BMS在储能系统中的定位 :
- BMS、PCS、EMS三者关系:
- BMU(Battery Management Unit)与BSMU(Battery System Management Unit)的层级关系
- 本工程:BMU负责单体采集,通过CAN上报BSMU
硬件平台选型分析
- 主控:NXP S32K146(ARM Cortex-M4F,112MHz,车规级MCU)
- 为什么选车规MCU:AEC-Q100认证、宽温度范围、功能安全
- 片上资源盘点:FlexCAN×3、LPUART×3、LPSPI×4、LPI2C×2、FTM×8、ADC×2
外围芯片生态
- AFE:LTC6813-1(18S,菊花链SPI,精度±1.2mV)
- 精密库仑计:LTC2949(高精度电流/电压/温度/功率/能量积分)
- SBC电源管理:NXP FS6503(ASIL-D,看门狗,安全状态机)
- 外部EEPROM:M24512(512Kbit,I2C,参数持久化)
- 外部Flash:SST26VF064(64Mbit,SPI,历史记录波形存储)
- RTC:EPSON RX8010(I2C,断电保持时间)
软件分层架构
Application Layer ← 业务逻辑(SOC/SOH/故障诊断/充放电策略)
Function Layer ← 功能模块(采样/计算/状态机)
BSP Layer ← 板级支持包(HAL适配,初始化序列)
Driver Layer ← 设备驱动(LTC6813/FS65/M24512等)
SDK Layer ← NXP SDK(Generated_Code,外设寄存器抽象)
Hardware Layer ← S32K146 + 外围芯片
模块间通信设计
- 全局共享内存(GroupInfo.c/GroupPara.c)
- API函数隔离(GetXXXAPI/SetXXXAPI模式)
- 无消息队列、无信号量的轻量级设计选择与代价
专题二:FreeRTOS在BMS中的工程化应用
博客标题建议:《FreeRTOS软件定时器+任务混合架构:BMS实时调度设计》
提纲要点:
为什么BMS需要RTOS
- 多路采样并发(电压/温度/电流/高压独立任务)
- 实时性要求:5ms控制周期,CAN收发不能阻塞采样
- 确定性执行:故障诊断必须在规定时间窗口内完成
本工程调度架构设计
- 10个软件定时器(Timer):5ms/10ms/50ms/100ms/200ms/300ms/400ms/500ms/1000ms/2000ms
- 6个独立任务(Task):CellSample/HigSample/LowSample/CANSend/CANRcv/UARTRcv
- 定时器回调在Timer Service Task中执行,与普通任务抢占
10ms任务的二级调度技巧
static u8 sTime = 0; switch(sTime) { case 0: CurrLimCalcTask(); CurrLimFallTask(); break; case 1: CheckVoltCharaTask(); CheckTempCharaTask(); break; // ...共10个case,每个100ms执行一次 } sTime = (sTime+1) % 10;- 意义:100ms周期任务分散在10个10ms时隙,避免同时执行造成抖动
- 工程实践:比直接用100ms定时器更灵活,便于调整各子任务时序依赖
阻塞式采样任务设计
- CellInfoSampleTask:12状态机 + OSIF_TimeDelay阻塞
- 状态机设计的优势:不阻塞调度器,通过delay主动让出CPU
- 与轮询方式对比:减少CPU占用,适合长耗时外设操作(SPI菊花链)
FreeRTOS关键API在BMS中的使用
- xTimerCreate/xTimerStart:软件定时器创建与启动
- xTaskCreate:任务优先级规划(采样 > CAN > UART)
- OSIF_TimeDelay:NXP SDK对vTaskDelay的封装
- vTaskStartScheduler:调度器启动点
RTOS诊断:OSDiagTimerAddTask
- 检测各定时器实际执行时间是否超期
- 嵌入式系统健康监控实践
专题三:锂电池单体电压采集——LTC6813工程实践
博客标题建议:《LTC6813菊花链采样:18S×32从控的工程级实现》
提纲要点:
LTC6813芯片架构
- 18路差分电压测量,±1.2mV精度
- 菊花链(Daisy-chain)SPI:多个芯片串联,单SPI口控制32片
- 隔离通信:LTC6820作为isoSPI转换器
- 内置ADC:7kHz模式18路扫描时间<3.9ms
双链路设计(本工程)
- LTC6820-1 + LTC6820-2:两路独立isoSPI,CS1/CS2片选切换
- 冗余设计意义:单链路故障仍可采样
采样状态机详解(12状态)
State 0: 更新均衡需求 → State 1/2
State 1: ADC清零(有均衡停止前序)
State 2: 启动ADC转换(7kHz模式)
State 3/4/5: 分批读取寄存器A/B、C/D、E/F
State 6: 校验并处理电压值
State 7/8/9: 清零GPIO ADC → 启动GPIO ADC → 读取温度
State 10: 处理温度值
State 12: 更新均衡控制
ADC读取分批策略
- 一次采样读6组寄存器(ADCA/B/ADCC/D/ADCE/F),每读一次等待bsuNum × LTC_RD_AD_T
- 原因:菊花链数据通过每个芯片中继,从控越多延迟越大
电池位置补偿(硬件寄生电阻补偿)
首节电池: +3.0mV(CELF_COMP_VOLT)
末节电池: +2.5mV(CELE_COMP_VOLT)
中间电池: +2.3mV(CELM_COMP_VOLT)
- 原理:PCB走线阻抗、均衡电阻导致测量偏差,通过固定补偿修正
14S特殊处理(CATL/标准PACK)
- - 第8路通道保留给参考电压,跳过:cell_num = cell_Id < 7 ? cell_Id : cell_Id - 1
采样异常处理
- noVSampCounter:连续异常计数,≥20次才记录故障
- 异常时重新初始化LTC6813
- 全为0时置Clr,触发上层诊断
专题四:NTC热敏电阻温度采集算法
博客标题建议:《NTC热敏电阻温度测量:从电压到℃的完整工程链路》
提纲要点:
NTC工作原理
- B值公式:R = R₀ × exp(B × (1/T - 1/T₀))
- 与温度负相关,灵敏度高(低温更明显)
- 10K/47K/100K不同阻值的应用场景
硬件电路(分压器)
- 电池温度:10K NTC + 100kΩ上拉,3.0V基准
- 均衡温度:47K NTC + 下拉(冷极/热极两种)
- AFE直接读取GPIO引脚电压(1mV精度)
电压→电阻转换
- // 10K NTC,100kΩ上拉,3.0V基准 R = Vdata * 10000 / (3000 - Vdata)
查表法与插值 - 166元素查找表,覆盖-41°C到125°C,步长1°C - 二分查找 + 中点插值:if(data <= (tab[i] + tab[i-1]) / 2) return i; else return i-1; - 四种不同电池型号的NTC表(宁温/CATL 240Ah/CATL 280Ah液冷/REPT标准)
均衡温度特殊处理 - GPIO1/GPIO2两路均衡温度,硬件存在非线性偏差 - 分段线性校正(KB修正): // GPIO1,13°C以上 corrTemp = (9569 * temp - 1639) / 10000; // GPIO2,低温段另一组系数 corrTemp = (10168 * temp - 17877) / 10000; - 意义:通过实测数据拟合修正,弥补NTC批次一致性差问题
多项目NTC表编译期选择 - #if(1 == PRJ_PARA_NUM_INFO) ... #elif ... #else - 同一份代码支持多个客户项目,编译配置宏切换
专题五:安时积分法(库仑计)——SOC核心算法实现
博客标题建议:《安时积分法完整工程实现:单位换算、累积误差与修正策略》
提纲要点:
安时积分基本原理 - SOC(t) = SOC(0) - (1/C_rated) × ∫I dt - 离散化:每个采样周期 ΔCap = I × Δt - 优势:实时性好,跟踪快速变化 - 劣势:误差累积,需要初始值校正
本工程实现的单位级联 输入:电流 I(单位:10mA),时间 t(单位:1ms) 累积器:chgCap10ma1ms(10mA·ms) 换算:1 mAh = 3600 mA·s = 3,600,000 mA·ms = 360,000 × 10mA·ms 进位:每积累360,000个10mA·ms,进位1 mAh 上层单位:mAh → Ah - 为什么用整数而非浮点:嵌入式无FPU时效率,或节省FPU给更高优先级计算
充放电方向处理 changCap1ma1h += chgCap1mah; // 充电增量(正方向) changCap1ma1h -= dhgCap1mah; // 放电减量(负方向) - changCap1ma1h:本次状态转换的净变化量,用于SOC缓慢变化算法
能量积分的并行实现 - Energy(Wh) = ∫V × I dt - 单位:mW·ms → mWh → Wh → 0.1kWh - 换算常数:1 Wh = 3,600,000 mW·ms
积分触发时机 - 采样完成标志位(VSampFinFlag/TSampFinFlag)置位后触发 - 确保积分使用已稳定的采样值
累积误差来源与影响 - 电流传感器零漂(Offset误差) - ADC量化误差 - 采样周期不均匀(OS调度抖动) - 温度影响电流传感器精度
专题六:SOC多策略融合修正算法
博客标题建议:《工程级SOC算法:安时积分+电压修正+端点标定的完整方案》
提纲要点:
容量形式(Capacity Form)设计 CAP_ZERO_POINT = 5000 mAh(零点偏移,避免负数) nowCap = 实际当前容量 + CAP_ZERO_POINT SOC = (nowCap - lowCap) * 10000 / (allCap - lowCap) - 为什么需要零点偏移:过放场景下nowCap可能比lowCap还小(负值),用偏移量统一处理
四个容量变量的语义 - baseCap:零SOC对应容量(死区容量) - topCap:100% SOC对应容量 - nowCap:当前容量(安时积分维护) - remCap:剩余可放电容量(理论最大放电量) - allCap = topCap - baseCap:有效容量
初始SOC建立 - 从EEPROM读取上次存储SOC - 上电5秒内不信任采样值,强制初始化期
五类电压修正触发条件
| 触发条件 | 修正动作 |
|---|---|
| 过充保护触发(VH1+VH2同时) | 强制SOC→100% |
| 过放保护触发(VL1+VL2同时) | 强制SOC→0% |
| 充电高压限制(VH2) | SOC收敛→99% |
| 放电低压限制(VL2) | SOC收敛→3% |
| 静置足够时间 + 电压极端区间 | 电压查表修正 |
静置修正(Open Circuit Voltage Correction) - 条件:空闲状态(CURR_IDLE)持续SOC_SLOW_CORR_IDLE_T时间 - 策略:最大电压低于阈值时下调SOC,最小电压高于阈值时上调SOC - 本质:利用OCV-SOC曲线的单调性,在静置后强制SOC与电压对应
充放末端修正 - 充电末端:最大电压≥4.15V且SOC<95% → 强制SOC上调 - 放电末端:最小电压≤3.0V且SOC>5% → 强制SOC下调 - 工程意义:防止SOC显示值在临界状态给出错误判断
EEPROM持久化策略 - SOC变化≥0.1%时写EEPROM - 充放电状态转换时强制写 - 容量值(nowCap)实时写(每次积分进位1mAh时)
专题七:SOC缓慢显示算法(用户体验工程)
博客标题建议:《BMS SOC显示平滑算法:让百分比变化符合用户直觉》
提纲要点:
为什么需要显示平滑 - 安时积分值跳变(ADC噪声/电流噪声) - 保护触发时SOC强制修正导致跳变 - 用户看到SOC像进度条一样跳动体验差
速度自适应的单向跟踪 - 充电时SOC只能增加(慢慢追上算法值) - 放电时SOC只能减少 - 突变量 = 实际变化量 + 步进量(stepSoc)
接近端点时加速显示 充电侧(SOC→100%): SOC > 97.5%: 5秒追完剩余量(快速) SOC > 95%: 15秒追完 SOC > 93%: 20秒追完 SOC > 90%: 30秒追完 SOC > 80%: 60秒追完 SOC < 80%: 120秒追完(最慢) - 同样逻辑用于放电侧(镜像处理)
端点锁定机制 - SOC≥99%时锁定在99%(不显示100%,除非触发满电保护) - SOC≤1%时锁定在1%(不显示0%,除非触发欠压保护) - 意义:给用户留有余量感
强制修正的显示处理 - CorrGDisplaySocByUser():直接覆写显示值,不经过缓慢变化 - 过充/过放保护触发:立即显示100%/0%
专题八:SOH健康状态算法
博客标题建议:《锂电池SOH计算:容量实测法与循环计数法的双重验证》
提纲要点:
SOH的定义与意义 - SOH = 当前最大容量 / 额定容量 × 100% - 反映电池老化程度,指导换电/维护决策
方法一:容量实测法 capSoh = GetGroupTotalCapAPI() * 10 / GetGroupRatedCapAPI() // TotalCap由实测充放电循环确定 - 优势:直接测量,准确 - 劣势:需要完整充放电循环,数据收敛慢
方法二:循环计数线性衰减模型 timSoh = 1000 - (fadeCycle * 200 / ratedCycle) // 假设:寿命终止时SOH=80%(线性衰减) - fadeCycle:实际循环次数 - ratedCycle:额定循环寿命(参数表读取) - 优势:无需等待完整循环
双方法融合策略 if |capSoh - timSoh| < 50(5%): 采用循环计数模型(更稳定) else: SOH = (capSoh + timSoh) / 2 SOH ≤ 上次SOH(防止反弹) SOH ≥ 上次SOH - 5(防止单次大跌)
SOH更新时机 - 每次循环计数变化后触发一次更新 - 同步写入EEPROM
SOH的工程局限性 - 温度影响容量(低温容量减小不代表SOH降低) - 倍率影响容量(大电流放电容量低) - 本工程未显式进行温度/倍率补偿的分析
专题九:卡尔曼滤波器理论与BMS应用
博客标题建议:《卡尔曼滤波估算SOC:从理论推导到嵌入式实现》
▎ 注:本工程未实现卡尔曼滤波,但这是BMS领域重要算法,以下为专题博客内容规划
提纲要点:
为什么安时积分需要卡尔曼辅助 - 开环积分误差不收敛 - 传感器噪声影响精度 - 卡尔曼:最优线性无偏估计
卡尔曼滤波五大方程
预测阶段:
x̂⁻(k) = A·x̂(k-1) + B·u(k) (状态预测)
P⁻(k) = A·P(k-1)·Aᵀ + Q (协方差预测)
更新阶段:
K(k) = P⁻(k)·Hᵀ / (H·P⁻(k)·Hᵀ + R) (卡尔曼增益)
x̂(k) = x̂⁻(k) + K(k)·(z(k) - H·x̂⁻(k)) (状态更新)
P(k) = (I - K(k)·H)·P⁻(k) (协方差更新)
3. BMS中的状态变量设计
- 状态向量:x = [SOC, 极化电压Vp]ᵀ
- 观测量:z = 端电压 Vt
- 模型:Vt = OCV(SOC) - Vp - I·R0 4. 扩展卡尔曼(EKF)的必要性 - OCV-SOC关系是非线性的 - 需要在工作点线性化(雅可比矩阵) 5. 嵌入式实现注意事项 - 矩阵运算的定点化 - Q/R噪声协方差的调参 - 计算量评估:2×2矩阵求逆 vs ARM Cortex-M4F性能 6. 与本工程方案对比 - 本工程:安时积分 + 多点电压校正(工程化、易调试) - 卡尔曼:理论最优、动态收敛(计算量大、调参复杂)
专题十:故障诊断系统设计
博客标题建议:《BMS故障诊断:两态状态机+滤波延迟的可靠故障检测》
提纲要点:
两态故障状态机 - eErr_A:正常态 - eErr_B:故障态 - 故障确认:需要持续超过滤波时间(防抖) - 故障恢复:需要持续正常超过恢复时间
故障分类体系 电压类:CEL_VH1/VH2(过压一/二级)、CEL_VL1/VL2(欠压一/二级) 温度类:CEL_TH1/TH2(高温)、CEL_TL1(低温) 电流类:过充电流、过放电流 采样类:SAMP_EXP(AFE异常)、SAMP_VOFF(电压断线)、SAMP_TOFF(温度断线) 通信类:INT_COFF(内部CAN)、CELL_MISS(从控丢失) 绝缘类:INS_LOW(绝缘下降) 继电器类:主继电器粘连
通信看门狗机制 - 每个从控(BSU)有计数器,每秒复位 - CAN消息到达时递增 - 1秒内未收到N帧 → 触发通信故障
AFE采样错误位域 - u8 errFlag[MAX_BSU_NUM]:位0=电压异常,位1=温度异常,位2=AFE通信异常 - 按从控粒度记录,便于定位具体节点
继电器粘连检测 - 主继电器吸合前:检测主正高压是否为0(粘连则有电压) - 主继电器断开后:检测主正高压是否降为0(粘连则仍有电压) - 电流辅助:切换瞬间无电流变化也可判断粘连
绝缘监测(接地故障检测) - 正负极对地阻抗测量 - 主动注入法 vs 被动测量法 - 阈值:通常<500Ω/V触发报警
诊断结果对SOC算法的保护 - 采样异常时:不更新电压/温度 - 通信故障时:停止均衡 - 过压/过放时:强制SOC修正
专题十一:被动均衡策略工程实现
博客标题建议:《锂电池被动均衡:LTC6813放电均衡的完整控制逻辑》
提纲要点:
均衡原理 - 被动均衡:通过放电电阻将高电压单体的能量以热量形式耗散 - LTC6813:每节电池对应一个内部开关,控制寄存器bit位对应单体
均衡请求信息更新 sLTC6813PasBalanCmd[i] = GetGroupVoltPasBalanReqState(i); // 14S特殊处理:跳过第8路(参考电压) sLTC6813PasBalanCmd[i] = reqState & 0x007f | ((reqState & 0x3f80) << 1);
均衡开/停条件 - 开始:有均衡请求(sLTC6813PasBalanReqState > 0) - 停止条件(任一触发):
无均衡请求
均衡时间达到最大值(BalSamT × 100ms)
最大单体电压≥平台电压(CellPlaUpV,0.5周期)
最大单体电压接近告警(CellPlaUpV - 30mV)
均衡期间的采样处理 - 均衡开启时:不更新电压显示值(均衡电流引起电压偏差) - sLTC6813PasBalanCtrlState:记录当前是否有均衡开启 - 判断条件:(sLTC6813PasBalanCtrlState == 0) || (cmd[cell_Ic] & (1 << cell_Id)) == 0
均衡寄存器写入(支持18S) // 配置寄存器A:cell1-8(低8位)、cell9-12(中4位) cfgA[4] = cmd & 0x00FF; // S1-S8 cfgA[5] = (cmd & 0x0F00) >> 8; // S9-S12 // 配置寄存器B:cell13-16(高4位)、cell17-18 cfgB[0] = ((cmd & 0xF000) >> 8) | LTC_GPIO_CT_AD_BIT; cfgB[1] = (cmd >> 16) & 0x03; // S17-S18
主动均衡与被动均衡对比(博客延伸) - 被动:简单,有热耗散,适合低均衡需求 - 主动:复杂(LLC/Buck-Boost),效率高,成本高
专题十二:CAN总线在储能BMS中的应用
博客标题建议:《储能BMS CAN通信架构:3路CAN的分工与协议设计》
提纲要点:
本工程CAN总线规划 CAN0:外部通信(BMU↔PCS/BSMU,标准协议/CATL协议) CAN1:内部通信(BMU↔BSU,采样数据上报) CAN2:辅助通信(特殊设备)
CAN任务架构 - BSPCANSendTask:独立高优先级任务,从消息队列取数据发送 - BSPCANRcvTask:独立高优先级任务,接收后分发给各模块 - 5ms Timer:CANLibHandleTask_API()定时触发CAN库处理(心跳/超时检测)
CAN消息分发(BSPUserHook.c) switch(msgId) { case PCS_MSG_ID: // PCS上/下电命令 case SOC_SYNC_ID: // SOC同步 case CHG_MSG_ID: // 充电协议 case CATL_MSG_ID: // CATL专属协议 }
通信协议层次 - 物理层:CAN 2.0B,标准帧/扩展帧 - 数据链路层:FlexCAN驱动(NXP SDK) - 应用层:自定义消息格式(ID + 8字节数据)
CAN通信故障处理 - Bus-off检测:物理层中断 - 消息超时:应用层看门狗计数 - 故障时动作:停止均衡、修正SOC为上次值
CATL协议的特殊支持 #if(1 == BMU_CATL_CAN_EN) CanSendUpCatlMsgCycleTask(); // 5ms周期发CATL心跳 #endif - 编译期配置支持多客户协议
CANopen/J1939的对比分析(延伸) - 本工程使用自定义协议 vs 标准协议的权衡 - J1939在商用车BMS的应用
专题十三:Modbus RTU协议实现
博客标题建议:《BMS Modbus RTU实现:从帧结构到寄存器映射的完整工程》
提纲要点:
Modbus RTU帧结构 [地址1B][功能码1B][数据NB][CRC2B] 帧间隔:3.5字符时间(>1ms@9600bps)
功能码实现 - 0x03:读保持寄存器(读参数/状态) - 0x06:写单寄存器(写参数) - 0x10:写多寄存器(批量写参数) - 错误响应:功能码+0x80,异常码
寄存器映射设计(BMS典型映射) - 0x0000-0x00FF:实时状态(电压/温度/电流/SOC) - 0x0100-0x01FF:告警状态位 - 0x0200-0x02FF:可写参数 - 0x1000-:历史记录读取
UART DMA接收实现 - BSPUARTRcvTask:独立任务,循环等待DMA完成 - 帧超时判断:3.5字符时间无数据 → 帧结束 - CRC校验:多项式0xA001
主从模式 - 本工程同时支持:作为从站响应上位机,作为主站轮询下位设备
专题十四:电源管理与功能安全——FS6503 SBC
博客标题建议:《车规SBC FS6503:BMS电源管理与ASIL-D功能安全实现》
提纲要点:
SBC(System Basis Chip)的作用 - 集成:LDO电源、CAN收发器、看门狗、安全状态机 - 为MCU提供受监控的供电和复位
FS6503安全状态机 - INIT → NORMAL → STANDBY → SLEEP 状态转换 - MCU必须定期喂狗,否则触发复位 - 看门狗窗口模式:喂狗过早/过晚都会触发复位(防止死循环喂狗)
FS65DiagnosticTask(5ms调用) - 定期读取FS65状态寄存器 - 检测:过压、欠压、过温、看门狗状态 - 喂狗序列:SPI发送特定序列
启动顺序中的FS65 BSPDriverInit(): 初始化FS6503 → 进入正常工作模式 期间喂狗避免复位
功能安全意义(ISO 26262/IEC 61508) - ASIL-D:汽车最高安全完整性等级 - SBC提供的硬件冗余:独立于MCU的看门狗 - 失效安全:MCU死机 → SBC触发安全状态 → 继电器断开
专题十五:参数管理与持久化存储
博客标题建议:《嵌入式参数管理:EEPROM+Flash的分层存储策略》
提纲要点:
存储介质分工 内部Flash(S32K146内置):程序代码 + 出厂默认参数 外部EEPROM(M24512):运行时参数(频繁读写,掉电保持) 外部Flash(SST26VF064):历史波形记录(大容量,顺序写)
参数分组体系(从文件名和变量名推断) - gGBmuGenPara_102[]:通用参数(电压限值/容量/SOC等,约200项) - gGBmuHigLevPara_103[]:高层级参数(从控数量/单体数等硬件配置) - gGHardPara_104[]:硬件参数(均衡时间/补偿系数等) - gGSysCapInfo_61[]:运行时信息(SOC/能量等,不持久化)
EEPROM写保护策略 - 只在值变化时写(防止频繁写缩短寿命) - SOC写策略:变化≥0.1%才写 - M24512:写周期>5ms,必须有写完成等待
ParaStoreCopyTask(10ms子任务) - 后台参数写任务,分散EEPROM写操作 - 避免在中断/关键路径中写EEPROM
Flash历史记录 - RcdFaultWaveHandleTask(100ms):故障波形数据缓冲 - RcdStoreHandleTask(500ms):历史记录写入 - LoadAppFlashErasHandleAPI(300ms):后台擦除(SPI Flash必须先擦后写)
掉电数据一致性保证 - 关键参数写入后必须校验读回 - 多副本存储(写两份,读时校验CRC)
专题十六:嵌入式C语言工程化编码规范
博客标题建议:《工业BMS代码规范:从命名约定到防御性编程的工程实践》
提纲要点:
命名约定体系 g前缀:全局变量(gGBmuGenPara_102) s前缀:静态变量(sLTC6813CellVoltAD) e前缀:枚举值(eBmuGenPara102_NowSoc) API后缀:对外接口函数(GetGCellMaxVoltAPI) Hook后缀:用户实现的回调函数(EnerChangEepGNowSocHook) Task后缀:任务函数(CellInfoSampleTask)
类型定义 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef signed char s8; typedef signed short s16; typedef signed int s32; - 显式位宽,避免平台差异 - 与stdint.h的对比
防御性编程实践 // 越界保护 if(num >= gGBmuHigLevPara_103[eBmuHigLevPara103_BsuVNum]) return; // 参数合法性 if(flag > 1) return; // 溢出防护 if(corrTemp > 167) corrTemp = 167; if(corrTemp < 0) corrTemp = 0;
ABS宏的正确写法 #define ABS(a, b) ((a) > (b) ? ((a)-(b)) : ((b)-(a))) // 注意:与标准abs()不同,这是两数之差的绝对值
编译期配置(多项目支持) #if(1 == PRJ_PARA_NUM_INFO) // 宁温项目 #elif(2 == PRJ_PARA_NUM_INFO) // CATL 240Ah项目 #elif(5 == PRJ_PARA_NUM_INFO) // CATL液冷项目 #else // 默认 #endif - 通过宏实现同一份代码支持多个硬件配置
接口与实现分离 - XXXInterface.c:对外接口(Hook函数声明) - XXXUser.c:用户具体实现 - 意义:库代码与用户代码解耦,便于复用
静态分析友好的代码风格 - 所有函数返回值通过(void)显式忽略 - 避免全局变量直接访问(通过API函数) - (void)DEVGPIOSetPortState(...) 显式丢弃返回值
专题十七:电流采样与高压侧测量
博客标题建议:《BMS电流测量:霍尔传感器+分流器的双冗余方案》
提纲要点:
电流传感器类型 - 霍尔效应传感器:非接触,适合大电流,有零点漂移 - 分流器:接触式,精度高,有功耗 - 本工程:MCP3913 ADC采集分流器电压(推断)
LTC2949精密库仑计 - 同时测量:电流、电压、温度、功率、能量积分 - 内置积分器:硬件级安时积分,精度高于软件积分 - SPI接口,独立于LTC6813
高压侧测量(DC bus电压) - 配置宏BMU_DC_VH_TYPE决定测量方式:
类型1:LTC2949直接测量
类型2:外部分压电阻+ADC
类型3:从CAN读取
低压侧ADC(LowADCSamp) - MCU内部12/16位SAR ADC - 采集:辅助电源电压、温度传感器、绝缘检测
电流零漂校正 - 上电静置期间测量零点偏移 - 运行期间持续校正(基于空闲状态检测)
专题十八:继电器控制与预充电策略
博客标题建议:《BMS继电器控制:预充电保护与粘连检测的完整实现》
提纲要点:
主回路拓扑 电池+ → 主正继电器 → 负载 电池- → 主负继电器 → 负载 预充电路:主正旁路串预充电阻
上电预充序列
闭合主负继电器
闭合预充继电器(串联大电阻,限流)
等待负载电容充电(监测高压侧电压上升)
当高压 > 电池电压×90%时,闭合主正继电器 e. 断开预充继电器
粘连检测时序 - 吸合前检测:主正高压应接近0(若有电压→粘连) - 断开后检测:主正高压应跌落(若仍高→粘连)
GroupSysIoUpDnCtrlTask(1000ms) - 系统级IO上下电管理 - 继电器状态机:OPEN→PRECHARGE→CLOSE→CHECK
专题十九:多项目工程管理(一码多项目)
博客标题建议:《嵌入式多项目管理:编译宏+Hook模式支持多客户硬件》
提纲要点:
问题背景 - 同一BMS平台服务多个客户:CATL、宁德、REPT等 - 电池参数不同、NTC型号不同、CAN协议不同 - 如何用一套代码维护?
编译宏分层 PRJ_PARA_NUM_INFO:项目编号(1/2/3/4/5) BMU_CATL_CAN_EN:是否启用CATL协议 BMU_DC_VH_TYPE:高压测量方式 MAX_LTC6813_NUM:最大从控数量
运行时参数化 - gGBmuHigLevPara_103[eBmuHigLevPara103_BsuNum]:从控数量从EEPROM读取 - 出厂配置:生产线写入对应项目参数
Hook回调模式 - 库代码调用Hook函数(弱符号或接口文件) - 用户在XXXUser.c中实现具体行为 - 好处:库代码无需修改,仅替换User文件
博客写作路线图(推荐发布顺序)
入门系列(基础知识):
1. BMS系统架构总览
2. 锂电池基础:单体特性与成组
3. NTC温度采集
4. LTC6813电压采集
算法系列(核心价值):
5. 安时积分法完整实现
6. SOC多策略修正算法
7. SOC显示平滑算法
8. SOH双方法计算
9. 卡尔曼滤波理论与BMS应用(理论篇)
RTOS系列:
10. FreeRTOS软件定时器+任务混合架构
11. 状态机设计:12状态采样任务剖析
通信系列:
12. CAN总线3路分工设计
13. Modbus RTU完整实现
工程化系列:
14. 嵌入式C编码规范
15. 多项目一码管理
16. 参数分层存储策略
安全系列:
17. 故障诊断状态机
18. FS6503功能安全与看门狗
19. 继电器控制与预充电
20. 被动均衡策略
以上共19个专题、1个路线图,覆盖了本BMS工程所有核心知识域。每个专题提纲均来自实际代码中提炼的工程细节,确保博客内容有代码支撑、有原理解释、有工程价值。