3、CAN FD协议:从经典CAN到CAN FD的进化之路

大家好,我是你们的老朋友。今天我们来聊聊CAN FD协议。说实话,我刚接触CAN FD那会儿,心里也犯嘀咕——这不就是CAN的升级版吗?能有多大区别?结果真上手做了项目才发现,这里面的门道还真不少。

咱们直接切入正题。CAN FD,全称是CAN with Flexible Data-Rate。说白了,就是给经典CAN打了一针强心剂。我最早在2015年参与一个车载网关项目时,第一次在实车上用到了CAN FD。那时候芯片还贵,供应商也不多,调试起来真是踩了不少坑。

3.1 CAN FD与经典CAN的核心区别

先列个表,大家一目了然:

对比项 经典CAN CAN FD
最大数据场长度 8字节 64字节
最大位速率 1 Mbps 数据段最高8 Mbps(实际常用2-5 Mbps)
帧格式 标准帧/扩展帧 兼容经典帧 + FD帧
CRC校验 15位/17位/21位 17位/21位(数据场更长,安全性更高)
位速率切换 不支持 支持(仲裁段与数据段速率不同)

嗯,这里要注意。很多人以为CAN FD只是把速率提上去了。其实不然。我个人认为,数据场从8字节扩展到64字节,才是真正改变游戏规则的地方。你想想看,以前传一个诊断请求,动不动就要拆成好几帧。现在一帧搞定,效率提升不是一星半点。

核心观点:CAN FD不是简单的"加速版CAN",而是一次协议层面的重构。它保留了经典CAN的仲裁机制和总线访问优先级,但在数据传输效率和灵活性上做了质的飞跃。

3.2 CAN FD数据场长度编码——DLC的秘密

说到数据场长度,就不得不提DLC(Data Length Code)。经典CAN里,DLC是4位,直接表示0-8字节。CAN FD呢?同样是4位,但编码方式变了。

为什么会这样?因为4位二进制最多表示0-15,但CAN FD支持到64字节。所以协议规定了一个映射表:

DLC值 经典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

我刚开始做CAN FD开发时,就犯过一个低级错误。我在代码里直接写死了DLC=9对应9字节,结果接收端解析出来只有12字节,后面4个字节全是乱码。排查了半天才发现是DLC映射搞错了。所以大家记住:CAN FD的DLC不是线性映射,而是分段映射

来看一段实际代码,这是我在一个HIL测试项目中用到的DLC解析函数:

/* CAN FD DLC转实际字节数 */
uint8_t canfd_dlc_to_len(uint8_t dlc) {
    if (dlc <= 8) {
        return dlc;  /* 0-8字节,和经典CAN一致 */
    }
    switch (dlc) {
        case 9:  return 12;
        case 10: return 16;
        case 11: return 20;
        case 12: return 24;
        case 13: return 32;
        case 14: return 48;
        case 15: return 64;
        default: return 0;  /* 非法DLC */
    }
}

个人经验:在HIL测试中,我习惯把DLC映射表做成一个查找数组,而不是用switch-case。因为测试用例里经常要遍历所有DLC值,数组方式性能更好,代码也更简洁。

3.3 CAN FD的位速率切换——BRS位的妙用

这是CAN FD最亮眼的功能。经典CAN整个帧都是一个速率,比如500 kbps。CAN FD不一样,它在仲裁段数据段可以用不同的速率。

具体怎么实现的?看帧结构:

  • 仲裁段:SOF、ID、RTR、IDE、FDF、BRS、ESI等位。这部分速率较低(通常与经典CAN一致,比如500 kbps),保证总线仲裁的可靠性。
  • 数据段:DLC、Data、CRC、ACK等位。这部分速率可以切换到一个更高的值(比如2 Mbps甚至5 Mbps)。

切换的关键就是BRS位(Bit Rate Switch)。当BRS=1时,表示从下一个位开始切换到高速模式。当BRS=0时,全程保持仲裁段速率。

