1. CAN FD 协议基础:从 CAN 2.0 到 CAN FD 的进化
各位同学,咱们直接进入正题。CAN FD 这玩意儿,说白了就是 CAN 2.0 的升级版。我最早接触 CAN 总线是在做车载网关项目的时候,那时候用的还是经典 CAN,跑 500kbps 的波特率,一帧数据最多带 8 个字节。后来项目要求升级固件 OTA,8 个字节一帧地传,那速度真是让人抓狂。嗯,CAN FD 就是来解决这个痛点的。
1.1 CAN FD 与 CAN 2.0 的核心区别
先看一张对比表,把差异摆到台面上来:
| 对比项 | CAN 2.0(经典 CAN) | CAN FD |
|---|---|---|
| 最大数据段长度 | 8 字节 | 64 字节 |
| 最大波特率(数据段) | 1 Mbps(固定) | 最高 8 Mbps(可切换) |
| 帧格式 | 标准帧 / 扩展帧 | 兼容 CAN 2.0 + FD 帧 |
| 位速率切换 | 不支持 | 支持(BRS 位控制) |
| 错误状态指示 | 无 | 支持(ESI 位) |
| CRC 校验 | 15 位 / 17 位 | 17 位 / 21 位(更强) |
你看,最直观的变化就是数据段从 8 字节跳到了 64 字节。我在做电池管理系统(BMS)的时候,一包电池数据有 48 个单体电压,用经典 CAN 得拆成 6 帧发,用 CAN FD 一帧搞定。这不仅仅是省时间,更重要的是数据一致性——你想想看,6 帧数据在总线上传输时,中间可能被其他节点打断,数据完整性就打了折扣。
1.2 CAN FD 帧结构详解
CAN FD 的帧结构,我建议你把它拆成三段来理解:仲裁段、控制段、数据段。咱们以数据帧为例,画个结构图:
我的经验之谈:刚开始用 CAN FD 时,我犯过一个低级错误——把 EDL 位和 BRS 位搞混了。EDL 位决定这是不是 FD 帧,BRS 位决定数据段要不要跑高速。这两个位是独立的,你可以发一个 EDL=1、BRS=0 的帧,那就是 FD 帧但数据段不加速。我曾经在调试时发现总线一直报错,查了半天,原来是 EDL 位没置 1,接收端把它当经典 CAN 帧解析了,CRC 校验当然过不了。
1.3 数据段长度编码(DLC)
DLC 在 CAN FD 里和经典 CAN 不一样了。经典 CAN 的 DLC 直接对应字节数,0~8。CAN FD 的 DLC 编码做了扩展,但并不是线性映射到 64 的。看这张表:
| DLC 值(4 bit) | 经典 CAN 数据长度 | 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 里分别对应 12、16、20、24、32、48、64 字节。这个设计是为了向后兼容——经典 CAN 控制器收到 DLC=9 的帧,依然按 8 字节处理,不会出错。
避坑指南:我曾经在配置 STM32H7 的 CAN FD 外设时,直接写了 DLC=15 想发 64 字节,结果发现发送缓冲区只传了 8 个字节出去。后来查手册才发现,DLC 寄存器写入的是编码值,但数据长度寄存器(比如 FDCAN_DLC)需要配合数据字节数寄存器一起设置。嗯,细节决定成败。
1.4 位速率切换(BRS)
BRS 位是 CAN FD 最实用的特性之一。它允许你在同一帧内使用两种波特率:
- 仲裁段:使用较低波特率(典型 500 kbps),保证总线仲裁的可靠性
- 数据段:切换到较高波特率(典型 2~5 Mbps),提升数据传输效率
为什么会这样设计?你想想看,仲裁段需要所有节点以相同速率监听总线,如果速率太高,信号在长距离传输时反射和衰减会严重影响仲裁的准确性。但数据段不一样,它只涉及发送节点和接收节点,只要收发器支持,跑快点完全没问题。
我在实际项目中测试过,用 500 kbps 仲裁 + 4 Mbps 数据段,传输 64 字节数据的时间从经典 CAN 的约 1.2 ms 降到了约 0.25 ms,效率提升了近 5 倍。这对于需要实时传输大量数据的场景(比如激光雷达点云、高分辨率图像)来说,意义重大。
注意:BRS 位只在 FD 帧(EDL=1)中有效。如果你在经典 CAN 帧里置了 BRS=1,接收端会忽略这个位,不会切换速率。另外,数据段速率不能超过收发器的物理限制,比如 TJA1044T 最高支持 5 Mbps,而 TJA1463 可以到 8 Mbps。选型时一定要看数据手册。
1.5 错误状态指示(ESI)
ESI 位是 CAN FD 新增的,用来指示发送节点的错误状态。它的逻辑很简单:
- ESI = 0:发送节点处于
Error Active状态,可以正常发送和接收 - ESI = 1:发送节点处于
Error Passive状态,只能发送被动错误帧
这个位有什么用?我举个例子。在经典 CAN 里,如果一个节点频繁出错,它会进入 Bus Off 状态,完全脱离总线。但在 CAN FD 里,ESI 位让接收节点提前知道发送节点的健康状况。如果收到 ESI=1 的帧,接收节点可以主动减少与该节点的通信,或者触发诊断流程。
我记得有一次在产线测试中,一批 ECU 频繁报错,排查后发现是某个节点的 CAN 收发器虚焊,导致信号质量差。那个节点反复进入 Error Passive 状态,发出的帧 ESI 位一直为 1。通过监控 ESI 位,我们快速定位了问题批次,避免了大规模返工。
总结一下:CAN FD 不是颠覆性的新技术,它是在 CAN 2.0 基础上的增量升级。核心变化就四点——更大的数据段、可切换的速率、更灵活的帧结构、更智能的错误指示。掌握了这些基础,后面配置 STM32 的 CAN FD 外设时,你就能理解每个寄存器位是干什么用的了。