CAN FD 基础回顾:从 CAN 2.0 到 CAN FD 的进化

各位同学,咱们开始第一讲。说实话,CAN FD 这个概念在汽车电子圈里已经火了好几年了。我最早接触它是在 2016 年做的一个车载网关项目,当时被客户要求支持 CAN FD,我还觉得「这玩意儿跟普通 CAN 有啥区别?」结果一上手才发现,坑还真不少。

这一章咱们先把地基打牢。我会从 CAN 2.0 和 CAN FD 的区别讲起,再到帧结构、速率提升原理,最后看看 STM32 的 CAN FD 外设长什么样。嗯,都是干货,没有废话。

1.1 CAN 2.0 与 CAN FD:到底差在哪?

先问大家一个问题:为什么要有 CAN FD?

传统 CAN 2.0 的带宽只有 1 Mbps,数据场最多 8 个字节。这在十年前够用,但现在一辆车上有几十个 ECU,OTA 升级、ADAS 数据、高精度地图……8 个字节?根本不够塞牙缝的。

CAN FD(Flexible Data-Rate)就是在这样的背景下诞生的。它保留了 CAN 2.0 的物理层和总线仲裁机制,但在数据段做了两件事:提速和扩容。

对比项 CAN 2.0 CAN FD
最大数据场长度 8 字节 64 字节
最大速率(数据段) 1 Mbps 8 Mbps(实际常用 2~5 Mbps)
帧格式 标准帧 / 扩展帧 兼容 CAN 2.0,新增 FDF 标志位
CRC 校验 15 位 CRC 17 位 / 21 位 CRC(根据数据长度)
总线仲裁 逐位仲裁 相同(仲裁段速率不变)
向后兼容 — CAN FD 节点可与 CAN 2.0 节点共存

核心要点:CAN FD 不是推翻重来,而是在 CAN 2.0 的基础上做了「局部加速」和「数据扩容」。仲裁段仍然用原来的速率,只有数据段才切换到高速模式。这样做的好处是——总线仲裁逻辑不变,现有 CAN 控制器可以低成本升级。

1.2 CAN FD 帧结构:多出来的那些位

咱们来看看 CAN FD 的帧长什么样。我习惯把 CAN FD 帧分成三段:仲裁段、控制段、数据段。

跟 CAN 2.0 相比,CAN FD 在控制段里多了几个关键位:

  • FDF 位(Flexible Data Format):这是 CAN FD 的「身份证」。FDF = 1 表示这是一个 CAN FD 帧,CAN 2.0 控制器看到这个位会直接报错。
  • BRS 位(Bit Rate Switch):速率切换开关。BRS = 1 时,从 BRS 位之后的数据段切换到高速模式;BRS = 0 则全程用仲裁段速率。
  • ESI 位(Error State Indicator):发送节点的错误状态指示。主动错误节点发 0,被动错误节点发 1。
  • DLC 编码变化:CAN FD 的 DLC 从 0~8 映射到数据长度 0~64 字节,具体映射表后面会讲。

我给大家画了一张帧结构对比图,一看就明白:

CAN 2.0 与 CAN FD 帧结构对比 CAN 2.0 帧: SOF 仲裁段 (11/29 bit ID) 控制段 数据段 (0~8B) CRC ACK EOF CAN FD 帧: SOF 仲裁段 (11/29 bit ID) 控制段 (含FDF/BRS/ESI) 数据段 (0~64B) ★高速 CRC (17/21位) ACK EOF BRS=1 切换高速 💡 注意:CAN FD 的仲裁段和 CAN 2.0 完全兼容,所以 CAN FD 节点可以和 CAN 2.0 节点挂在同一总线上。 但 CAN 2.0 节点收到 FDF=1 的帧会报错,所以混合组网时需要做「CAN FD 透明」处理。

我的经验:刚开始用 CAN FD 时,我总搞混 BRS 位的作用。记住一句话——BRS 位是「油门」,踩下去(=1)数据段就加速,松掉(=0)就按原速跑。但要注意,BRS 位本身是用仲裁段速率传输的,所以接收端必须在 BRS 位之后立即切换采样点。

1.3 数据段速率提升原理:为什么能跑那么快?

