1. CAN与CANFD基础概念对比:标准CAN帧结构 vs CANFD帧结构,数据场长度、波特率、DLC编码差异
好,咱们直接进入正题。很多工程师刚接触CANFD时,第一反应就是“这不就是CAN的升级版吗?”
嗯,这么说也没错,但如果你真把它当CAN来用,调试的时候会踩不少坑。
我个人习惯是,先搞清楚帧结构上的差异,再谈别的。因为帧结构决定了你能传多少数据、能跑多快、以及怎么解析。
1.1 标准CAN帧结构回顾
先简单过一下标准CAN帧。你肯定见过这个:
SOF + 11位ID + RTR + IDE + r0 + 4位DLC + 0~8字节数据 + CRC + ACK + EOF
这里有几个关键点:
- 数据场长度:最多8个字节。这是CAN协议诞生时就定死的,当年觉得8个字节够用了,现在嘛...你想想看,一个ECU刷写动辄几百KB,8字节一帧得发到猴年马月。
- 波特率:整个帧都是同一个波特率。比如你设了500kbps,那从SOF到EOF全是500k。我在项目中遇到过,有些节点在总线负载高时,仲裁段没问题,但数据段太长导致位定时误差累积,最后丢帧。
- DLC编码:4位DLC,取值范围0~8,直接对应数据字节数。比如DLC=3,就是3个字节数据。很简单,对吧?
核心记忆点:标准CAN帧,数据最多8字节,整帧同速,DLC就是数据长度。
1.2 CANFD帧结构:到底改了啥?
CANFD的帧结构,说白了就是在标准CAN帧上“打了几个补丁”。但这几个补丁,让整个协议脱胎换骨。
SOF + 11/29位ID + RTR + IDE + r0 + BRS + ESI + 4位DLC + 0~64字节数据 + CRC + ACK + EOF
你仔细看,多了两个位:BRS 和 ESI。另外,数据场长度、波特率、DLC编码全变了。
1.3 数据场长度:从8到64,质的飞跃
CANFD的数据场最大支持64字节。为什么是64?不是128或256?
我记得当时看博世的文档,他们做过统计,大部分车载应用的单次数据需求在32~64字节之间。64字节刚好够用,又不会让CRC校验过于复杂。
我在做电池管理系统(BMS)项目时,原来用CAN传电池单体电压,一帧只能传4个单体(每个2字节),要传完96个单体得24帧。换成CANFD后,一帧64字节能传32个单体,3帧搞定。总线负载直接降了70%。
我的建议:如果你的应用需要传输超过8字节的数据块,别犹豫,直接上CANFD。但要注意,不是所有ECU都支持64字节,有些老节点只支持到32字节。设计时要向下兼容。
1.4 波特率:仲裁段 vs 数据段,双速率来了
这是CANFD最骚的操作——双波特率。
- 仲裁段:沿用CAN的波特率,比如500kbps。为什么?因为仲裁段需要所有节点参与总线仲裁,必须统一速率。
- 数据段:可以切换到高速率,比如2Mbps甚至5Mbps。因为数据段不需要仲裁,谁拿到总线谁说话,速率可以飙起来。
切换的关键就是那个BRS位(Baud Rate Switch)。BRS=1时,从数据段开始切换到高速率;BRS=0时,整帧保持仲裁段速率,兼容标准CAN。
我曾经踩过的坑:有一次我设了数据段5Mbps,结果某个老节点直接罢工。查了半天才发现,那个节点的CANFD控制器最高只支持2Mbps数据段。所以,设计网络时一定要确认所有节点的数据段速率上限,取最小值。
1.5 DLC编码差异:不再是简单的1:1映射
标准CAN的DLC编码很简单:DLC=0~8,数据长度就是0~8字节。
但CANFD的DLC编码,嗯,这里要注意,它变了。
因为数据场最大64字节,而DLC只有4位(0~15),所以不能直接映射。CANFD的DLC编码规则如下:
| DLC值 | 标准CAN数据长度(字节) | CANFD数据长度(字节) |
|---|---|---|
| 0~8 | 0~8 | 0~8 |
| 9 | 不允许 | 12 |
| 10 | 不允许 | 16 |
| 11 | 不允许 | 20 |
| 12 | 不允许 | 24 |
| 13 | 不允许 | 32 |
| 14 | 不允许 | 48 |
| 15 | 不允许 | 64 |
看到了吗?DLC=9时,数据长度是12字节,不是9字节。DLC=15时,才是64字节。
为什么会这样?说白了,是为了在4位DLC中覆盖0~64的范围,只能跳着映射。中间那些值(比如9、10、11...)对应的数据长度,都是8的倍数或接近8的倍数,方便内存对齐。
避坑指南:在写CANFD解析代码时,千万别直接用DLC值当数据长度。我见过有人直接拿DLC当长度去memcpy,结果数据对不上,排查了一整天。正确做法是建一个查找表,或者用协议栈提供的API去转换。
1.6 帧结构对比总结
来,我把关键差异列个表,方便你对照:
| 对比项 | 标准CAN | CANFD |
|---|---|---|
| 数据场最大长度 | 8字节 | 64字节 |
| 波特率 | 整帧统一 | 仲裁段/数据段可不同 |
| DLC编码 | 0~8直接映射 | 0~8直接映射,9~15跳变映射 |
| 新增控制位 | 无 | BRS、ESI |
| CRC | 15位CRC | 17位(数据≤16字节)或21位(数据>16字节) |
| 兼容性 | — | 向下兼容标准CAN(BRS=0时) |
我个人觉得,CANFD最大的价值不是快,而是灵活。你可以根据实际需求,在兼容性和性能之间做权衡。比如,和旧节点通信时用标准CAN模式,和新节点通信时切到CANFD模式。这在CANalyzer里配置起来也很方便,后面章节我会详细讲。
一个小技巧:在CANalyzer的Trace窗口里,你可以直接看到帧的BRS和ESI位状态。如果BRS=1,说明数据段用了高速率。如果ESI=1,说明发送节点处于错误被动状态。这两个位在调试时非常有用,建议你养成查看的习惯。
好了,这一节的内容就到这里。下一节我会带你用CANalyzer实际抓几帧CAN和CANFD的波形,看看它们在总线上的真实表现。到时候你会发现,理论归理论,实际波形里藏着更多细节。