第三章 系统架构设计:硬件架构与软件架构

各位同学,咱们今天聊聊系统架构设计。说实话,很多新手工程师一上来就急着写代码、画原理图,结果做到一半发现接口对不上,或者性能瓶颈卡死。我当年也踩过这个坑——有一次项目都到联调阶段了,才发现隔离通信的速率根本跟不上数据量,那叫一个痛苦。

所以,架构设计不是走形式。它是整个BMS的骨架。骨架歪了,后面再怎么填肉都没用。今天我就把硬件架构和软件架构的核心思路,掰开了讲给你听。

3.1 硬件架构:主控MCU、AFE芯片、电流传感器、隔离通信

先看硬件。BMS的硬件架构,说白了就是几个关键芯片怎么连、怎么分工。我个人习惯把硬件分成四个核心模块:

  • 主控MCU:大脑,负责运算和决策
  • AFE芯片:眼睛和手,负责采集电压、温度,以及均衡控制
  • 电流传感器:耳朵,负责感知电流大小和方向
  • 隔离通信:神经,负责高低压之间的数据传递

嗯,这里要注意一个关键点:高压和低压必须隔离。为什么?因为电池包电压可能高达400V甚至800V,而MCU的工作电压只有3.3V或5V。一旦高压窜入低压侧,整个系统就烧了。我在项目中遇到过客户把隔离芯片选成了非隔离型号,结果一上电就冒烟……嗯,从那以后我每次选型都会反复确认隔离等级。

3.1.1 主控MCU选型

MCU的选择,我个人建议关注三点:

  1. 算力:BMS需要实时处理多路ADC数据、运行SOC/SOH算法,至少需要Cortex-M4或以上内核。你想想看,如果MCU算力不够,SOC估算就会滞后,电池过充了都不知道。
  2. 外设资源:至少需要2路SPI(一路接AFE,一路接隔离通信)、1路I2C(接温度传感器)、多路GPIO(控制继电器和均衡)。
  3. 安全特性:最好带ECC内存和硬件看门狗。我见过一个项目因为内存软错误导致SOC跳变,差点引发事故。

推荐型号参考:

厂商型号内核适用场景
TITMS320F28069C28x DSP高端BMS,需要复杂算法
STSTM32F407Cortex-M4中端BMS,性价比高
NXPLPC54606Cortex-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