2、CAN数据帧结构:SOF、仲裁场、控制场、数据场、CRC场、ACK场、EOF详解
说实话,搞CAN诊断这么多年,我最怕的就是有人一上来就背帧结构。背得滚瓜烂熟,真到抓波形的时候,连SOF在哪都找不到。我个人习惯是——把帧结构当成一条公路,每个字段就是一个路段。你只要知道每个路段是干嘛的,出问题就知道去哪查。
好,咱们今天就一条一条捋清楚。
2.1 SOF(Start of Frame)——帧起始
SOF就是一个显性位(逻辑0)。它告诉总线上所有节点:我要开始说话了。
你想想看,总线平时是隐性电平(逻辑1),突然拉低,大家就知道有数据要来了。这个动作很简单,但非常重要。我记得有一次调试,发现某个节点老是丢帧,抓波形一看,SOF后面紧跟着一个毛刺,把同步给破坏了。嗯,这种问题往往跟硬件设计有关,终端电阻没配好。
2.2 仲裁场(Arbitration Field)——谁说了算
仲裁场包含两部分:ID(标识符)和RTR(远程传输请求位)。
ID就是消息的身份证。标准帧是11位,扩展帧是29位。ID越小,优先级越高。为什么?因为显性位(0)会覆盖隐性位(1)。
举个例子:
- 节点A发ID=0x123(二进制:0001 0010 0011)
- 节点B发ID=0x124(二进制:0001 0010 0100)
当它们同时发送时,从高位开始比。比到第8位,A是0,B是1。A赢了,B乖乖退出发送,转为接收。
RTR位呢?平时数据帧是显性(0),远程帧是隐性(1)。说白了,远程帧就是“你发个数据给我看看”,但实际项目中远程帧用得很少。我建议你直接忽略它,先把数据帧搞明白。
2.3 控制场(Control Field)——数据有多长
控制场有6位:
- IDE位(1位):0表示标准帧,1表示扩展帧
- 保留位(1位):标准帧叫r0,扩展帧叫r1,必须发显性(0)
- DLC(4位):数据长度代码,范围0~8
DLC这玩意儿我吃过亏。有一次客户报故障,说某个节点发出来的数据长度不对。我抓波形一看,DLC=8,但实际数据场只有4个字节有效,后面4个字节全是垃圾。后来发现是代码里DLC写死了8,但数据只填了4个。
记住:DLC必须跟实际数据长度一致。多出来的字节,接收方会当成有效数据来处理,容易引发逻辑错误。
| DLC值 | 数据长度(字节) | 常见用途 |
|---|---|---|
| 0 | 0 | 远程帧、心跳信号 |
| 1~7 | 1~7 | 单信号、小数据包 |
| 8 | 8 | UDS诊断、多信号打包 |
2.4 数据场(Data Field)——真正的干货
数据场就是你要传的实际数据,0~8个字节。CAN FD可以到64字节,但那是后话了。
数据怎么放?有两种方式:
- Motorola格式(大端):高字节在前,低字节在后。比如0x1234,先发0x12,再发0x34。
- Intel格式(小端):低字节在前,高字节在后。比如0x1234,先发0x34,再发0x12。
我见过最坑的事,就是整车厂和供应商对信号格式理解不一致。一个用Motorola,一个用Intel,结果车速显示300km/h。嗯,车没跑,数据先飞了。
2.5 CRC场(Cyclic Redundancy Check)——数据对不对
CRC场包含15位CRC序列和1位CRC界定符(隐性)。
CRC的作用很简单:接收方算一遍,跟发送方算的对比。不一样?说明数据被干扰了,直接丢帧。
CAN的CRC算法是固定的,多项式是:x¹⁵ + x¹⁴ + x¹⁰ + x⁸ + x⁷ + x⁴ + x³ + 1。你不用背,工具会算。但你要知道,CRC覆盖的范围是从SOF到数据场结束。
我曾经遇到一个奇葩问题:CRC每次都错,但波形看着没问题。后来发现是晶振偏差太大,导致采样点偏移,CRC算出来就不对了。换了个高精度晶振,问题解决。
2.6 ACK场(Acknowledge)——收到了没
ACK场就2位:
- ACK Slot(1位):发送方发隐性(1),接收方拉显性(0)表示确认
- ACK界定符(1位):必须隐性(1)
这里有个细节:只要总线上有一个节点正确接收了帧,ACK Slot就会被拉低。所以发送方看到ACK Slot是显性,就知道至少有一个节点收到了。
如果发送方发现ACK Slot还是隐性?说明没人理它。这时候发送方会重发。重发次数超过上限,就报Bus Off。
我记得有一次,一个节点老是报Bus Off。抓波形发现,它发完数据后ACK Slot一直是隐性。查了半天,原来是这个节点的CAN控制器配置成了只听模式(Listen Only),不会发ACK。嗯,配置错了。
2.7 EOF(End of Frame)——说完了
EOF是7个连续的隐性位(1)。它告诉总线:这帧结束了,大家可以抢下一帧了。
为什么是7位?因为位填充机制最多连续5个相同位,7个隐性位足够让所有节点识别出帧结束。如果EOF被破坏(比如出现显性位),接收方会认为帧不完整,直接丢弃。
EOF后面还有3位ITM(Intermission),也就是帧间隔。这3位也是隐性,用来让总线喘口气。
2.8 完整帧结构一览
把上面所有字段串起来,一个标准数据帧长这样:
SOF | ID(11位) | RTR | IDE | r0 | DLC(4位) | Data(0~8字节) | CRC(15位) | CRC界定符 | ACK Slot | ACK界定符 | EOF(7位)
1 11 1 1 1 4 0~64 15 1 1 1 7
总位数:1 + 11 + 1 + 1 + 1 + 4 + (0~64) + 15 + 1 + 1 + 1 + 7 = 44~108位(不含位填充)。
加上位填充后,实际长度会略长。但别担心,CAN控制器会自动处理这些。
2.9 我的调试建议
如果你刚开始学CAN,我建议你这么做:
- 拿一个CAN分析仪,抓一段真实的总线数据
- 对照帧结构,把每个字段标出来
- 重点关注SOF和EOF,看它们是否完整
- 检查CRC,看有没有错误帧
- 看ACK Slot,确认节点间通信正常
等你亲手抓过几十帧波形,这些字段就刻在脑子里了。比死记硬背强一百倍。
好,这一章就到这儿。下一章咱们聊聊CAN的位时序和同步机制——说白了就是,为什么总线上那么多节点,数据还能不乱套。