我曾经在一个项目中遇到过这样的问题:ECU的CAN FD控制器在高速模式下采样点设置不对,导致数据段频繁出现位错误。排查了整整两天,最后发现是相位缓冲段1(PB1)和相位缓冲段2(PB2)的比例没调好

避坑指南:我曾经因为采样点设置不当,导致CAN FD在2 Mbps下误码率高达5%。后来总结出经验:高速模式下,采样点建议设置在75%-80%的位置。仲裁段则保持在80%-87.5%。两个速率段的采样点要分别计算,不能偷懒用一个配置。

这里给出一组我常用的位时序配置参数:

/* 仲裁段:500 kbps,采样点87.5% */
#define ARB_BRP    4   /* 波特率预分频器 */
#define ARB_TSEG1  13  /* 时间段1(含同步段) */
#define ARB_TSEG2  2   /* 时间段2 */
#define ARB_SJW    2   /* 同步跳转宽度 */

/* 数据段:2 Mbps,采样点80% */
#define DATA_BRP   1   /* 预分频器减半 */
#define DATA_TSEG1 12  /* 时间段1 */
#define DATA_TSEG2 3   /* 时间段2 */
#define DATA_SJW   1   /* 同步跳转宽度 */

嗯,这里要注意。位速率切换不是瞬间完成的。协议规定了一个切换延迟时间,通常为1-2个位时间。在HIL测试中,我建议用示波器抓一下BRS位之后的波形,确认切换点没有毛刺或畸变。

3.4 CAN FD的兼容性设计——新旧设备如何共处

这是实际项目中绕不开的问题。你想想看,一辆车上不可能一夜之间把所有ECU都换成CAN FD。总有一些老节点还在用经典CAN。怎么让它们和平共处?

CAN FD协议在设计之初就考虑到了这一点。核心思路是:经典CAN节点看到CAN FD帧时,会把它当作一个错误帧来处理,然后总线会自动重发。但这显然不是我们想要的。

所以协议引入了FDF位(FD Format Indicator):

  • FDF=0:表示这是一个经典CAN帧。所有节点都能正常接收。
  • FDF=1:表示这是一个CAN FD帧。只有支持CAN FD的节点才能正确解析。

但问题来了——如果总线上混有经典CAN节点,它们看到FDF=1的帧会怎么反应?答案是:它们会检测到CRC错误,然后发送错误帧。这样一来,整个总线就被污染了。

怎么解决?我给大家三个实战策略:

  1. 物理隔离:把CAN FD节点和经典CAN节点放在不同的总线段上,中间用网关桥接。这是最稳妥的做法。我在一个商用车项目中就是这么干的。
  2. 协议降级:让CAN FD节点在发送时,检测到总线上有经典CAN节点,就自动降级为经典CAN模式(FDF=0,数据场不超过8字节)。这需要节点具备总线诊断能力。
  3. 混合模式:同一个节点既发经典CAN帧,也发CAN FD帧。关键帧(如安全相关)用经典CAN保证兼容性,大数据帧(如OTA升级)用CAN FD提高效率。

我的建议:在HIL测试中,一定要覆盖"混合总线"场景。我曾经测试过一个项目,CAN FD节点和经典CAN节点在同一总线上,结果经典CAN节点频繁报错,导致总线负载率飙升到80%以上。最后发现是CAN FD节点的发送间隔太短,经典CAN节点来不及恢复。解决办法是在CAN FD帧之间插入一个"恢复间隔"(至少3个空闲位)。

最后说一个容易被忽略的点:终端电阻。CAN FD在高速模式下对总线阻抗更敏感。我建议在HIL测试中,使用120Ω的终端电阻,并且确保总线长度不超过10米(2 Mbps下)。如果总线过长,信号反射会导致位错误。

好了,关于CAN FD协议的核心内容就讲到这里。下一章我们会深入CAN FD的物理层测试,包括眼图分析、信号质量评估等实战内容。到时候我会分享一些我在实验室里用示波器抓到的"翻车"波形,保证让你印象深刻。