第1章:CAN数据帧详解——标准帧与扩展帧、数据帧结构
各位同学,咱们今天聊点实在的。CAN数据帧,说白了就是总线上跑的数据包。你想想看,一辆车上几十个ECU,大家怎么交流?就是靠这个数据帧。我做了十几年CAN开发,第一次调通数据帧的时候,那种感觉,嗯,就像打通了任督二脉。
1.1 标准帧 vs 扩展帧:到底差在哪?
先说说标准帧和扩展帧的区别。这个问题,我面试新人时必问。很多人背得滚瓜烂熟,但一问到实际应用场景就卡壳。
标准帧的ID是11位,扩展帧是29位。就这么简单?不,背后有故事。
我记得2015年做一个商用车项目,整车控制器需要跟十几个子节点通信。标准帧的11位ID,满打满算也就2048个可用ID。你想想看,一个动力系统、一个车身系统、再加个信息娱乐系统,ID很快就用完了。那时候我就在想,要是当初设计时用了扩展帧就好了。
核心区别对照表:
| 对比项 | 标准帧 | 扩展帧 |
|---|---|---|
| ID位数 | 11位 | 29位 |
| ID范围 | 0x000 ~ 0x7FF | 0x00000000 ~ 0x1FFFFFFF |
| 仲裁场长度 | 12位(含RTR) | 32位(含SRR、IDE、RTR) |
| 总线利用率 | 较高(帧短) | 稍低(帧长) |
| 适用场景 | 节点少、实时性高 | 节点多、需复杂过滤 |
1.2 数据帧结构:从SOF到EOF,一个都不能少
一个完整的数据帧,由7个场组成。我习惯把它想象成一封信:有信封、有内容、有签名、有回执。
帧结构总览:
| SOF | 仲裁场 | 控制场 | 数据场 | CRC场 | ACK场 | EOF |
| 1位 | 12/32位 | 6位 | 0~64位 | 16位 | 2位 | 7位 |
1.3 逐个拆解:每个场都在干什么?
1. SOF(帧起始)
就1位,显性电平(逻辑0)。说白了就是喊一嗓子:「大家注意,我要发数据了!」
嗯,这里要注意:SOF是同步信号。总线上所有节点看到这个下降沿,都会重新同步自己的时钟。我曾经遇到过一个案子,某个节点的晶振偏差太大,SOF检测老是出错,导致整个网络丢帧。最后换了晶振才解决。
2. 仲裁场
这是CAN协议最精彩的部分。标准帧的仲裁场包含11位ID + 1位RTR;扩展帧则包含29位ID + SRR + IDE + RTR。
为什么会设计成这样?因为CAN总线没有主从之分,谁想发就发。那冲突了怎么办?靠仲裁!
仲裁规则:显性位(0)赢隐性位(1)。ID越小,优先级越高。
3. 控制场
6位:IDE(1位)+ r0(1位)+ DLC(4位)。
IDE用来区分标准帧(0)和扩展帧(1)。DLC表示数据场有多少个字节,范围0~8。
我见过有人把DLC设成8但只用了2个字节,剩下的全填0。嗯,浪费带宽。你想想看,CAN总线速率也就500kbps,能省则省。
4. 数据场
0~8字节,这就是真正要传的信息。比如发动机转速、车速、水温,都塞在这里。
数据排列:Motorola格式(大端)和Intel格式(小端)。
// 示例:车速信号,0x1234,Motorola格式
Byte0 = 0x12 // 高字节在前
Byte1 = 0x34 // 低字节在后
// Intel格式则相反
Byte0 = 0x34 // 低字节在前
Byte1 = 0x12 // 高字节在后
5. CRC场
15位CRC + 1位CRC分隔符。用来校验数据有没有传错。
CRC算法是固定的,多项式是x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1。你不用背,芯片会算。但你要知道,CRC覆盖的范围是从SOF到数据场结束。如果CRC校验失败,接收节点会丢弃这帧数据。
6. ACK场
2位:ACK槽 + ACK分隔符。
发送节点发完数据后,会释放总线。接收节点如果正确收到,就在ACK槽里拉一个显性位。发送节点检测到这个显性位,就知道「嗯,有人收到了」。
如果没人应答呢?发送节点会重发。我调试时经常用示波器看ACK位,如果一直没看到显性位,那肯定是总线哪里断了。
7. EOF(帧结束)
7位隐性位。表示这帧数据结束了,大家该干嘛干嘛。
1.4 完整数据帧示例
咱们看一个实际抓包的数据帧:
ID: 0x123 (标准帧)
DLC: 3
数据: 0x41 0x52 0x63
二进制展开:
SOF: 0
仲裁场: 001 0010 0011 0 (ID=0x123, RTR=0)
控制场: 0 0 0011 (IDE=0, r0=0, DLC=3)
数据场: 0100 0001 0101 0010 0110 0011
CRC场: [15位CRC] 1
ACK场: 0 1
EOF: 1111111
你看,实际传输的就是这么一串0和1。CAN控制器会帮你打包解包,但作为工程师,你必须知道每一位的含义。否则出了问题,你连从哪里下手都不知道。
1.5 小结
这一章我们聊了标准帧和扩展帧的区别,也拆解了数据帧的7个场。我个人觉得,理解CAN数据帧的关键在于:把它当成一个通信协议来读,而不是一堆二进制位。
下一章,咱们聊聊远程帧和错误帧。嗯,那又是另一番天地了。