第 4 章 CAN FD¶
CAN FD(Flexible Data-rate)由 Bosch 2012 年提出、2015 年并入 ISO 11898-1 修订版,解决经典 CAN 的两处硬约束:每帧 8 字节载荷不够用、整帧同一波特率在长总线上跑不到高速。CAN FD 的关键设计选择是"只改数据段、不改仲裁段"——保留位仲裁与既有物理层,同时把数据段位速率抬到常见 2–5 Mbps(部分控制器与收发器组合可到 8 Mbps)、载荷上限扩到 64 字节。本章按帧结构、位时序、共存与回退、应用四个面展开,示例基于 python-can 与 SocketCAN。
只改数据段的设计取舍:
flowchart LR
keep["仲裁段:保持经典速率<br/>兼容既有物理层"] --> brs["BRS 位速率切换"]
brs --> data["数据段:2–5 Mbps<br/>载荷 ≤ 64 B"]
data --> crc["更强 CRC + 填充规则"]
1. 从 CAN 到 CAN FD:动机与折衷¶
经典 CAN 在 1 Mbps 下最大 40 m,本质是位时序 PROP 段必须覆盖往返传播时延;把位速率翻倍,长度上限减半。要在长总线上"跑更多数据"只有两条路:每帧塞更多位(延长帧)或提高位速率。延长帧会破坏位仲裁窗口(ID 之外的位多了、仲裁失败浪费更多时间),提高位速率又撞回长度上限。
CAN FD 的答案:只在数据段提高位速率。仲裁段维持原波特率(保位仲裁与既有收发器电气兼容),数据段允许 BRS(Bit Rate Switch)位打开后切到更高位速率。这样:
- 短帧、低优先级、仲裁竞争激烈的场景仍按原波特率跑,不影响总线实时性预算。
- 数据段是帧内主要耗时,提速率后单帧时间显著下降;64 字节数据在 5 Mbps 数据段下约 100 μs,折算的载荷吞吐比经典 CAN 8 字节、1 Mbps 的约 120 μs 高一个数量级。
代价:需要 FD 兼容的收发器(ISO 11898-2:2016 起)、FD 兼容的控制器;经典节点在 FD 总线上会报错但不锁总线(见「与经典 CAN 的共存与回退」),可以共存但不能"完全无缝"。
2. 帧结构差异¶
CAN FD 帧与经典 CAN 数据帧的字段布局高度相似,但若干位的含义改变、若干新位插入、CRC 场加长。
2.1 仲裁段不变、数据段变速¶
SOF | 仲裁场 | 控制场 | 数据场 | CRC 场 | ACK | EOF | IFS
| base ID | RRS | IDE | FDF | res | [扩展 ID] | RTR | BRS | ESI | DLC | 0–64B | CRC+stuff cnt | | |
与经典帧相比,FD 帧在仲裁场保留了 ID、RRS(替代 SRR)、IDE、RTR 的位置,把经典帧中 IDE 之后的保留位 r0 的位置改为 FDF,再插入 res 位;控制场则由 BRS、ESI、4 位 DLC 组成。仲裁段(SOF 到 RTR)完全保持经典 CAN 的位速率与时序;从控制段起若 BRS 位为显性,数据段与 CRC 段切到 FD 位速率(dbitrate)。帧尾的 ACK、EOF、IFS 段回落至仲裁段波特率——这一约束保证经典节点能在帧尾正确解码。
2.2 BRS、ESI、FDF 与 IDE 位¶
三位新加的语义:
- BRS(Bit Rate Switch):1 位;显性 = 打开数据段高速率、隐性 = 数据段保持仲裁速率。经典节点在更早的 FDF 位就已判错,根本到不了 BRS;对 FD 节点而言,BRS 只切换本帧后半段的位时序。
- ESI(Error State Indicator):1 位,位于 BRS 之后;发送器用它报告自己的错误状态——显性 = error-passive,隐性 = error-active。接收器读 ESI 可提前判断发送器已降级,比经典 CAN 靠外部诊断更直接。
- FDF(FD Format):1 位,占用经典帧中 r0 保留位的位置;隐性表示 FD 帧、显性表示经典帧。经典节点在该位置期待显性 r0,一旦读到隐性的 FD 帧就按格式错误处理——这是"经典节点检出 FD 帧"的关键判定点。
2.3 DLC 扩展与数据长度编码¶
经典 CAN 的 DLC 场 4 位、直接对应 0–8 字节;FD 数据段最长 64 字节,4 位不够。FD 仍保留 4 位 DLC 场,但把 9–15 这七个码重新映射成离散阶梯,编码如下:
| DLC 码 | 数据字节数 |
|---|---|
| 0–8 | 0–8(与经典一致) |
| 9 | 12 |
| 10 | 16 |
| 11 | 20 |
| 12 | 24 |
| 13 | 32 |
| 14 | 48 |
| 15 | 64 |
离散长度(12、16、20、24、32、48、64)是帧格式对 CRC 与位填充预算折衷后的结果——大于 8 字节时只支持这几个阶梯值。实际数据长度小于所选阶梯时,帧内多出的字节填什么由应用层约定,协议本身不规定。
2.4 CRC-17 / CRC-21 与 CRC 界定符¶
经典 CAN 的 CRC-15 只能保护约 130 位;FD 帧最长约 600 位(64 B 数据 + 加长控制段与 CRC),需要更强的校验。FD 分两档:
- 数据段 ≤ 16 字节:CRC-17,17 位监督码(具体生成多项式以 Bosch CAN FD Specification Part 1 定义为准,本处不列系数)。
- 数据段 ≥ 20 字节:CRC-21,21 位监督码(同)。
CRC 后跟 1 位隐性界定符(与经典一致);接收器在 CRC 校验失败时按位填充违规或直接 CRC 违规报错误帧,机制与经典 CAN 相同。
3. 位时序的两套波特率¶
FD 帧跨越两段不同波特率,位时序参数也要独立配置两套:仲裁段一套、数据段一套。
3.1 独立配置的意义¶
SocketCAN 与 python-can 都提供两套参数:
bitrate/brp/tsc/sjw/prop-seg/phase-seg1/phase-seg2→ 仲裁段dbitrate/dsjw/dprop-seg/dphase-seg1/dphase-seg2→ 数据段
配置约束:
- 仲裁段的位时序决定总线最大长度(PROP ≥ 2 × 单程传播时延),与经典 CAN 完全一致。
- 数据段不再仲裁,同一时刻只有一个发送器,采样点只需覆盖单程传播与收发器延时,而不必像仲裁段那样为"发送后回读"留出往返时延;因此同一物理线上数据段可以显著快于仲裁段。代价是收发器环路延时与边沿不对称在总延时中的占比随速率上升,速率越高可布线长度越短。
典型配置:仲裁 500 kbps(对应 100 m 总线)、数据 2–5 Mbps(对应同一物理线)。
3.2 数据段采样点要求更严¶
ISO 11898-1:2015 与 CiA 601 系列对 FD 位时序给出的常用取值:
- 仲裁段采样点:75%–87.5%(工程常取 80%)
- 数据段采样点:80%,可接受窗口比仲裁段窄
数据段采样点更严是因为收发器延时不对称在 FD 高速下更明显——CAN_H / CAN_L 驱动器切换显性/隐性的边沿在 5 Mbps 下位时间只有 200 ns,收发器传播延迟 40–60 ns 已经是位时间的 20%–30%,采样点位置容差被压小。具体窗口按所选收发器的环路延时与不对称参数核算,不能照搬仲裁段的经验值。
python-can 里配置 FD 位时序的最小片段:
## 运行环境:Ubuntu 22.04(Linux 5.15),python-can 4.x,SocketCAN backend
import can
bus = can.Bus(interface="socketcan", channel="can0",
bitrate=500_000, # 仲裁段
data_bitrate=2_000_000, # 数据段
fd=True) # 打开通用 FD 支持
对同一物理接口,SocketCAN 侧通常先用 ip link set can0 type can bitrate 500000 dbitrate 2000000 fd on 配置;python-can 的构造参数也接受同一组速率,是否由它代配接口取决于所用版本与 backend,以该版本文档为准。
4. 与经典 CAN 的共存与回退¶
FD 帧在既有 CAN 网络上会怎么表现,直接决定升级路径能否"分节点逐步切"。
4.1 经典节点在 FD 总线上的行为¶
经典节点看到 FD 帧时:
- 仲裁段完全兼容,正常参与位仲裁(若 ID 更小时仍能赢)。
- 进入仲裁场后,在经典帧 r0 的位置读到隐性的 FDF(经典 CAN 要求该位为显性),按格式错误检出。
- 发出主动错误标志(error-active 节点)或被动错误标志(error-passive 节点)。
- 该错误标志本身不会破坏 FD 帧的载荷,但会让发送器重发。
关键结论:经典节点会把 FD 帧"打成错误",但错误帧之后总线回到空闲、FD 节点重发。这在协议层看似不兼容;但工程上通过 ESI + 混合调度能实现"某些时段 FD、某些时段经典"——把 FD 帧的 ID 空间与经典帧的 ID 空间错开,用网关或主站协调。
4.2 混合拓扑的可行边界¶
CAN FD 与经典 CAN 能在同一总线共存。共存是协议级别可行的,条件是:
- 经典节点不会主动去发 FD 帧(它自己发不了)。
- FD 节点在含有经典节点的段上,用网关/桥接方式而非直接广播 FD 帧——网关把 FD 帧拆成经典 CAN 帧转发,代价是数据量下降与时延上升。
- 或者物理上把 FD 段与经典段用隔离网关分成两个独立 CAN 域,两域间按需路由。
同一根物理总线同时混挂经典收发器与 FD 收发器在电气上没问题(都是 ISO 11898-2 兼容),但 FD 帧会被经典节点报错——所以严格意义的"完全透明"混挂只在仲裁段波特率相同、且经典节点被明确告知不去解读 FD 帧的场景可行。部分 FD 网络(只有一部分节点支持 FD)的时序余量要按拓扑与收发器延时逐段核算,不能套用全 FD 网络的经验。
工程惯例:新系统从头全 FD,不在同一物理段混合;已有经典 CAN 网络升级用双协议栈网关隔离。
5. 典型应用:关节驱动与高数据量传感¶
CAN FD 在机器人上主要填三个空:
- 关节驱动的 CSP 模式(周期同步位置):CiA 402 profile 的 CSP 每周期需要下发目标位置(4 字节)+ 控制字,并上传实际位置、速度、电流、状态字与故障字(合计约 12–20 字节)。经典 CAN 需要 2–3 帧拼一次控制周期;FD 一帧装完,同步抖动小、总线负载降一半。
- 多路传感器聚合:IMU(三轴加速度 + 三轴陀螺 + 温度 ≈ 20 字节)+ 磁编码器(4 字节)+ 限位(1 字节)合并一帧发送,避免每传感器一帧的仲裁开销。
- 参数下载与固件升级:CANopen SDO 的分段传输在经典 CAN 下每 7 字节一段、开销大;FD 一帧可 50+ 字节有效数据,一次刷写完小 MCU 的固件镜像。
性能量级参考(1 Mbps 仲裁 / 5 Mbps 数据、64 字节载荷):一条 CAN FD 帧约 120–160 μs,同载荷的经典 CAN 需要 8 条帧、约 0.8–1 ms,再加上仲裁与错误重发的期望时延,吞吐提升约 5–8 倍。
6. 最小 python-can 收发 FD 帧示例¶
以下片段展示:接口配置 → 发一条 FD 帧(BRS=1、DLC=15 即 64 字节) → 读回并核对 is_fd 与 bitrate_switch。运行环境:Ubuntu 22.04、Linux 5.15、python-can 4.3、PEAK PCAN-USB Pro FD;换 Kvaser 或 SocketCAN backend 时 interface 参数改写。
## 运行环境:Ubuntu 22.04(Linux 5.15),python-can 4.3,pcan backend
import can
## 打开 FD 接口:仲裁 1 Mbps、数据 5 Mbps、启用 FD
bus = can.Bus(interface="pcan", channel="PCAN_USBBUS1",
bitrate=1_000_000, data_bitrate=5_000_000, fd=True)
## 构造一条 FD 消息:ID 0x123、BRS=True、64 字节数据
msg = can.Message(
arbitration_id=0x123,
is_extended_id=False,
is_fd=True, # FD 帧标志,对应 FDF 位
bitrate_switch=True, # BRS 位:数据段切 5 Mbps
data=bytes(range(64)), # 0x00..0x3F,DLC=15
)
bus.send(msg)
## 读回一条:核对 FD 属性
rx = bus.recv(timeout=1.0)
if rx and rx.is_fd:
print(f"FD 帧:ID=0x{rx.arbitration_id:X} BRS={rx.bitrate_switch} "
f"DLC={len(rx.data)} 前 8 字节={rx.data[:8].hex()}")
## 期望输出:FD 帧:ID=0x123 BRS=True DLC=64 前 8 字节=0001020304050607
SocketCAN 侧对照:
## 终端 A 挂监听(-fd on 让 candump 支持 FD 帧解码)
candump -L can0
## 终端 B 发 FD 帧:# 分隔符前后是仲裁段与数据段速率;数据 64 B
cansend can0 123##1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
candump 输出中 ##1 表示 FD 帧且 BRS=1(数据段切高速率),##0 表示 FD 帧但 BRS=0(数据段保持仲裁速率);标志位其他位对应 ESI 等属性,以 can-utils 手册为准。DLC 码 9–15(十六进制 9–F)对应 12–64 字节的阶梯(与「DLC 扩展与数据长度编码」小节表一致)。
7. 要点¶
- CAN FD 改动集中在四类:FDF 标志帧类型、BRS 让数据段变速率、ESI 上报发送器错误状态、载荷扩到 64 B;仲裁段与帧尾保持经典 CAN 的位时序,位仲裁与物理层兼容。
- 三个新位:FDF(隐性=FD 帧,占用经典 r0 位置)、BRS(数据段速率开关)、ESI(显性=error-passive)。
- DLC 是阶梯映射:0–8 直映射、9–15 分别对应 12 / 16 / 20 / 24 / 32 / 48 / 64 字节;大于 8 字节不支持任意长度。
- CRC 分两档:≤ 16 B 用 CRC-17、≥ 20 B 用 CRC-21;数据段采样点窗口比仲裁段更窄(常取 80%,按收发器参数核算)。
- 共存与回退:经典节点会把 FD 帧判错、发错误标志、FD 节点重发,形成"能共存但不透明";工程上升级路径要么全 FD 从头、要么用双协议栈网关隔离。
- 在机器人上的定位:CSP 模式一帧装完、多传感器聚合、SDO 与固件下载;相较经典 CAN 吞吐 5–8 倍、单周期同步抖动更小。