3、CAN FD数据链路层详解:CAN FD的仲裁机制、CAN FD的错误检测与错误帧、CAN FD的位填充机制、CAN FD的CRC校验(17位/21位)
大家好,我是你们的讲师。今天咱们来啃一块硬骨头——CAN FD的数据链路层。说实话,很多工程师用CAN FD好几年,对仲裁和CRC还是一知半解。我个人觉得,搞懂这一层,才算真正入了CAN FD的门。
咱们不搞教科书式的罗列,我直接把我这些年调试中踩过的坑、总结的经验,揉碎了讲给你听。
3.1 CAN FD的仲裁机制:还是那个味儿,但更快了
先聊仲裁。CAN FD的仲裁机制,说白了跟经典CAN一模一样——非破坏性逐位仲裁。你想想看,为什么叫“非破坏性”?因为赢了的节点继续发,输了的节点自动闭嘴,总线上的数据一点没坏。
具体怎么仲裁?靠的是“显性位(0)”压倒“隐性位(1)”。谁先发0,谁就赢。我刚开始学的时候,总觉得这跟“谁嗓门大谁说话”一个道理。嗯,差不多就是这个意思。
我在项目中遇到过一个问题:有个节点在仲裁阶段总是莫名其妙丢仲裁。查了半天,发现是它的振荡器精度不够,导致位时间偏差太大。后来换了高精度晶振,问题解决。所以啊,仲裁阶段的时钟同步,比你想的更重要。
3.2 CAN FD的错误检测与错误帧:五种武器,一个都不能少
CAN FD的错误检测机制,可以说是汽车电子里最严密的。它用了五种错误检测方法,我一个个说。
- 位错误(Bit Error):发送节点监控总线,发现自己发的跟总线上的不一样,立刻报错。注意,仲裁阶段和ACK槽阶段不检测位错误,因为那会儿允许冲突。
- 填充错误(Stuff Error):这个后面细讲,简单说就是连续5个相同位后,没出现填充位。
- CRC错误(CRC Error):接收节点算出来的CRC跟发送的不一致。
- 格式错误(Form Error):固定格式的位段(比如CRC分隔符、ACK分隔符)出现了错误电平。
- ACK错误(Acknowledgement Error):发送节点没收到显性ACK。
一旦检测到错误,节点就会发送错误帧。错误帧由两部分组成:错误标志(6个显性位)和错误分隔符(8个隐性位)。
3.3 CAN FD的位填充机制:为什么从5位变成了4位?
位填充,是为了保证时钟同步。经典CAN是每5个相同位后插入一个相反位。CAN FD呢?在数据段,改成了每4个相同位后插入一个相反位。
为什么会这样?你想想看,CAN FD的数据段速率高了,位时间短了。如果还用5位填充,万一连续5个相同位,接收节点的锁相环可能就失锁了。缩短到4位,填充更频繁,同步更可靠。
我个人的习惯是,在写CAN FD驱动时,一定要确认MCU的CAN FD控制器是否支持自动位填充。有些老旧的控制器只支持经典CAN的5位填充,用在CAN FD上会出大问题。
| 对比项 | 经典CAN | CAN FD |
|---|---|---|
| 填充规则 | 每5个相同位插入1个 | 每4个相同位插入1个(数据段) |
| 仲裁段填充 | 5位规则 | 5位规则(不变) |
| 填充位置 | 从SOF到CRC结束 | 从SOF到CRC结束(数据段用4位规则) |
3.4 CAN FD的CRC校验:17位还是21位,这是个问题
CRC校验,是CAN FD数据链路层的重头戏。经典CAN用的是15位CRC,CAN FD升级了,提供了两种选择:17位CRC和21位CRC。
怎么选?看数据长度:
- 数据长度 ≤ 16字节:用17位CRC
- 数据长度 > 16字节:用21位CRC
为什么这么分?说白了,数据越长,出错的概率越大,需要更强的校验能力。21位CRC的汉明距离更大,能检测更多错误模式。
我给大家看个实际计算例子。假设我们要发送8字节数据,用17位CRC:
// 伪代码:CAN FD 17位CRC计算
// 生成多项式:0x3685B(x^17 + x^16 + x^14 + x^13 + x^11 + x^10 + x^9 + x^8 + x^7 + x^5 + x^3 + x^2 + x + 1)
uint32_t calc_crc17(uint8_t *data, uint8_t len) {
uint32_t crc = 0;
for (int i = 0; i < len; i++) {
crc ^= (data[i] << 9);
for (int j = 0; j < 8; j++) {
if (crc & 0x10000) {
crc = (crc << 1) ^ 0x3685B;
} else {
crc <<= 1;
}
}
}
return crc & 0x1FFFF; // 取17位
}
最后说个我踩过的坑。有一次,我用CAN FD传输64字节大数据包,接收端总是报CRC错误。查了两天,发现是发送端的CRC生成多项式配置错了——它用了17位多项式,但数据长度超过16字节,应该用21位。嗯,这种低级错误,配置寄存器时多看一眼就能避免。
好了,这一章的内容就到这里。数据链路层是CAN FD的基石,仲裁、错误检测、位填充、CRC,每一个都值得你花时间吃透。下一章,咱们聊聊CAN FD的物理层,看看那些电平信号和位时序到底是怎么回事。