3. CANFD数据链路层:数据场长度扩展、CRC校验改进、位填充机制、错误处理机制
好,咱们进入CANFD最核心的改动——数据链路层。说实话,经典CAN的数据链路层已经非常成熟了,但面对自动驾驶和OTA升级,它有两个硬伤:数据太短,速率太慢。CANFD就是冲着这两个问题来的。
我个人习惯把数据链路层拆成四个模块来看:数据场怎么变长、CRC怎么更安全、位填充怎么优化、错误怎么处理。咱们一个一个聊。
3.1 数据场长度扩展:从8到64字节的跨越
经典CAN的数据场最多8字节。你想想看,一个高精地图包或者一个固件升级包,动不动就几KB。用CAN传?得拆成几百帧,效率低得吓人。
CANFD直接把数据场长度扩展到最多64字节。怎么做到的?靠的是DLC(数据长度码)的重新定义。
经典CAN的DLC是4位,理论上能表示0-15。但实际只用到0-8,9-15都是保留的。CANFD把这4位用满了,但映射关系不是线性的。我刚开始看这个表的时候也愣了一下,后来才明白是为了兼容性考虑。
| DLC值 | 经典CAN数据长度(字节) | CANFD数据长度(字节) |
|---|---|---|
| 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 |
关键点:DLC=9时,数据长度是12字节,不是9字节。这个映射关系是固定的,写驱动时千万别搞错。
我在项目中遇到过一个问题:某个供应商的CANFD控制器,DLC=9时只发了9个字节,结果接收方直接报CRC错误。查了半天,原来是他们固件里写死了「DLC就是字节数」。嗯,这种坑踩过一次就记住了。
3.2 CRC校验改进:从15位到21位,还有可选的17/21位
数据变长了,校验也得跟上。经典CAN用的是15位CRC,对于8字节数据够用。但64字节?15位CRC的汉明距离不够,漏检率会上升。
CANFD引入了两种新的CRC:
- 17位CRC:用于数据场长度≤16字节的情况
- 21位CRC:用于数据场长度>16字节的情况
说白了,就是根据数据量动态选择CRC长度。数据少就用短CRC,省带宽;数据多就用长CRC,保安全。
这里有个细节我特别想强调:CRC的计算范围变了。经典CAN只算数据场,CANFD把控制场的一部分也纳入了CRC计算。为什么?因为控制场里有BRS位(波特率切换标志)和ESI位(错误状态指示),这两个位如果被干扰,整个帧的解析都会出问题。
我的经验:调试CANFD通信时,如果CRC总报错,先别急着怀疑硬件。检查一下CRC计算时是否包含了BRS位。我曾经在一个项目中,因为CRC多项式配置错了,整整调了两天。后来发现是某家芯片的CRC种子值默认不是0,而是0xFFFF。
3.3 位填充机制:从固定到灵活
位填充是CAN总线的一个经典机制。为了防止连续5个相同电平导致时钟同步丢失,发送方会在每5个相同位之后插入一个相反位。接收方再把这些填充位去掉。
经典CAN的位填充是固定速率的——仲裁段和数据段都用同样的位时间。但CANFD不一样,它引入了双速率:
- 仲裁段:用标准速率(比如500kbps),位填充规则不变
- 数据段:用高速率(比如2Mbps甚至5Mbps),位填充规则做了调整
为什么会这样?你想想看,高速率下,位时间很短。如果还按每5位填充一次,填充位的插入和删除会占用大量CPU时间。CANFD的做法是:数据段高速率下,位填充的间隔可以动态调整。有些实现甚至允许在数据段关闭位填充(但我不建议这么做,风险太大)。
注意:位填充的调整只影响数据段。仲裁段必须保持经典CAN的位填充规则,否则无法兼容。
我记得有一次调试,发现CANFD在2Mbps下偶尔丢帧。用示波器抓了波形才发现,是位填充导致的信号畸变。后来把采样点从70%调整到80%,问题就解决了。嗯,位填充和采样点的关系,很多人容易忽略。
3.4 错误处理机制:多了两个新错误
经典CAN有5种错误:位错误、填充错误、CRC错误、形式错误、应答错误。CANFD保留了这5种,但增加了两个新的:
- 填充错误(新增场景):在数据段高速率下,如果接收方检测到填充规则被违反,会报填充错误。但注意,这个错误的处理方式和经典CAN略有不同——CANFD允许接收方在数据段直接发送错误帧,而不必等到帧结束。
- CRC边界错误:CRC分隔符必须是隐性位。如果检测到显性位,就报这个错误。这个在经典CAN里属于形式错误的一部分,CANFD把它独立出来了。
另外,CANFD的错误恢复机制也有变化。经典CAN在错误后会自动重发,但CANFD多了一个选项:错误帧可以只影响数据段。也就是说,如果数据段出错了,仲裁段已经传完的信息可以保留,不用整个帧重来。这个优化对高负载网络特别有用。
避坑指南:我曾经在一个项目中,CANFD总线偶尔出现大量错误帧。排查后发现是某个节点的晶振偏差太大,导致位时序漂移。CANFD对时钟精度要求比经典CAN高得多——经典CAN允许±1.5%的偏差,CANFD在高速率下要求±0.5%以内。所以,选晶振时别省钱。
3.5 小结:数据链路层的四个变化
咱们捋一下:
- 数据场:从8字节扩展到64字节,DLC映射关系变了
- CRC:从15位升级到17/21位,计算范围包含了控制场
- 位填充:数据段支持动态调整,高速率下更灵活
- 错误处理:新增了CRC边界错误,错误恢复可以只影响数据段
这四个变化,每一个都牵一发而动全身。你如果只是把经典CAN的驱动改一改就拿来用,大概率会出问题。我建议你从底层开始,重新理解CANFD的数据链路层协议。下一章咱们聊物理层,那个坑更多。