CAN FD 协议概述
大家好。这一章我们先聊聊 CAN FD 的来龙去脉,以及它和传统 CAN 2.0 到底差在哪。
我个人最早接触 CAN 2.0 是在几年前的一个车载控制器项目里。那时候总线负载率一高,数据就得拆成好几帧发,还得算好优先级。后来发现国外同行已经开始用 CAN FD 了,我才开始系统琢磨这个升级版协议。说实话,刚开始看帧结构时有点懵 —— 多了不少位,跟我印象中的 CAN 差挺多。今天就按我的理解,带大家把基础打牢。
1.1 发展历程:从 CAN 2.0 到 CAN FD
CAN(Controller Area Network)由 Bosch 在 1986 年提出,1991 年确定了 CAN 2.0(分 A 和 B 两个版本)。CAN 2.0B 的 29 位扩展标识符加上每帧最多 8 字节数据,在很长时间里都是汽车 ECU 通信的主力。
问题出在哪?
- 带宽不足:CAN 2.0 最高支持 1 Mbit/s(实际常用 500 kbit/s),做 OTA 升级或大数据量诊断时,一包数据要拆几十帧,延迟感人。
- 有效载荷太小:每帧 8 字节,传个 4KB 的固件要发 500 多帧,浪费大量总线时间。
2011 年,Bosch 与业界伙伴推出了 CAN FD(CAN with Flexible Data-Rate)。我跟进的第一个项目就是移植一款 MCU 的 CAN FD 驱动库,摸爬滚打几个月,总算把收发器配置、位时序调通。
关键时间节点:
| 年份 | 事件 | 备注 |
|---|---|---|
| 1991 | CAN 2.0 标准确定 | 8 字节 / 帧,1 Mbit/s |
| 2011 | Bosch 公开 CAN FD 初版 | 数据段可以跑更高比特率 |
| 2012 | 标准化提交 CiA | 经多个组织测试验证 |
| 2015 | ISO 11898-1:2015 发布 | CAN FD 正式国际标准 |
| 2018 | ISO 11898-1:2015 更新 | 补充了错误状态机等细节 |
有些芯片手册上把 CAN FD 和 TTCAN 放在一起提,但 TTCAN 是时间触发模式,CAN FD 是灵活数据率,两者定位完全不同。我一开始也搞混过。
1.2 帧结构差异:多出来的那些位
CAN FD 和 CAN 2.0 的帧结构很像,但仔细比较会发现几处关键变化。下面这张表是个人总结的差异点,项目开发时可以当备忘用。
| 字段/特性 | CAN 2.0(标准帧) | CAN FD(标准帧) | 说明 |
|---|---|---|---|
| 控制段 bit6 | IDE(隐性=1) | EDL(隐性=1 表示 FD 帧) | 二者占用同一位,接收方根据该位识别帧类型 |
| 控制段 bit0 | DLC(4 位,0~8) | DLC(4 位,0~15) | CAN FD 中 DLC 对应实际数据长度(见后表) |
| 控制段保留位 | 1 个 r0 | BRS(位速率切换标志)+ ESI(错误状态指示) | CAN FD 占用了原来的 r0 和 r1 位 |
| 数据段最大长度 | 8 字节 | 64 字节 | 这是最直观的升级 |
| CRC 段 | 15 位 CRC + 1 位 CRC 界定符 | 17/21 位 CRC + 1 位 CRC 界定符 | 根据数据长度选择 17 或 21 位 CRC |
| ACK 槽之后 | 7 个隐性位(EOF) | 同 CAN 2.0,但位填充规则有差异 | 数据段采用新的填充机制 |
我举个实际例子:CAN FD 的控制段中,原来 CAN 2.0 的 r0 位被改造成了 BRS 位。当 BRS = 显性时,仲裁段用标准速率,数据段切换到高速率;BRS = 隐性时,全程用仲裁速率。这个设计很巧妙 —— 仲裁段继续用传统速率保证总线仲裁稳定性,数据段才提速。
注意:CAN FD 帧里 DLC 不再是 0~8 直接对应字节数。DLC=9 对应 12 字节,10 对应 16,11 对应 20,12 对应 24,13 对应 32,14 对应 48,15 对应 64。我第一次写解码时没查表,直接把 DLC 当字节数用,结果一直丢帧。
1.3 与 CAN 2.0 的兼容性:能混跑吗?
这个问题我项目中被问过很多次:总线上一半传统节点、一半 FD 节点,能不能正常通信?
答案是:可以,但有前提。
- 物理层兼容:CAN FD 使用相同的差分信号、总线电平、收发器接口。大多数 CAN FD 收发器(如 TJA1044、SN65HVD255)和普通 CAN 收发器是 pin-to-pin 兼容的。
- 协议层兼容:CAN FD 帧的 SOF、仲裁段(11 位或 29 位标识符)、控制段的前几位与 CAN 2.0 完全一致。传统节点接收 FD 帧时,会在解析到 EDL 位(原 IDE 位)时发现该位状态不是预期的显性,从而引发格式错误,产生错误帧 —— 但 FD 节点会自行处理,不会让传统节点“误操作”。
- 混合通信策略:要保证传统节点不参与 FD 帧的接收,可以在系统设计上让 FD 节点发送的标识符在传统节点侧被屏蔽,或者仅让传统节点监听,不参与 ACK。通常建议:如果混用,传统节点必须能容忍 FD 帧的“隐形 ACK”以及多出来的数据段位。
我记得第一次在实验室测试混用场景,一台只支持 CAN 2.0 的示波器解不出 FD 帧的数据,但能看到它发了错误帧 —— 说明传统节点确实会检测到格式错误并主动报错。后来我调整了 FD 节点的位时序,让数据段速率不高于 2 Mbit/s,错误帧就很少出现了。
核心结论:CAN FD 节点向下兼容 CAN 2.0,但反之不行。传统节点无法正确解析 FD 帧,只能“容忍”它的存在。如果你要升级既有网络,必须确保所有新节点都用 CAN FD,老节点要么换掉,要么确保它们不会因为收到 FD 帧而频繁报错阻塞总线。
1.4 CAN FD vs CAN 2.0 帧结构对比图
下面这张 SVG 图是我自己梳理的,把两种帧在控制段之后的差异直观对比出来。箭头走向就是实际发送顺序,左边是仲裁段——两边完全相同,右边是差异区。
1.5 小总结:为什么要关注 FIFO 溢出
你想想看,CAN FD 一帧能塞 64 字节,数据段速率还能飙到 5 Mbit/s 甚至更高。如果 MCU 的 CAN 控制器 FIFO 深度不够,或者 CPU 来不及取走帧,FIFO 很容易溢出。我记得有一次测试,总线负载率才 30% 就频繁丢帧,查来查去发现是 FIFO 深度只有 64 字节(基于 8 字节帧配置),而 CAN FD 每帧 64 字节,一次中断就把 FIFO 塞满了。
所以,理解 CAN FD 帧结构的差异,是后续定位 FIFO 溢出的基本功。下一章我们就深入到具体 FIFO 工作机制,看看溢出到底是怎么发生的。
嗯,先消化这些吧。有问题可以翻回来看这张表。