4. CAN总线协议详解(下):数据帧、错误帧与过载帧
上一讲我们把CAN总线的物理层和电气特性聊透了。这一讲,咱们深入协议的核心——数据帧的结构,以及总线出问题时的“急救机制”:错误帧和过载帧。
说实话,搞懂CAN的数据帧结构,你就能看懂90%的总线报文。我在调试台架时,经常看到工程师对着CANalyzer上的一串十六进制数发懵。其实,只要你把每一位拆开看,它就像一张表格一样清晰。
4.1 CAN数据帧结构——一张图看懂
一个标准的数据帧,总共包含7个场。我习惯把它比作一封信:信封上写地址(仲裁场),里面装内容(数据场),最后还要贴个防伪标签(CRC场)。
日常车载网络里,动力总成和车身控制多用标准帧,因为ID短、实时性好。信息娱乐和ADAS系统因为节点多,常用扩展帧。我个人建议:能用标准帧就别用扩展帧,省带宽。
4.2 逐场拆解——从SOF到EOF
4.2.1 SOF(帧起始)
SOF只有1位,必须是显性(逻辑0)。它干两件事:一是告诉所有节点“我要发数据了”,二是同步时钟。我记得有一次调试,某个节点SOF位总是发不出显性电平,查了半天发现是CAN收发器的TXD引脚虚焊了。嗯,这种问题示波器一看就露馅。
4.2.2 仲裁场——谁优先级高谁先走
这是CAN协议最巧妙的设计。标准帧的仲裁场包含11位ID和1位RTR。所有节点同时往总线上丢ID位,谁先发出隐性位(1)而别人发显性位(0),谁就退出竞争。
说白了,ID值越小,优先级越高。0x000是最高优先级,0x7FF是最低。
| ID范围 | 典型应用 | 优先级 |
|---|---|---|
| 0x000 - 0x1FF | 动力总成(发动机、变速箱) | 最高 |
| 0x200 - 0x3FF | 底盘安全(ABS、ESP) | 高 |
| 0x400 - 0x5FF | 车身控制(门窗、灯光) | 中 |
| 0x600 - 0x7FF | 信息娱乐、诊断 | 低 |
4.2.3 控制场——告诉别人我带了多长的行李
控制场共6位:IDE(1位,标识是标准帧还是扩展帧)、r0(1位保留位,必须为显性)、DLC(4位,数据长度码)。
DLC的取值范围是0~8,对应数据场的字节数。注意:DLC可以设为0,这叫远程帧请求,只问数据不传数据。我见过有人把DLC设成大于8的值,结果接收节点直接报错——协议规定DLC最大就是8。
4.2.4 数据场——真正的干货
数据场长度0~8字节,MSB先发。这里有个小细节:如果DLC=3,但实际只用了2个字节,剩下的1个字节怎么办?协议没规定,但大多数实现会填充0x00或0x55。我个人习惯是严格按照DLC长度发送,不多不少。
4.2.5 CRC场——防篡改的“封条”
CRC场包含15位CRC校验码和1位CRC界定符(隐性)。发送节点对SOF到数据场的所有位做CRC计算,接收节点收到后重新算一遍。如果对不上,接收节点就发错误帧。
CRC多项式是固定的:x¹⁵ + x¹⁴ + x¹⁰ + x⁸ + x⁷ + x⁴ + x³ + 1。你不用背,但要知道它能检测出所有≤5位的突发错误,以及99.998%的其他错误。
4.2.6 ACK场——接收节点的“回执”
ACK场只有2位:ACK槽和ACK界定符。发送节点在ACK槽发隐性位,所有接收节点如果正确收到报文,就在ACK槽发显性位“覆盖”它。如果发送节点发现ACK槽还是隐性,就知道没人收到——重发!
4.2.7 EOF(帧结束)
EOF是7个连续的隐性位。为什么是7位?因为位填充机制最多连续5个相同电平,7个隐性位足够让所有节点确认帧结束了。EOF之后,总线进入3位的ITM(帧间空间),然后才能发下一帧。
4.3 错误帧——总线出问题时的“警报”
CAN总线最牛的地方,就是它的错误检测和处理机制。错误帧是节点发现错误后主动发出的“求救信号”。
错误帧由两部分组成:
- 错误标志(6个显性位): 主动错误节点发6个显性位,被动错误节点发6个隐性位
- 错误界定符(8个隐性位): 结束错误帧
错误类型有5种:
| 错误类型 | 检测时机 | 说明 |
|---|---|---|
| 位错误 | 发送时 | 发送的位与总线电平不一致(仲裁期间除外) |
| 填充错误 | 接收时 | 检测到连续6个相同电平 |
| CRC错误 | 接收时 | CRC校验不匹配 |
| 形式错误 | 接收时 | 固定格式位(如CRC界定符)不是隐性 |
| ACK错误 | 发送时 | ACK槽未被覆盖为显性 |
4.4 过载帧——当节点“忙不过来”时
过载帧和错误帧长得有点像,但用途完全不同。过载帧是接收节点告诉发送节点:“我还没处理完上一帧,你慢点发。”
过载帧的结构:
- 过载标志(6个显性位): 节点主动发6个显性位
- 过载界定符(8个隐性位): 结束过载帧
触发过载帧的两种情况:
- 接收节点在帧间空间的前两位检测到显性位(本应是隐性)
- 接收节点内部缓冲区满,需要延迟下一帧
说实话,过载帧在实际车载网络中很少见。因为CAN的速率(最高1Mbps)和8字节数据场,大多数ECU的处理能力都够用。但如果你在做网关或数据记录仪,过载帧就可能出现——尤其是当CAN总线负载率超过80%时。
4.5 本章小结
数据帧的7个场,每个都有它的设计目的。SOF同步、仲裁场解决冲突、CRC保证完整性、ACK确认接收——这套机制让CAN在恶劣的车载环境下依然可靠。错误帧和过载帧则是总线的“自愈”能力,确保一个节点出问题不会拖垮整个网络。