3. BMS通信协议详解:BMS数据报文结构

各位同学,咱们今天聊点实在的。BMS和PCS能不能好好配合,全看通信协议写得怎么样。我见过太多项目,硬件都调通了,结果卡在协议解析上,一查就是好几天。说白了,协议就是BMS和PCS之间的“共同语言”,语言不通,啥都白搭。

这一节,我带你拆解BMS报文的核心结构。电压、电流、温度、SOC,这些数据怎么打包发送?告警和保护报文长什么样?心跳机制又是怎么维持的?咱们一个一个来。

核心要点:BMS报文结构遵循“帧头+数据域+校验+帧尾”的通用格式。数据域中,每个参数都有固定的字节位置和精度定义。搞懂这个,你就能读懂任何BMS协议。

3.1 数据报文结构:电压、电流、温度、SOC

先看最基础的数据报文。BMS需要定期上报电池的实时状态,包括总电压、总电流、最高/最低单体电压、平均温度、SOC等。这些数据怎么组织?

我个人习惯用Modbus RTU协议,因为它简单可靠。但不管用哪种协议,报文结构都大同小异。下面是一个典型的BMS数据报文示例:

帧头: 0xAA 0x55
数据长度: 0x1E (30字节)
设备地址: 0x01
功能码: 0x03 (读取寄存器)
数据域:
  - 总电压: 0x0B 0xB8 (3000, 表示300.0V, 精度0.1V)
  - 总电流: 0x00 0x64 (100, 表示10.0A, 精度0.1A)
  - 最高单体电压: 0x0E 0x10 (3600, 表示3.600V, 精度0.001V)
  - 最低单体电压: 0x0D 0xF0 (3568, 表示3.568V, 精度0.001V)
  - 平均温度: 0x00 0x1E (30, 表示30.0°C, 精度0.1°C)
  - SOC: 0x00 0x3C (60, 表示60.0%, 精度0.1%)
  - 预留字节: 0x00 * 18
CRC校验: 0xXX 0xXX
帧尾: 0x0D 0x0A

你注意看,每个参数都有明确的精度定义。总电压精度0.1V,单体电压精度0.001V,温度精度0.1°C。为什么这么设计?因为电池管理对精度要求很高。我曾经遇到一个项目,单体电压精度用了0.01V,结果SOC估算偏差很大,后来改成0.001V才解决问题。

这里有个表格,把常见参数的数据格式列出来:

参数名称 字节数 数据类型 精度 取值范围
总电压 2 uint16 0.1V 0~6553.5V
总电流 2 int16 0.1A -3276.8~3276.7A
最高单体电压 2 uint16 0.001V 0~65.535V
最低单体电压 2 uint16 0.001V 0~65.535V
平均温度 2 int16 0.1°C -3276.8~3276.7°C
SOC 2 uint16 0.1% 0~100.0%

经验之谈:电流用int16是因为有充放电方向。正数表示充电,负数表示放电。我见过有人用uint16,结果放电电流解析出来是65535A,直接触发过流保护。嗯,这种低级错误咱们别犯。

3.2 BMS告警与保护报文

数据报文是常规上报,告警报文则是紧急情况。BMS检测到异常时,会主动发送告警报文,通知PCS执行保护动作。

告警报文的结构和数据报文类似,但数据域的内容不同。它通常包含告警类型、告警级别、告警参数等。下面是一个例子:

帧头: 0xAA 0x55
数据长度: 0x0A (10字节)
设备地址: 0x01
功能码: 0x04 (告警上报)
数据域:
  - 告警类型: 0x01 (单体过压)
  - 告警级别: 0x02 (严重)
  - 告警参数: 0x0E 0x10 (告警时的电压值, 3.600V)
  - 告警时间戳: 0x00 0x00 0x00 0x01 (系统运行时间, 单位秒)
CRC校验: 0xXX 0xXX
帧尾: 0x0D 0x0A

告警类型通常用一个字节表示,常见的告警类型包括:

  • 0x01:单体过压
  • 0x02:单体欠压
  • 0x03:过温
  • 0x04:低温
  • 0x05:过流
  • 0x06:短路
  • 0x07:绝缘故障
  • 0x08:通信故障

