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”。