一、引言
CAN(Controller Area Network)总线自 1986 年由 Bosch 公司推出以来,已成为车载网络的事实标准。但随着现代汽车电子系统的日益复杂,经典 CAN 的局限性逐渐凸显------单帧 8 字节、最高 1 Mbps 的带宽已无法满足域控制器、自动驾驶等场景下的大数据传输需求。2012 年发布的 CAN FD(CAN with Flexible Data rate) 在保持经典 CAN 最大兼容性的同时,突破了这两大瓶颈。
二、核心区别一览
| 维度 | 经典 CAN (CAN 2.0A/B) | CAN FD |
|---|---|---|
| 单帧最大数据长度 | 8 字节 | 64 字节 |
| 速率 | 全程单一速率,最高 1 Mbps | 仲裁段 ≤ 1 Mbps(同 CAN),数据段最高 5~8 Mbps |
| 帧结构 | 全程同一速率 | 仲裁段 → 速率切换 → 数据段 |
| CRC 校验 | 15-bit CRC | 17-bit CRC,误检率更低 |
| 兼容性 | --- | CAN FD 控制器能收 经典 CAN;经典 CAN 收不了 CAN FD 帧 |
| 收发器 | 经典 CAN 收发器 | 必须用 CAN FD 收发器(如 TJA1463) |
| 总线长度 | 500 kbps 下约 40 米 | 数据段高速下约 10 米以内 |
三、数据帧结构差异
经典 CAN 和 CAN FD 的仲裁段(ID 竞争阶段)完全相同 ,速率也一样。CAN FD 在仲裁结束后,发送方通过一个 FDF(FD Format)位 通知接收方:"接下来要切到高速模式了"。
经典 CAN 帧:
┌─────────┬──────┬──────────┬──────┐
│ 仲裁段 │ 数据 │ CRC/ACK │ 结束 │
│ ≤1Mbps │ ≤8B │ 15-bit │ │
└─────────┴──────┴──────────┴──────┘
CAN FD 帧:
┌─────────┬──────┬──────────┬──────┐
│ 仲裁段 │ 数据 │ CRC/ACK │ 结束 │
│ ≤1Mbps │ ≤64B │ 17-bit │ │
└─────────┴──────┴──────────┴──────┘
▲
│ 这里插入 FDF 位 + BRS 位,
│ 通知硬件切换数据段波特率
这意味着 CAN FD 帧对经典 CAN 控制器来说,仲裁段能看懂,但一旦读到 FDF 位就会把整帧当作"未知格式"丢弃------这是硬件层面的不兼容,无法通过软件解决。
四、为什么需要 CAN FD
经典 CAN 的 8 字节 + 1 Mbps 在现代车上面临三大压力:
4.1 域控制器架构下的数据瓶颈
传统分布式架构中一个 ECU 只负责一个功能(比如变速箱 ECU、刹车 ECU),CAN 总线能撑住。但域控制器把十几个 ECU 整合成一个大脑,需要传输的数据量呈数量级增长------固件升级、诊断日志、摄像头预览等场景下,经典 CAN 一帧只能带 8 字节,光升级一个 2MB 的固件就要发几十万帧。
4.2 自动驾驶的传感器数据传输
激光雷达、摄像头的原始数据如果走 CAN,经典 CAN 根本扛不住。CAN FD 的 64 字节帧 + 5 Mbps 数据段,吞吐量提升了约 6~8 倍。
4.3 车内网络成本
CAN FD 可以用更少的总线、更低的成本满足更高带宽需求,在车载以太网普及之前是最务实的过渡方案。
五、在 DBC 文件中的体现
5.1 波特率段 BS_
这是最直接、最标准的判断依据。
经典 CAN:
BS_: 500000
CAN FD:
BS_: 500000, 2000000
逗号分隔两个数值:仲裁段波特率在前,数据段波特率在后。
5.2 Signal 长度上限
经典 CAN 单帧 8 字节 → Signal 长度最大 64 bit 。 CAN FD 单帧 64 字节 → Signal 长度最大 512 bit。
DBC 中 SG_ 段的 Length 字段超过 64,必然是 CAN FD。
5.3 其他标记
部分 DBC 工具会通过注释或自定义 BA_DEF_ 属性标记总线类型:
BA_DEF_ "BusType" STRING ;
BA_DEF_DEF_ "BusType" "CANFD";
但这不是标准字段,不可靠。BS_ 段的双波特率是唯一可靠的判断方式。
六、编程层面的影响
6.1 车型 Protocol 类(应用层)
变化极小,核心就是数据长度从 ≤8 变成 ≤64。
一个 Protocol 类典型的三个关键点:
// 1. 帧 ID ------ 和 CAN/CAN FD 无关,取决于车型 CAN 矩阵
const int32_t Accelcmd100::ID = 0x100;
// 2. 帧长度 ------ 经典 CAN ≤ 8,CAN FD 可以 ≤ 64
int32_t Accelcmd100::GetLength() const { return 8; }
// 3. 位定义、缩放因子、物理量转换 ------ 与 CAN/CAN FD 无关,照搬 DBC
void Accelcmd100::set_p_accel_cmd(uint8_t* data, double accel_cmd) {
uint16_t raw = static_cast<uint16_t>(accel_cmd / 0.001); // 精度 0.001
data[1] = (raw >> 8) & 0xFF;
data[2] = raw & 0xFF;
}
对应用层开发者来说:适配一辆 CAN FD 车型,Protocol 类代码逻辑和经典 CAN 完全一样,只是 GetLength() 返回值变大了。
6.2 底层驱动(CAN Client)
变化较大,需要处理:
-
CanFrame 结构体 ------
data[8]需要扩成data[64],len字段语义变化 -
FD 帧标志位 ------ 需要一个字段告诉硬件"这是 CAN FD 帧"
-
双波特率配置 ------ 仲裁段波特率和数据段波特率分开设置
-
收发器配置 ------ 必须切换到 CAN FD 模式
Apollo当前
CanFrame定义为经典CAN设计:struct CanFrame { uint32_t id; uint8_t data[8]; // ← 仅支持8字节,CAN FD需扩展至64字节 uint8_t len; };需修改为:
struct CanFrame { uint32_t id; uint8_t data[64]; // 支持CAN FD帧 uint8_t len; // 帧长度,经典CAN≤8,CAN FD≤64 bool is_fd_frame; // ← 新增:标记是否为CAN FD帧 };双波特率配置
CAN FD需分别设置仲裁段和数据段波特率,而非经典CAN的单一配置:
// 经典CAN驱动初始化 can_client_->Init(500000); // CAN FD驱动初始化 can_client_->Init(500000, 2000000); // 仲裁段500k,数据段2M
6.3 硬件层
-
CAN 卡(如 PEAK PCAN、Vector VN1640)必须支持 CAN FD
-
收发器必须是 CAN FD 型号(经典 CAN 收发器硬件上不识别 FDF 位)
-
总线长度要控制在数据段高速模式允许的范围内
-
CAN总线首尾两个节点 必须各加一个120Ω终端电阻 ,中间节点绝对不能加------这是CAN总线能可靠通信的硬性要求。原理:消除高速信号反射
七、兼容性矩阵
| 发送端 | 接收端 | 经典 CAN 帧 | CAN FD 帧 |
|---|---|---|---|
| 经典 CAN 控制器 | 经典 CAN 控制器 | ✅ | ❌ |
| CAN FD 控制器 | 经典 CAN 控制器 | ✅ | ❌ |
| CAN FD 控制器 | CAN FD 控制器 | ✅ | ✅ |
CAN FD 控制器向下兼容经典 CAN,但经典 CAN 无法理解 CAN FD------这意味着车载网络中只要还有一个经典 CAN 节点,就不能在那条总线上发 CAN FD 帧。车厂的应对策略通常是:在域控制器内部的高速通道用 CAN FD,对外保留经典 CAN 总线与传统 ECU 通信。
八、总结
| 角度 | 一句话 |
|---|---|
| 协议本身 | CAN FD = 更大的帧(64B)+ 更快的数据段(5~8 Mbps)+ 更强的 CRC |
| DBC 识别 | BS_ 段有两个波特率即 CAN FD |
| 应用层开发 | 和经典 CAN 几乎一样,只是数据长了 |
| 底层驱动 | 需要扩展 CanFrame、加 FD 标志、双波特率 |
| 硬件 | 必须换 CAN FD 收发器 |
| 兼容性 | CAN FD 能收经典 CAN,经典 CAN 不能收 CAN FD |
CAN FD 不是 CAN 的替代品,而是经典 CAN 的向后兼容的扩展------它在不破坏现有车载网络架构的前提下,为车厂提供了向域控制器、自动驾驶等高带宽场景平滑过渡的路径。
