2. CAN报文帧结构:标准帧与扩展帧、数据帧、远程帧、错误帧、过载帧、帧间隔
好,咱们今天来啃一块硬骨头——CAN报文的帧结构。说实话,我刚入行那会儿,看到这些帧类型也是一头雾水。什么标准帧、扩展帧,数据帧、远程帧……感觉像在看天书。但后来在项目里被坑过几次,才真正搞明白这些东西有多重要。
你想想看,CAN总线上跑的就是这些帧。不理解它们,你连报文都读不懂。咱们一个一个来拆解。
2.1 标准帧 vs 扩展帧
先说最基础的区别——ID长度。标准帧的ID是11位,扩展帧是29位。为什么要有两种?说白了,早期CAN总线节点少,11位ID够用。后来车上的ECU越来越多,11位不够分了,就搞了个29位的扩展帧。
关键区别:
- 标准帧:11位标识符,最多2032个不同ID
- 扩展帧:29位标识符,最多5.3亿个不同ID
- IDE位(Identifier Extension)决定是标准还是扩展
我在项目中遇到过一件事:有个同事把标准帧和扩展帧混着用,结果接收节点死活收不到数据。查了半天,原来是接收滤波器配置只认标准帧,而发送端发的是扩展帧。嗯,这种坑踩过一次就记住了。
2.2 数据帧
数据帧,这是咱们用得最多的。它负责把数据从发送节点传到接收节点。结构上分7个段:
| 段名称 | 说明 | 我的一点经验 |
|---|---|---|
| 帧起始 | 1位显性位,同步用 | 别小看这一位,总线空闲时全靠它 |
| 仲裁段 | ID + RTR位 | ID越小优先级越高,这是CAN的精华 |
| 控制段 | IDE + DLC | DLC告诉你有几个字节数据 |
| 数据段 | 0-8字节数据 | 最多8字节,别想塞更多 |
| CRC段 | 15位校验 + 1位界定符 | 校验出错?节点会自动重发 |
| ACK段 | 2位:应答间隙 + 界定符 | 接收节点拉低应答位,告诉发送方"我收到了" |
| 帧结束 | 7位隐性位 | 表示帧结束了 |
小技巧:抓包时看到DLC=0的数据帧别慌,那是合法的。有些节点就用空数据帧来当心跳包用。
2.3 远程帧
远程帧,说白了就是"请求帧"。一个节点发远程帧,意思是"谁有某某ID的数据?发给我"。它没有数据段,DLC表示它期望接收的数据长度。
我记得有一次调试一个电机控制器,发现它老是发远程帧请求某个传感器的数据。但传感器节点没响应。查了半天,原来是传感器节点的接收滤波器没配好,压根没认出这个远程帧。后来我把滤波器改了一下,问题就解决了。
注意:远程帧的RTR位是隐性(1),而数据帧的RTR位是显性(0)。抓包时看到RTR=1,那就是远程帧。
2.4 错误帧
错误帧,这是CAN总线的"警察"。一旦有节点检测到错误,就会发错误帧通知大家。错误帧由两部分组成:
- 错误标志:6个连续相同位(显性或隐性)
- 错误界定符:8个隐性位
错误类型有几种:位错误、填充错误、CRC错误、格式错误、应答错误。我见过最典型的是位错误——某个节点发送显性位,但总线上读到的是隐性位,说明总线被其他节点抢占了或者短路了。
我曾经在实验室里用示波器抓过错误帧。那波形看着就乱,一堆显性位挤在一起。后来发现是终端电阻没接好,信号反射导致位错误。嗯,这种问题排查起来确实费劲。
2.5 过载帧
过载帧,相当于"我忙,等会儿再说"。当接收节点来不及处理数据时,就发过载帧让发送方等一等。它的结构和错误帧很像:
- 过载标志:6个显性位
- 过载界定符:8个隐性位
为什么会有过载?你想想看,如果总线上数据量太大,接收节点的缓冲区满了,它就得发过载帧。我在一个多节点项目中就遇到过这种情况——某个节点处理速度慢,总线上数据一多它就发过载帧,搞得整个网络效率下降。后来给它换了个性能更强的MCU才解决。
2.6 帧间隔
帧间隔,就是两帧之间的"休息时间"。CAN总线规定,每发完一帧,必须等3个隐性位才能发下一帧。这3个位叫"间歇场"。之后总线进入"总线空闲"状态,直到有节点开始发下一帧。
为什么要这样?说白了,给节点一点时间处理刚收到的数据,也防止总线冲突。我见过有人为了追求高吞吐量,把帧间隔缩短,结果总线乱成一锅粥。嗯,别这么干,规矩就是规矩。
总结一下:
- 数据帧:传数据用的,最常见
- 远程帧:请求数据用的,没有数据段
- 错误帧:出错了,大家注意
- 过载帧:我忙不过来,等会儿
- 帧间隔:两帧之间的休息时间
好了,帧结构这块就讲这么多。你把这些搞清楚了,抓包解析的时候就能一眼看出报文类型。下一章咱们聊聊CAN的位时序和同步,那个更烧脑,但搞懂了就能自己算波特率了。