4. CAN总线协议:CAN 2.0与CAN FD的区别、帧结构、仲裁机制及在电池簇内部通信中的实践

好,咱们今天聊聊CAN总线。在储能系统里,尤其是电池簇内部,CAN总线可以说是最常用的通信手段了。我做了这么多年储能,经手的项目里,十有八九都在用CAN。但说实话,很多人对CAN的理解还停留在“能通就行”的阶段。今天咱们就把它掰开揉碎了讲清楚。

4.1 CAN 2.0与CAN FD:到底差在哪?

先问个问题:你手头的BMS(电池管理系统)用的是CAN 2.0还是CAN FD?我猜大部分还是CAN 2.0。但最近两年,CAN FD开始多起来了。

CAN 2.0,也叫经典CAN。它的数据段最多只能带8个字节。嗯,8个字节。你想想看,一个电池簇里,电压、电流、温度、SOC、SOH……这些数据加起来,8个字节根本不够用。所以大家只能分帧发送,一帧报电压,一帧报温度,效率很低。

CAN FD,全称是CAN with Flexible Data-Rate。它把数据段扩展到了最多64个字节。说白了,就是一次能拉更多货了。而且它的速率可以切换,仲裁段还是用原来的速率(比如250kbps),但数据段可以飙到2Mbps甚至更高。我在一个项目中遇到过,用CAN FD后,电池簇的状态更新周期从原来的100ms缩短到了20ms,效果很明显。

对比项 CAN 2.0(经典CAN) CAN FD
数据长度 最多8字节 最多64字节
最大速率 1 Mbps 数据段可达8 Mbps
帧格式 标准帧/扩展帧 兼容CAN 2.0,新增FD帧
CRC校验 15位 CRC 17位/21位 CRC(更强)
向后兼容 - 可与CAN 2.0节点共存

核心区别一句话:CAN FD是CAN 2.0的升级版,更快、数据量更大、更安全。但代价是硬件成本略高,且需要协议栈支持。

4.2 帧结构:数据到底怎么装?

帧结构这东西,看着复杂,其实就几个关键字段。我习惯把它分成三部分:头部、数据区、尾部。

先看CAN 2.0的帧结构:

  • SOF(起始帧):1个显性位,告诉总线“我要发数据了”。
  • 仲裁段:11位(标准帧)或29位(扩展帧)的ID。这个ID决定了优先级。
  • 控制段:包含IDE位、DLC(数据长度码)等。DLC告诉你后面跟了几个字节。
  • 数据段:0~8字节,真正的数据在这里。
  • CRC段:15位校验,加上1位CRC分隔符。
  • ACK段:接收节点在这里回应“我收到了”。
  • EOF(帧结束):7个隐性位。

CAN FD的帧结构有什么不同?

  • 控制段里多了EDL位(扩展数据长度)和BRS位(比特率切换)。EDL=1表示这是FD帧,BRS=1表示数据段要提速。
  • 数据段可以到64字节,DLC的编码方式也变了。
  • CRC段更长,17位或21位,覆盖的范围也更广。

我的小技巧:在实际调试时,用CAN分析仪抓一帧数据,对照着数据手册看每个位。我当年就是这么学会的。别光看理论,动手抓一帧比看十页书都管用。

4.3 仲裁机制:谁先说话?

CAN总线的仲裁机制,说白了就是“谁的数字小,谁先走”。

为什么?因为CAN总线是“线与”逻辑。显性位(逻辑0)会覆盖隐性位(逻辑1)。所以ID越小,优先级越高。

举个例子:

  • 节点A的ID是0x100(二进制:0001 0000 0000)
  • 节点B的ID是0x200(二进制:0010 0000 0000)

两个节点同时发送时,从最高位开始比较。第1位都是0,没问题。第2位,A是0,B是1。A的显性位把B的隐性位覆盖了,B检测到总线电平跟自己发的不一样,就知道自己输了,乖乖退出。A继续发送。

这个机制在电池簇内部通信中特别重要。你想想看,电池簇里有主控、从控、采集模块,还有消防、温控等设备。如果多个设备同时发数据,谁先谁后?

我建议这样分配ID:

  • 主控(BMU):ID最小,优先级最高。比如0x100~0x1FF。
  • 从控(BCMU):ID中等。比如0x200~0x2FF。
  • 采集模块:ID较大。比如0x300~0x3FF。
  • 辅助设备(消防、温控):ID最大。比如0x400~0x4FF。

注意:千万不要把两个设备设成同一个ID!我曾经见过一个项目,两个从控的ID都是0x201,结果总线一直报错,数据根本收不到。查了三天才发现是ID冲突。这种低级错误,犯一次就够了。

4.4 在电池簇内部通信中的实践

好了,理论讲完了,咱们说说实际怎么用。

场景一:电池簇状态上报

每个电池簇需要定期上报电压、电流、温度、SOC等数据。用CAN 2.0的话,8个字节根本不够。我一般这样设计:

  • 帧1:总电压(2字节)+ 总电流(2字节)+ 最高温度(1字节)+ 最低温度(1字节)+ 预留(2字节)
  • 帧2:SOC(1字节)+ SOH(1字节)+ 循环次数(2字节)+ 故障码(4字节)

用CAN FD的话,一帧就够了:

  • 总电压(2字节)+ 总电流(2字节)+ 最高温度(1字节)+ 最低温度(1字节)+ SOC(1字节)+ SOH(1字节)+ 循环次数(2字节)+ 故障码(4字节)+ 单体电压(48字节,支持24串)

场景二:均衡控制指令

主控需要告诉从控“对第5节电池进行均衡”。这个指令很短,用CAN 2.0就够了。ID设为0x150,数据段包含:

  • 命令码(1字节):0x01表示启动均衡,0x02表示停止
  • 电池编号(1字节):0x05表示第5节
  • 均衡电流(2字节):单位mA

场景三:故障报警

这个优先级最高。我习惯把故障报警帧的ID设得很小,比如0x001。这样一旦有故障,它能立刻抢占总线。数据段包含:

  • 故障类型(1字节):0x01过压,0x02欠压,0x03过温……
  • 故障位置(1字节):哪个簇、哪个模组、哪节电池
  • 故障时间戳(4字节):精确到毫秒

实践要点:

  • 所有节点必须使用相同的波特率。我见过有人把主控设成250k,从控设成500k,结果根本不通。
  • 终端电阻一定要加!120欧姆,加在总线两端。不加的话,信号反射会导致通信不稳定。
  • CAN FD的速率切换要谨慎。数据段速率太高,线束太长的话,信号会衰减。我一般建议数据段不超过2Mbps,线束长度不超过5米。
CAN总线在电池簇内部通信中的知识体系 CAN总线协议 CAN 2.0 vs CAN FD 帧结构 仲裁机制 电池簇内部通信实践 经典CAN(8字节) CAN FD(64字节) SOF/仲裁/控制 数据/CRC/ACK ID越小优先级越高 线与逻辑 状态上报 均衡控制 故障报警

最后说一句,CAN协议看起来简单,但真正用好它,需要你对硬件、时序、协议栈都有深入理解。我建议你在做项目时,先画好通信矩阵,把每个帧的ID、数据内容、发送周期都定义清楚。这样后面调试会省很多事。

好了,关于CAN总线协议,咱们就聊到这儿。记住,理论是基础,实践出真知。多动手,多踩坑,你也能成为CAN专家。

专注资料整理