第三章 系统架构设计:硬件架构与软件架构
各位同学,咱们今天聊聊系统架构设计。说实话,很多新手工程师一上来就急着写代码、画原理图,结果做到一半发现接口对不上,或者性能瓶颈卡死。我当年也踩过这个坑——有一次项目都到联调阶段了,才发现隔离通信的速率根本跟不上数据量,那叫一个痛苦。
所以,架构设计不是走形式。它是整个BMS的骨架。骨架歪了,后面再怎么填肉都没用。今天我就把硬件架构和软件架构的核心思路,掰开了讲给你听。
3.1 硬件架构:主控MCU、AFE芯片、电流传感器、隔离通信
先看硬件。BMS的硬件架构,说白了就是几个关键芯片怎么连、怎么分工。我个人习惯把硬件分成四个核心模块:
- 主控MCU:大脑,负责运算和决策
- AFE芯片:眼睛和手,负责采集电压、温度,以及均衡控制
- 电流传感器:耳朵,负责感知电流大小和方向
- 隔离通信:神经,负责高低压之间的数据传递
嗯,这里要注意一个关键点:高压和低压必须隔离。为什么?因为电池包电压可能高达400V甚至800V,而MCU的工作电压只有3.3V或5V。一旦高压窜入低压侧,整个系统就烧了。我在项目中遇到过客户把隔离芯片选成了非隔离型号,结果一上电就冒烟……嗯,从那以后我每次选型都会反复确认隔离等级。
3.1.1 主控MCU选型
MCU的选择,我个人建议关注三点:
- 算力:BMS需要实时处理多路ADC数据、运行SOC/SOH算法,至少需要Cortex-M4或以上内核。你想想看,如果MCU算力不够,SOC估算就会滞后,电池过充了都不知道。
- 外设资源:至少需要2路SPI(一路接AFE,一路接隔离通信)、1路I2C(接温度传感器)、多路GPIO(控制继电器和均衡)。
- 安全特性:最好带ECC内存和硬件看门狗。我见过一个项目因为内存软错误导致SOC跳变,差点引发事故。
推荐型号参考:
| 厂商 | 型号 | 内核 | 适用场景 |
|---|---|---|---|
| TI | TMS320F28069 | C28x DSP | 高端BMS,需要复杂算法 |
| ST | STM32F407 | Cortex-M4 | 中端BMS,性价比高 |
| NXP | LPC54606 | Cortex-M4 | 低功耗BMS |
3.1.2 AFE芯片选型
AFE芯片是BMS的“数据源”。它的精度直接决定了SOC估算的准确性。我建议关注以下参数:
- 通道数:常见的有6串、12串、16串。根据电池包串联数选择。
- 电压采样精度:至少±5mV以内。我曾经用过一款精度±10mV的AFE,结果SOC误差高达8%,根本没法用。
- 均衡能力:被动均衡还是主动均衡?被动均衡简单便宜,但发热大;主动均衡效率高,但成本高。
- 通信接口:SPI或I2C。SPI速率更高,适合大数据量传输。
小技巧:选AFE时,尽量选带菊花链功能的。这样多片AFE可以级联,只用一根SPI线就能读取所有电芯数据。我最早做的一个项目用了4片AFE,每片单独接SPI,结果MCU的SPI口不够用,被迫加了一个SPI扩展芯片,麻烦得很。
3.1.3 电流传感器
电流传感器有两种主流方案:
- 霍尔传感器:非接触式,体积小,但精度受温度影响大。适合低成本方案。
- 分流器+隔离运放:精度高,但会发热。适合高精度需求。
我个人更倾向于分流器方案,尤其是需要做库仑计SOC估算时。霍尔传感器的零点漂移会让你头疼不已。我记得有一次调试,霍尔传感器在零电流时输出竟然有50mV的偏移,换算成电流就是2A的误差——这SOC还能算准吗?
3.1.4 隔离通信
隔离通信是BMS的“生命线”。常用的隔离方式有:
- 数字隔离器:如ISO7240,速率高,体积小。
- 隔离SPI:如ADuM3151,专门用于SPI信号隔离。
- 隔离CAN:如ISO1050,用于整车通信。
这里有个坑:隔离通信的速率一定要留余量。我做过一个项目,AFE的采样率是100Hz,每帧数据128字节,算下来需要约100kbps的通信速率。我选了隔离SPI,理论速率10Mbps,看似绰绰有余。但实际调试时发现,由于线缆长度和寄生电容,实际速率只能跑到2Mbps。嗯,还好留了余量,不然又得改板。
3.2 软件架构:分层设计
说完硬件,咱们聊聊软件。软件架构我习惯用分层设计。为什么分层?说白了就是为了解耦。你想想看,如果所有代码都揉在一起,换一个AFE芯片就要重写整个工程,那得多痛苦。
我一般把BMS软件分成三层:
- 驱动层:直接操作硬件寄存器
- 中间件层:封装通用功能,如通信协议、数据缓存
- 应用层:实现业务逻辑,如SOC估算、保护判断
3.2.1 驱动层
驱动层是最底层的代码。它直接和硬件打交道。比如:
- SPI驱动:读写AFE寄存器
- ADC驱动:采集电流传感器信号
- GPIO驱动:控制继电器和均衡MOS
- 定时器驱动:生成PWM或定时中断
驱动层的核心原则是:只做一件事,并且做好。不要在里面加业务逻辑。我曾经见过有人在SPI驱动里直接做SOC计算——那代码简直没法维护。
注意:驱动层要处理好临界区。比如SPI传输时,如果被中断打断,数据可能出错。我习惯用关中断或信号量来保护。
3.2.2 中间件层
中间件层是驱动层和应用层之间的桥梁。它提供一些通用服务:
- 通信协议栈:比如Modbus、CANopen,或者自定义协议
- 数据缓存:环形缓冲区,用于暂存AFE采样数据
- 状态机框架:管理BMS的工作状态(待机、充电、放电、故障)
- 滤波算法:比如卡尔曼滤波、滑动平均滤波
中间件层的设计要点是:可配置、可复用。比如滤波算法,你可以做成一个模块,输入原始数据,输出滤波后的数据。这样不管上层怎么变,中间件都不用动。
3.2.3 应用层
应用层是BMS的“大脑”。它负责:
- SOC估算:用开路电压法+安时积分法,或者卡尔曼滤波
- SOH评估:根据内阻和容量衰减判断电池健康状态
- 保护逻辑:过压、欠压、过流、过温、短路保护
- 均衡控制:什么时候开启均衡,均衡多长时间
- 通信管理:与整车控制器(VCU)或充电桩交互
应用层的代码要尽量简洁。复杂的算法可以封装成函数,不要堆在一个文件里。我习惯把每个功能模块单独建一个.c/.h文件,比如soc.c、protection.c、balance.c。这样后期维护起来,找问题也方便。
3.3 模块划分与接口定义
模块划分和接口定义,是架构设计中最容易被忽视的一环。很多工程师觉得“反正代码我自己写,接口随便定就行”。但项目一大了,你就会发现接口混乱带来的痛苦。
我建议按功能划分模块,每个模块对外暴露明确的接口。比如:
| 模块名称 | 功能描述 | 对外接口 |
|---|---|---|
| AFE模块 | 采集电芯电压、温度,控制均衡 | AFE_ReadVoltage(), AFE_ReadTemp(), AFE_BalanceCtrl() |
| 电流模块 | 采集电流值,提供滤波后的数据 | Current_GetValue(), Current_GetDirection() |
| SOC模块 | 估算电池剩余电量 | SOC_GetValue(), SOC_Reset() |
| 保护模块 | 检测异常状态,触发保护动作 | Protection_Check(), Protection_Clear() |
| 通信模块 | 与外部设备交互 | Comm_SendFrame(), Comm_ReceiveFrame() |
接口定义要遵循几个原则:
- 参数类型明确:不要用void*,除非万不得已
- 返回值统一:成功返回0,失败返回错误码
- 命名规范:模块名_动作_对象,比如AFE_ReadVoltage
我的习惯:在项目初期,我会先写一个接口头文件,比如bms_interfaces.h,里面只放函数声明和数据结构定义。然后各个模块的开发人员按照这个头文件去实现。这样即使大家并行开发,也不会出现接口对不上的问题。
好了,关于系统架构设计,今天就聊这么多。硬件架构决定了BMS的“下限”,软件架构决定了“上限”。两者缺一不可。下一章咱们会深入讲讲AFE芯片的驱动开发,到时候我会带着你一步步写代码。记得提前预习一下SPI通信协议。
有什么问题,欢迎在课程群里讨论。咱们下节课见。
公众号:蓝海资料掘金营,微信deep3321