2. CAN协议基础:CAN数据帧结构
好,咱们今天聊聊CAN数据帧的结构。说实话,这是整个CAN协议里最核心的内容。你想想看,一辆车上几十个ECU,它们之间怎么交流?就是靠这个数据帧。我在调试台架时,经常要对着逻辑分析仪一帧一帧地看数据,所以对这个结构特别熟悉。
一个标准的CAN数据帧,总共由7个场组成。我习惯把它们分成三部分来看:开头、中间和结尾。开头是SOF和仲裁场,中间是控制场和数据场,结尾是CRC场、ACK场和EOF。咱们一个一个说。
2.1 SOF(帧起始)
SOF就是一个显性位(逻辑0)。它告诉总线上所有节点:“我要开始说话了”。
为什么只有一个位?因为CAN总线是“线与”机制。显性位会覆盖隐性位。所以只要有一个节点拉低总线,其他节点就知道有数据来了。嗯,这里要注意:SOF必须是严格的显性位,不能有任何偏差。我在项目中遇到过,有个节点的晶振精度不够,SOF位置偏了,结果整个网络都乱套了。
关键点:SOF是同步的起点。所有节点都靠这个边沿来重新同步自己的时钟。
2.2 仲裁场
仲裁场包含两部分:11位标识符(标准帧)和RTR位。如果是扩展帧,那就是29位标识符。
这里有个很有意思的机制:总线仲裁。说白了,就是多个节点同时发数据时,谁优先级高谁先发。标识符越小,优先级越高。为什么?因为显性位(0)会覆盖隐性位(1)。
我举个例子:
节点A:ID = 0x7FF(二进制:111 1111 1111)
节点B:ID = 0x001(二进制:000 0000 0001)
同时发送时,从最高位开始比较。
节点A发1(隐性),节点B发0(显性)。
总线被拉低为0,节点A检测到总线与自己发送的不一致,立刻退出。
节点B继续发送,赢得仲裁。
RTR位呢?它区分数据帧和远程帧。数据帧的RTR是显性,远程帧是隐性。我在做诊断工具时,经常用远程帧来请求某个节点的数据,挺方便的。
个人经验:设计网络时,尽量把高优先级(小ID)分配给关键功能,比如刹车、转向。娱乐系统的ID可以大一些,反正优先级低点也没事。
2.3 控制场
控制场有6位:IDE位、保留位r0、DLC(数据长度码)4位。
IDE位用来区分标准帧和扩展帧。标准帧的IDE是显性,扩展帧是隐性。保留位r0目前固定为显性,留给以后用。
DLC表示数据场的字节数,范围是0到8。注意,DLC可以设置成0到8,但实际数据场长度必须匹配。我曾经见过一个新手,DLC设成8但只发了3个字节,结果接收方读到一堆垃圾数据。
| DLC值 | 数据长度(字节) |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
2.4 数据场
数据场就是实际要传输的数据,最多8个字节。为什么是8个?因为CAN最初是为汽车设计的,8个字节足够传递大部分控制信号了。比如发动机转速、车速、水温这些,每个信号2个字节,8个字节能装4个信号。
数据场的排列方式,我建议遵循Motorola格式(大端序)或者Intel格式(小端序)。这个在项目初期就要定好,不然不同ECU之间会解析错。我踩过这个坑:有一次两个团队用了不同的字节序,结果车速显示成了负数,排查了好久才发现是字节序的问题。
注意:数据场的内容完全由用户定义。CAN协议只负责传输,不关心里面是什么。所以发送方和接收方必须约定好数据格式,包括信号起始位、长度、缩放因子、偏移量等。
2.5 CRC场
CRC场包含15位CRC序列和1位CRC界定符(隐性)。
CRC的计算范围是从SOF到数据场结束。算法是CRC-15,多项式是x¹⁵ + x¹⁴ + x¹⁰ + x⁸ + x⁷ + x⁴ + x³ + 1。嗯,这个多项式不用背,芯片会自动算。但你要知道它的作用:检测传输错误。
我在做EMC测试时,遇到过总线受到干扰导致CRC错误的情况。CAN控制器会自动重发,但如果错误太多,节点会进入总线关闭状态。所以CRC不仅是检错,还关系到网络的可靠性。
2.6 ACK场
ACK场有2位:ACK槽和ACK界定符。
发送节点在ACK槽发送隐性位。接收节点如果正确收到数据,就在ACK槽发送显性位。这样发送节点就知道数据被至少一个节点收到了。
这里有个细节:ACK是“线与”的。只要有一个节点应答成功,总线就是显性。发送节点只关心有没有应答,不关心有几个节点应答。
重要:如果总线上只有一个节点,它自己发自己收,ACK会失败。因为发送节点自己不会应答自己。所以单节点网络需要特殊处理,比如开启自应答模式。
2.7 EOF(帧结束)
EOF是7个隐性位。它告诉总线:“这帧数据结束了”。
为什么是7个?因为CAN协议规定,连续6个相同位就表示错误。所以EOF用7个隐性位,既表示结束,又不会触发错误检测。设计得挺巧妙的,对吧?
EOF之后,总线会进入3位的ITM(帧间空间)。然后就可以开始下一帧了。
总结一下
一个完整的CAN数据帧,从SOF开始,到EOF结束,总共47到111位不等(取决于数据场长度)。我习惯用这个口诀来记:
SOF开始一个0
仲裁场里比高低
控制场里说长度
数据场里装内容
CRC场里查错误
ACK场里求应答
EOF结束七个1
嗯,这个口诀虽然不太押韵,但挺实用的。你在看逻辑分析仪波形时,可以对照着这个口诀来解析每一帧数据。
下一章咱们聊聊CAN的位时序和同步机制,那个更烧脑,但理解了之后,你对CAN的掌握就更深一层了。