1. CAN FD 协议基础:从 CAN 2.0 到 CAN FD 的进化
各位同学,咱们直接进入正题。CAN FD 这玩意儿,说白了就是 CAN 2.0 的升级版。我最早接触 CAN 总线是在做车载诊断模块的时候,那时候还是经典的 CAN 2.0B,跑 500 kbps,一帧最多带 8 个字节数据。后来项目要求升级固件 OTA,8 个字节根本不够用,这才开始研究 CAN FD。
嗯,咱们先搞清楚一个核心问题:为什么要有 CAN FD?
传统 CAN 2.0 的瓶颈很明显:
- 数据场最多 8 字节,传个 Bootloader 得拆成几百帧
- 整帧都用同一个位速率,仲裁段和数据段速度一样
- 没有错误状态反馈,出了问题只能靠超时判断
CAN FD 就是来解决这些问题的。它向下兼容 CAN 2.0,但多了几个关键能力。
1.1 CAN 2.0 与 CAN FD 的核心区别
我习惯用一张表来对比,这样最直观。你在项目选型时,这张表能帮你快速判断该用哪种协议。
| 对比项 | CAN 2.0 (经典 CAN) | CAN FD (灵活数据速率) |
|---|---|---|
| 最大数据场长度 | 8 字节 | 64 字节 |
| 位速率 | 整帧固定(通常 ≤1 Mbps) | 仲裁段 ≤1 Mbps,数据段最高 8 Mbps |
| 帧格式 | 标准帧 / 扩展帧 | 兼容 CAN 2.0 + FD 帧(带 BRS/ESI) |
| DLC 编码 | 0~8 对应 0~8 字节 | 0~8 对应 0~8 字节,9~15 对应 12/16/20/24/32/48/64 字节 |
| CRC | 15 位 CRC | 17 位(≤16 字节)或 21 位(>16 字节) |
| 错误状态指示 | 无 | ESI 位,发送节点主动上报错误状态 |
关键点:CAN FD 的物理层和 CAN 2.0 完全一样。也就是说,你现有的 TJA1044 收发器可以直接用在 CAN FD 网络上,不需要换硬件。这一点我在项目中验证过多次,放心用。
1.2 CAN FD 帧结构详解
咱们来看 CAN FD 的帧结构。它和 CAN 2.0 长得像,但多了几个关键位。我画了一张图,你一看就明白。
你注意看控制段里的三个关键位:DLC、BRS、ESI。这三个位是 CAN FD 的灵魂。咱们一个一个拆开讲。
1.3 数据场长度编码(DLC)
DLC 在 CAN 2.0 里很简单:0~8 对应 0~8 字节。但 CAN FD 不一样,它用了 4 位 DLC 编码,可以表示更大的数据长度。
我刚开始看这个表的时候也愣了一下——为什么 9~15 不连续对应 9~15 字节?后来才明白,这是为了兼容 CAN 2.0 的 DLC 编码,同时用剩余编码值映射到更大的数据长度。
| 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 字节 |
实战经验:我在做 Bootloader 升级时,用 DLC = 15 传 64 字节数据帧,配合 4 Mbps 的数据段速率,一秒钟能传大约 3 MB 数据。相比传统 CAN 2.0 的 500 kbps、每帧 8 字节,速度提升了将近 50 倍。这个提升在 OTA 场景下非常明显。
1.4 位速率切换(BRS)
BRS 位是 CAN FD 最巧妙的设计。它允许在一帧内部切换位速率。
为什么会这样?你想想看,CAN 总线的仲裁过程需要所有节点同步,所以仲裁段必须用慢速。但数据段传输的是有效载荷,不需要仲裁,完全可以跑快一点。
BRS 的工作逻辑:
- BRS = 0:整帧使用仲裁段速率(兼容 CAN 2.0)
- BRS = 1:从 BRS 位之后切换到高速数据段,直到 CRC 段结束再切回
我习惯这么配置:
- 仲裁段:500 kbps(保证兼容性和抗干扰)
- 数据段:2 Mbps ~ 5 Mbps(根据线缆长度和节点数调整)
注意:数据段速率不是越高越好。我在一个项目中试过 8 Mbps,结果线缆超过 40 cm 就开始丢帧。后来降到 4 Mbps,配合 TJA1044 的显性超时功能,才稳定下来。建议你先从 2 Mbps 起步,用示波器看眼图,再逐步提高。
1.5 错误状态指示(ESI)
ESI 位是 CAN FD 新增的,用来让发送节点主动告诉接收方:「我现在状态不太好」。这在 CAN 2.0 里是没有的。
ESI 的三种状态:
- 错误主动(Error Active):ESI = 0,节点正常工作,可以主动发送错误帧
- 错误被动(Error Passive):ESI = 1,节点发送错误计数 ≥ 128,只能发送被动错误帧
- 总线关闭(Bus Off):节点彻底离线,不参与任何通信
我记得有一次调试,发现某个节点间歇性丢帧。用 CAN 分析仪抓包,看到 ESI 位频繁置 1。一查,原来是那个节点的终端电阻虚焊,导致信号反射严重,错误计数飙升。修好电阻后,ESI 恢复正常。
实用技巧:在 STM32 的 CAN FD 驱动中,你可以配置中断来捕获 ESI 状态变化。一旦发现 ESI = 1,立即记录错误计数并报警。这比等总线离线再处理要主动得多。
1.6 本章小结
咱们把这一章的核心点串一下:
- CAN FD 向下兼容 CAN 2.0,物理层不变
- 数据场从 8 字节扩展到 64 字节,DLC 编码用 4 位映射
- BRS 位实现仲裁段低速 + 数据段高速的混合速率
- ESI 位让节点主动上报错误状态,方便诊断