3. CAN FD数据链路层:帧结构详解

好,咱们进入CAN FD最核心的一层——数据链路层。说白了,这一层就是决定“数据怎么打包、怎么发、怎么保证不出错”的。很多工程师学CAN FD,卡就卡在这一块。我个人习惯是,先把帧结构掰开揉碎了看明白,后面那些速率提升、兼容性设计,自然就通了。

3.1 标准帧 vs 扩展帧:11位ID和29位ID的博弈

先聊帧结构。CAN FD保留了经典CAN的两种帧格式:标准帧和扩展帧。区别在哪?就在仲裁场那11位ID和29位ID上。

标准帧,ID只有11位。你想想看,11位二进制能表示多少?2048个。对大多数车载网络来说,够用了。但现在的车,一个网关后面挂几十个ECU,各种信号满天飞,2048个ID有时候真不够分。

扩展帧,ID是29位。这就有5亿多个标识符了。我做过一个项目,某主机厂要求所有诊断报文必须用扩展帧,就是为了避免和动力总成的CAN报文冲突。嗯,这里要注意:扩展帧不是标准帧的“升级版”,它们是两种不同的格式,在同一个网络上可以共存。

来看一下帧结构的对比:

字段 标准帧 扩展帧
仲裁场ID长度 11位 29位
IDE位 显性(0) 隐性(1)
RTR位
数据场最大长度 8字节(CAN FD可达64) 8字节(CAN FD可达64)

我个人建议:如果项目是新设计的,优先用标准帧。ID不够?那就用CAN FD的64字节数据场,一个报文顶八个,ID占用自然就少了。实在不行再上扩展帧。

3.2 数据场长度编码(DLC):从4位到更灵活的映射

DLC,Data Length Code,4个位。经典CAN里,DLC直接对应数据字节数:0到8。但CAN FD不一样了,它支持最大64字节的数据场。4位二进制最多表示16种状态,怎么映射到0~64?

看这张表就明白了:

DLC值(二进制) 经典CAN数据长度(字节) CAN FD数据长度(字节)
0000 ~ 1000 0 ~ 8 0 ~ 8
1001 8 12
1010 8 16
1011 8 20
1100 8 24
1101 8 32
1110 8 48
1111 8 64

看到了吧?DLC值从9到15,在经典CAN里统统映射到8字节,但在CAN FD里,它们对应12、16、20……一直到64。我刚开始做CAN FD驱动时,就踩过这个坑——以为DLC=9就是9字节,结果解析出来的数据全是乱的。后来查了协议才知道,DLC不是线性映射的。

核心要点:CAN FD的DLC编码是非线性的。写代码时千万别直接用DLC值当长度,一定要查表或者用协议栈提供的转换函数。

3.3 位填充机制:为什么CAN FD要改规则?

位填充,这是CAN总线保证时钟同步的老传统了。经典CAN的规则是:连续发送5个相同电平的位后,自动插入一个相反电平的位。这样接收端就能不断重新同步时钟。

但CAN FD在数据场部分,把规则改了。改成什么?改成“连续发送5个相同电平的位后,插入一个相反电平的位,但插入的位不计入数据”。 等等,这和经典CAN有什么区别?

区别大了。经典CAN里,填充位是算在数据流里的,接收端收到后要把它剔除。而CAN FD在高速数据段(BRS位之后的区域),填充位不参与CRC计算。这意味着什么?意味着CRC校验的覆盖范围变了。

我举个例子:假设数据场里有连续6个显性位。经典CAN会在第5位后插入一个隐性填充位,然后CRC计算时把这6个位(5个数据+1个填充)都算进去。CAN FD呢?它只算那5个数据位,填充位不算。

避坑指南:我曾经在一个项目中,用经典CAN的CRC算法去校验CAN FD的报文,结果死活对不上。后来才发现,CAN FD的CRC计算范围排除了填充位。所以,写CRC校验代码时,一定要区分是经典CAN模式还是CAN FD模式。

3.4 CRC校验升级:从15位到21位,安全性翻倍

CRC校验,这是数据链路层的最后一道防线。经典CAN用的是15位CRC,多项式是x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1。这个多项式对付8字节的数据场,绰绰有余。

但CAN FD的数据场最长64字节,15位CRC的检错能力就不够看了。所以CAN FD引入了两种新的CRC:

  • 17位CRC:用于数据场长度≤16字节的报文
  • 21位CRC:用于数据场长度>16字节的报文

这两个CRC的多项式分别是:

  • 17位CRC:x^17 + x^16 + x^14 + x^13 + x^11 + x^10 + x^9 + x^8 + x^7 + x^6 + x^5 + x^3 + x^2 + x + 1
  • 21位CRC:x^21 + x^20 + x^13 + x^11 + x^10 + x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x + 1

说白了,就是多项式阶数更高,检错能力更强。我算过,21位CRC的汉明距离比15位CRC提升了将近一倍。对于自动驾驶这种对安全性要求极高的场景,这个升级是必须的。

注意:CAN FD的CRC计算范围包括:SOF位、仲裁场、控制场、数据场,但不包括填充位(在高速数据段)。这个细节很容易被忽略,但一旦出错,整个通信链路都会崩溃。

最后说一句,CRC的硬件实现其实不难。现在主流的CAN FD控制器(比如NXP的TJA1145、TI的TCAN4550)都内置了CRC硬件模块,软件只需要配置好模式就行。但如果你是用MCU的CAN FD外设,记得检查一下它是否支持17位和21位CRC的自动计算。我见过一些早期的CAN FD控制器,只支持15位CRC,那其实是个“假CAN FD”。