好,接下来是重点。CAN FD 的数据段速率为什么能提升到 5 Mbps 甚至更高?

说白了,就两个原因:缩短位时间和优化采样点。

在仲裁段,所有节点必须同步采样,因为要逐位仲裁。这时候位时间不能太短,否则传播延迟会导致仲裁失败。CAN 2.0 的位时间通常设在 1 µs(1 Mbps),再快就危险了。

但进入数据段后,仲裁已经结束,总线上只有一个节点在发送。这时候就没有「多节点同步」的压力了。我们可以把位时间缩短到 200 ns(5 Mbps)甚至 125 ns(8 Mbps)。

不过,这里有个陷阱——采样点位置。高速模式下,位时间变短,采样点的精度要求更高。我见过一个项目,CAN FD 在 4 Mbps 下跑得好好的,换了一批发动机 ECU 就疯狂报错。查了半天,发现是采样点偏移了 5%。

⚠️ 避坑指南:我曾经在一个车载项目中,把 CAN FD 数据段速率设到 8 Mbps,结果发现线束稍微长一点(超过 1 米)就丢帧。后来老老实实降到 4 Mbps,配合 70% 采样点,稳如老狗。记住:速率越高,对线束、终端电阻、PCB 走线的要求越苛刻。

下面这张图展示了 CAN FD 的速率切换过程:

CAN FD 速率切换时序 仲裁段 (1 Mbps) BRS位 数据段 (5 Mbps) ★高速 CRC段 ACK+EOF 1 Mbps 5 Mbps 🔑 关键点:BRS 位之后,发送节点立即切换位时序,接收节点同步切换采样点。 切换必须在 1 个位时间内完成,这对 CAN 控制器的硬件设计提出了很高要求。

1.4 STM32 CAN FD 外设概述

好了,理论讲完了,咱们来看看 STM32 是怎么实现 CAN FD 的。

STM32 的 CAN FD 外设,在 FDCAN 系列(比如 STM32H7、G4、L5 等)中集成。它基于 Bosch M_CAN 内核,支持 CAN FD 规范 ISO 11898-1:2015。

我个人觉得 STM32 的 FDCAN 外设有几个亮点:

  • 双时钟域:一个时钟给仲裁段(通常 40~80 MHz),另一个给数据段(最高 80 MHz),方便独立配置速率。
  • 64 字节专用 RAM:用于消息 RAM,支持最多 32 个 Rx FIFO 和 32 个 Tx 缓冲。
  • 硬件时间戳:每个接收帧自动打上时间戳,精度可达 10 ns。我在做 CAN FD 数据记录时特别喜欢这个功能。
  • 低功耗模式:支持 Sleep、Standby 和 Wake-up,这也是咱们后面课程的重点。

下面是一个典型的 STM32 FDCAN 初始化代码片段,我习惯用 HAL 库:

/* FDCAN 初始化配置 */
FDCAN_HandleTypeDef hfdcan1;
hfdcan1.Instance = FDCAN1;

hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS;  // CAN FD 帧,带 BRS
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = ENABLE;

/* 仲裁段:1 Mbps */
hfdcan1.Init.NominalPrescaler = 2;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 13;
hfdcan1.Init.NominalTimeSeg2 = 2;

/* 数据段:4 Mbps */
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 9;
hfdcan1.Init.DataTimeSeg2 = 2;

HAL_FDCAN_Init(&hfdcan1);

小提示:配置数据段速率时,别忘了检查 STM32 的 FDCAN 时钟源。我遇到过有人把 FDCAN 时钟配成 40 MHz,却想跑 8 Mbps 数据段——位时间只有 5 个时钟周期,根本不够用。一般建议数据段位时间至少 8~10 个时钟周期。

1.5 本章小结

咱们这一章把 CAN FD 的基础过了一遍。总结几个关键点:

  • CAN FD 是 CAN 2.0 的升级版,核心改进是数据段提速和数据场扩容。
  • 帧结构多了 FDF、BRS、ESI 三个控制位,理解它们的作用是配置 CAN FD 的前提。
  • 速率提升的原理是「仲裁后加速」,但采样点配置和线束质量是瓶颈。
  • STM32 的 FDCAN 外设功能强大,双时钟域和硬件时间戳是亮点。