告警级别一般分三级:

  • 0x01:提示(仅记录,不动作)
  • 0x02:严重(需要降功率或停止充放电)
  • 0x03:致命(立即切断接触器)

注意:告警报文的优先级高于数据报文。BMS在发送告警时,可以中断正在发送的数据报文。我曾经调试一个项目,BMS一直发数据报文,结果过温告警发不出去,PCS没收到指令,电池直接热失控了。后来我们在协议里加了优先级机制,告警报文插队发送。

保护报文和告警报文类似,但保护报文是BMS主动执行保护动作后发送的确认报文。比如BMS检测到过压,先发告警,然后执行保护动作(断开接触器),再发保护报文确认。PCS收到保护报文后,需要停止充放电并等待BMS的恢复指令。

3.3 BMS心跳与同步机制

心跳机制,说白了就是BMS和PCS互相确认“我还活着”。没有心跳,你根本不知道对方是不是已经掉线了。

心跳报文通常很简单,就是一个固定格式的短报文。BMS每隔一定时间(比如1秒)发送一次心跳,PCS收到后回复确认。如果PCS连续几次没收到心跳,就认为BMS故障,需要执行安全动作。

下面是一个心跳报文的例子:

BMS发送:
帧头: 0xAA 0x55
数据长度: 0x02
设备地址: 0x01
功能码: 0x10 (心跳)
数据域: 0x00 0x01 (心跳计数, 每次加1)
CRC校验: 0xXX 0xXX
帧尾: 0x0D 0x0A

PCS回复:
帧头: 0xAA 0x55
数据长度: 0x02
设备地址: 0x01
功能码: 0x10 (心跳回复)
数据域: 0x00 0x01 (回复相同的心跳计数)
CRC校验: 0xXX 0xXX
帧尾: 0x0D 0x0A

心跳计数很重要。它用来检测报文是否丢失。如果BMS发送了计数5,但PCS回复的是计数3,说明中间有报文丢失了。这时候需要重新同步。

同步机制,我建议用“三次握手”的方式。BMS启动后,先发送同步请求,PCS回复同步确认,BMS再发送同步完成。这样双方就建立了可靠的通信链路。

同步流程如下:

  1. BMS发送同步请求(包含设备ID、协议版本号)
  2. PCS回复同步确认(包含PCS设备ID、支持的协议版本)
  3. BMS发送同步完成(确认版本一致,开始正常通信)

如果版本不一致怎么办?我建议BMS和PCS都支持向下兼容。比如BMS支持协议版本1.0和2.0,PCS只支持1.0,那就用1.0通信。如果完全不兼容,BMS需要上报“协议不匹配”告警。

避坑指南:我曾经遇到一个项目,BMS和PCS的心跳周期不一致。BMS设了1秒,PCS设了2秒。结果BMS发两次心跳,PCS才回一次,BMS以为PCS掉线了,直接切断了接触器。后来我们统一了心跳周期,并且在协议里明确写了“心跳周期可配置,但双方必须一致”。

好了,这一节的内容就这些。报文结构、告警保护、心跳同步,这三个点搞清楚了,BMS和PCS的通信对接就成功了一半。剩下的就是调试和测试了。

BMS通信协议核心结构 数据报文 电压、电流、温度、SOC 定期上报(1s/次) 精度:0.1V/0.001V/0.1°C/0.1% 告警报文 过压、欠压、过温、过流 紧急上报(优先级最高) 级别:提示/严重/致命 心跳报文 确认对方在线 周期:1s 计数机制防丢包 通用报文结构 帧头(2B) + 数据长度(1B) + 设备地址(1B) + 功能码(1B) + 数据域(NB) + CRC校验(2B) + 帧尾(2B) 同步机制(三次握手) BMS发送同步请求 → PCS回复同步确认 → BMS发送同步完成 包含设备ID、协议版本号,支持向下兼容 BMS通信协议核心结构图

专注资料整理