第3章 CAN FD数据链路层:帧结构
CAN FD的帧结构,说白了就是数据在总线上怎么包装、怎么拆包。你如果只做过CAN 2.0,第一次看CAN FD的帧会觉得多了几个位,但核心思路没变。
我刚开始接触CAN FD时,就琢磨一件事:标准帧和扩展帧的区别到底在哪?其实区别就一个——仲裁场的ID位数。标准帧11位ID,扩展帧29位ID。多出来的18位放在哪里?放到IDE位后面,用SRR位占住原来RTR位的位置,这样新老设备能共存。你想想看,这点兼容性设计真是绝了。
嗯,我从项目里摸爬滚打出来的经验是:解析帧的时候一定先看IDE位,它是1就是扩展帧,0就是标准帧。别搞反了,否则后面CRC算不对,全是总线错误。
3.1 帧结构的整体骨架
一张图说清楚CAN FD帧从头到尾的每个字段,比看一千字管用。下面是我自己总结的帧结构图——每个格子代表1位,但实际位长度按规约来。
3.2 标准帧 vs 扩展帧
刚才图里能看到,标准帧仲裁场只占12位(SOF+11位ID+1位RTR),扩展帧仲裁场占了32位(SOF+11位标准ID+SRR+IDE+18位扩展ID+RTR)。你心想:不就多了个扩展ID嘛?对,但带来的麻烦是每条报文多了7个bit的仲裁时间,所以除非你有超过2048个独立ID的需求,否则用标准帧更省带宽。
| 对比项 | 标准帧 (Base Frame) | 扩展帧 (Extended Frame) |
|---|---|---|
| ID 位数 | 11 位 | 29 位 |
| 仲裁场长度 | 12 bits(SOF+ID+RTR) | 32 bits(SOF+11位标准ID+SRR+IDE+18位扩展ID+RTR) |
| IDE 位值 | 0 | 1 |
| 兼容性 | CAN 2.0A/B 均支持 | CAN 2.0B 及以上 |
| 典型应用 | 车辆动力、底盘(ID少) | 诊断、多节点复杂网络 |
我之前调试一个项目,用的CAN FD扩展帧,但数据解析器只认标准帧,结果丢了一半报文。后来发现是IDE位被写死了0——硬件配置时没把扩展帧使能打开。嗯,IDE这比特就是帧类型信号,收到0就是标准帧,收到1就是扩展帧,千万别想当然。
3.3 控制场新三剑客:EDL、BRS、ESI
CAN FD的控制场里多了三个位,这是它和CAN 2.0最大的不同。我一个个说。
EDL(Extended Data Length)位
EDL=1表示这是CAN FD帧,数据段可以用0~64字节;EDL=0表示这是传统CAN帧,只能用0~8字节。你想想看,如果误把EDL当成0,解析器按CAN 2.0读数据,肯定读不对CRC,因为CRC算法也变了。
BRS(Bit Rate Switch)位
BRS是我最喜欢的一个位,因为它的存在让CAN FD既能跑仲裁段的标准速度(通常125k~1Mbps),又能切换到数据段的快车道(2Mbps、5Mbps甚至更高)。BRS=1表示在数据段开始切到快速率,到CRC分隔位后再切回来。BRS=0表示全程一个速率。
我遇到过一辆车的BRS位被固件写反了,导致高速传数据时采样点失准,CRC错误率飙升。后来在论坛上排查才发现是某款MCU的CAN FD控制器寄存器默认值反了——你写1它切到慢速,写0才切快速。这就是血淋淋的教训,所以做解码前一定要先确认控制器的BRS极性。
ESI(Error State Indicator)位
ESI=0表示发送节点处于主动错误状态,ESI=1表示已进入被动错误状态(Error Passive)。说白了就是告诉接收方:“我已经快不行了,你信号给我留点余量。”如果接收节点连续收到ESI=1,就知道该节点可能要进入busoff了,能提前做故障预判。
我有个经验:做总线监控系统时,我把ESI位专门拎出来做一条报警线,持续被动错误超过100ms就弹警告。这个策略在产线上抓到了好几个有接触不良的节点。
3.4 数据段长度:从8字节到64字节
CAN FD最大进步就是数据段从8字节扩展到了64字节。怎么编码?DLC(Data Length Code)用4位表示实际字节数。传统CAN的DLC编码是线性的:0~8直接对应0~8字节。CAN FD非线性的,具体看下表:
| DLC 值 (4位) | CAN 2.0 字节数 | CAN FD 字节数 |
|---|---|---|
| 0~8 | 0~8 | 0~8 |
| 9 | 8 | 12 |
| 10 | 8 | 16 |
| 11 | 8 | 20 |
| 12 | 8 | 24 |
| 13 | 8 | 32 |
| 14 | 8 | 48 |
| 15 | 8 | 64 |
注意:DLC=9~15在传统CAN里都是非法值(收端按8字节处理),但在CAN FD里才真正生效。写代码时一定要先判断EDL位,再决定DLC的查表方式。我以前就在这个坑里爬过——DLC=12的情况下,传统CAN解析器只读了8字节,少读了16个字节的数据,导致后面全是错位。
3.5 避坑指南:解码器的触发设置
用示波器或逻辑分析仪抓CAN FD报文时,触发设置最容易踩的坑。我总结了几条:
- 触发条件要指定BRS位:如果你想抓从仲裁段到数据段有速率切换的报文,触发条件设为BRS=1。如果你只想看低速报文,就设BRS=0。
- 小心数据段超宽:当DLC指定64字节数据场时,波形长度比传统CAN长很多。如果采样深度不够,可能会截断,导致CRC校验不过。我习惯把存储深度调成至少20Mpts来抓64字节的CAN FD。
- ESI触发用于故障排查:把触发条件设为ESI=1,可以捕捉到被动错误节点发出的所有报文。我曾经在总线上抓到一辆老是报被动错误的车,查出来是收发器供电不稳,虚焊。