2、CAN总线基础:物理层、帧格式、仲裁与错误处理

各位同学,今天咱们来啃一块硬骨头——CAN总线。说实话,在储能系统里,PCS和BMS能不能好好说话,全靠这条总线。我做了这么多年系统集成,见过太多因为CAN通信不稳导致的奇葩故障。所以这一章,咱们把底层的物理层、帧格式、仲裁机制和错误处理彻底讲透。

2.1 CAN总线物理层特性

CAN总线物理层,说白了就是信号怎么在线上跑。它用的是差分信号,两根线:CAN_H和CAN_L。为什么要用差分?抗干扰啊!储能站里逆变器一开,电磁环境那叫一个恶劣,单端信号根本扛不住。

我个人的习惯是,在设计CAN节点时,终端电阻一定不能省。120欧姆,两端各一个。为什么是120?因为CAN总线的特性阻抗就是120欧姆。不匹配的话,信号反射会搞得你怀疑人生。

关键参数速查表:

参数说明
总线电平显性0V / 隐性2.5V显性时CAN_H≈3.5V,CAN_L≈1.5V
最大速率1 Mbps总线长度≤40m时
最大节点数110个(理论)实际受驱动能力限制
终端电阻120Ω两端各一个

嗯,这里要注意:速率和总线长度是成反比的。你想想看,1Mbps时最多跑40米,降到125kbps就能跑500米。储能柜内部走线一般也就几米,所以用500kbps比较常见。我曾经在一个项目中,现场施工把CAN线跟动力线绑在一起走了20米,结果通信丢包率高达30%。后来分开走线,问题立刻解决。

2.2 CAN2.0A/B帧格式

CAN2.0A和2.0B的区别,说白了就是ID长度的不同。2.0A是11位ID,2.0B是29位ID。在储能系统里,我建议直接用2.0B。为什么?因为29位ID可以携带更多信息,比如把设备类型、功能码、数据索引都编码进去,方便后期扩展。

咱们来看一个标准数据帧的结构,我画了个图,你一看就明白:

CAN 2.0B 标准数据帧结构 SOF 仲裁场(29位ID) 控制场 数据场(0-8字节) CRC场 ACK EOF 位填充区域(5个相同位后插入一个反相位) • SOF: 1位显性,标志帧开始 • 仲裁场: 29位ID + SRR + IDE + RTR • 控制场: r1 + r0 + DLC(4位数据长度) • 数据场: 0~8字节,BMS通常传电压、温度、SOC • CRC: 15位校验 + 1位定界符

数据场最多8个字节,这是CAN的一个硬限制。在储能系统里,BMS上报的电池电压、温度、SOC等信息,8个字节往往不够用。怎么办?我一般会采用多帧传输,或者把数据压缩编码。比如电压值用2字节表示,温度用1字节,这样一帧能塞下3组数据。

避坑指南:我曾经遇到过一个坑——CAN控制器默认是2.0A模式,只支持11位ID。如果你用了29位ID,必须显式配置为2.0B模式。否则,节点会一直收不到消息,还以为是硬件坏了。

2.3 CAN总线仲裁机制

仲裁机制,说白了就是多个节点同时发数据时,谁说了算。CAN总线用的是CSMA/CA + 逐位仲裁。每个节点在发送前先监听总线,空闲了才发。如果两个节点同时发,就看谁的ID优先级高。

这里有个关键点:ID值越小,优先级越高。为什么?因为显性位(0)会覆盖隐性位(1)。你想想看,如果节点A的ID是0x100,节点B的ID是0x200,它们在总线上逐位比较,A的ID更小,所以A胜出,B自动退出发送。

在储能系统里,我一般这样分配优先级:

  • 最高优先级:紧急停机信号(ID=0x001)——命根子,必须最快响应
  • 高优先级:BMS上报的故障告警(ID=0x010~0x01F)
  • 中优先级:PCS的功率调度指令(ID=0x100~0x1FF)
  • 低优先级:BMS周期性上报的电压温度数据(ID=0x200~0x2FF)

嗯,这里要注意:仲裁机制虽然好用,但如果总线上节点太多,低优先级的节点可能一直抢不到总线。这就是所谓的“饿死”现象。我建议在协议设计时,给每个节点留一个“保底发送窗口”,确保低优先级数据也能发出去。

2.4 CAN总线错误处理

CAN总线的错误处理机制,是我觉得最牛的地方。它不像串口那样,丢了数据就丢了。CAN有5种错误检测机制,而且每个节点都会参与错误监控。

这5种错误分别是:

  1. 位错误:发送节点监控总线,发现发送的位和总线上的位不一致
  2. 填充错误:连续5个相同位后没有插入反相位
  3. CRC错误:接收节点计算的CRC与发送的不一致
  4. 格式错误:帧格式不符合规范
  5. ACK错误:发送节点没有收到应答

每个节点内部有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。错误多了,节点会进入三种状态之一:

状态条件行为
主动错误TEC<127 且 REC<127正常通信,发送主动错误标志
被动错误TEC>127 或 REC>127只能发送被动错误标志,且发送前要等待8个隐性位
总线关闭TEC>255完全脱离总线,不再参与任何通信

警告:总线关闭状态是致命的!节点一旦进入这个状态,必须由主机通过特定指令才能恢复。我在一个项目中遇到过,BMS因为CAN总线干扰频繁进入总线关闭状态,导致PCS收不到电池数据,直接停机。后来我们在BMS软件里加了自动恢复机制,检测到总线关闭后,主动复位CAN控制器。

最后说一个我自己的经验:CAN总线调试时,一定要用示波器看波形。别光看软件日志,有时候硬件上的毛刺、振铃、电平异常,软件根本发现不了。我习惯在CAN_H和CAN_L之间挂一个示波器,看差分信号的质量。如果波形上升沿不够陡,或者有回勾,那就要检查终端电阻和布线了。

好了,CAN总线的基础就讲到这里。这些内容看起来枯燥,但都是实际干活时绕不开的。下一章咱们会深入PCS和BMS之间的具体通信协议,到时候这些基础都会用上。


专注资料整理