2. CAN总线帧结构:数据帧、远程帧、错误帧、过载帧、帧间隔的详细结构与作用

CAN总线上跑的数据,说白了就五种“信封”。每种信封长什么样、干什么用、什么时候发,是每个CAN工程师必须烂熟于心的基本功。我当年刚入行时,就是靠死磕这五种帧结构,才把CAN总线的底层逻辑彻底吃透。

咱们一个一个来拆。

2.1 数据帧——最常用的“快递包裹”

数据帧负责把数据从发送节点送到接收节点。它有两种格式:标准帧(11位ID)和扩展帧(29位ID)。结构上,数据帧由7个段组成:

段名称 标准帧位数 扩展帧位数 作用
帧起始(SOF) 1 1 同步所有节点,标志总线从空闲变为忙碌
仲裁段 12 32 包含ID和RTR位,决定谁有发送权
控制段 6 6 标识数据长度(DLC)和扩展格式标志
数据段 0~64 0~64 真正的有效载荷,最多8字节
CRC段 16 16 15位CRC校验 + 1位CRC界定符
ACK段 2 2 接收节点回应,确认收到无误
帧结束(EOF) 7 7 标志帧结束,释放总线

关键点:数据帧的仲裁段里有个RTR位(远程发送请求位),数据帧的RTR=0。这个位在仲裁时非常关键——我后面讲远程帧时会对比。

我在项目中遇到过一个问题:两个节点同时发数据帧,ID小的那个赢了仲裁,但ID大的那个节点因为没收到ACK,会一直重发。嗯,这就是仲裁机制带来的“隐性重发”,设计时一定要考虑好ID的优先级分配。

2.2 远程帧——只问不拿的“查询单”

远程帧的结构和数据帧几乎一样,唯一的区别是:数据段为空,且RTR位=1。

远程帧的作用是什么?说白了就是“请求数据”。节点A发一个远程帧,告诉节点B:“把你那个ID的数据发给我。”节点B收到后,就会发一个同ID的数据帧回来。

避坑指南:我曾经在调试一个电机控制器时,发现总线负载率莫名其妙很高。查了半天,原来是某个传感器节点一直在发远程帧请求数据,而数据节点响应太慢,导致远程帧反复重发。后来我把远程帧的发送间隔调大,问题就解决了。远程帧不是免费的,别滥用。

数据帧和远程帧的仲裁对比:

对比项 数据帧 远程帧
RTR位 0(显性) 1(隐性)
数据段 有数据(0~8字节) 无数据
仲裁优先级 更高(RTR=0更优先) 更低(RTR=1)
典型用途 发送传感器值、控制指令 请求其他节点发送数据

你想想看,如果数据帧和远程帧的ID相同,数据帧一定会赢得仲裁。因为RTR=0比RTR=1更“显性”。这个细节在总线竞争激烈时特别重要。

2.3 错误帧——总线的“警报器”

错误帧是CAN总线自我纠错的核心机制。任何节点检测到错误,都会立即发送错误帧,通知所有节点:“刚才那帧有问题,别用了!”

错误帧由两部分组成:

  • 错误标志(Error Flag):6个连续的显性位(主动错误节点)或6个连续的隐性位(被动错误节点)
  • 错误界定符(Error Delimiter):8个连续的隐性位

注意:错误帧的发送时机非常关键。节点检测到错误后,必须在下一个位时间就开始发送错误标志。如果多个节点同时检测到错误,它们会同时发送错误标志,导致总线上出现6~12个显性位——这叫“错误叠加”,是CAN协议允许的。

错误帧的触发条件有五种:

  1. 位错误:发送节点监控总线,发现发送的位和总线上的位不一致
  2. 填充错误:连续5个相同位后,没有插入填充位
  3. CRC错误:接收节点计算的CRC和发送节点的不一致
  4. 形式错误:固定格式的位段(如EOF、界定符)出现错误电平
  5. ACK错误:发送节点没有收到ACK显性回应

我个人习惯在调试时,用CAN分析仪抓一下错误帧的类型。如果看到大量CRC错误,多半是总线干扰大;如果看到位错误,可能是节点时钟偏差太大。这些经验,都是被项目逼出来的。

2.4 过载帧——总线的“慢点,我还没准备好”

过载帧的作用很简单:当一个节点忙不过来时,它发一个过载帧,让其他节点等一等。

过载帧的结构和错误帧很像:

  • 过载标志:6个显性位
  • 过载界定符:8个隐性位

触发过载帧的条件有两个:

  • 接收节点内部条件未准备好(比如缓冲区满了)
  • 在帧间隔的间歇场检测到显性位(这属于异常情况)

实战经验:我曾经在一个多节点系统中,发现某个节点频繁发送过载帧。一开始以为是硬件问题,后来用示波器一量,发现那个节点的MCU主频偏低,导致CAN控制器来不及处理接收到的数据。换了个晶振就好了。过载帧是“求救信号”,别忽视它。

2.5 帧间隔——总线的“休息时间”

帧间隔不是一帧,而是两帧之间的空闲时段。它让总线有时间恢复,也让节点有时间处理上一帧的数据。

帧间隔由两部分组成:

  • 间歇场(Intermission):3个隐性位
  • 总线空闲(Bus Idle):任意长度的隐性位,直到有节点开始发送

对于被动错误节点,帧间隔还会多一个暂停发送场(Suspend Transmission):8个隐性位。这是对被动错误节点的“惩罚”——让它多等一会儿,减少对总线的干扰。

你想想看,如果没有帧间隔,总线上的帧会一个接一个地紧挨着发。接收节点根本没时间处理数据,缓冲区很快就满了。帧间隔就是给节点喘口气的机会。

2.6 五种帧的关系——一张SVG图说清楚

下面这张图展示了五种帧在总线上的出现顺序和关系。我建议你把它存下来,面试时绝对用得上。

CAN总线五种帧结构关系图 总线空闲(帧间隔) 数据帧(Data Frame)—— 最常用,携带数据 错误帧 过载帧 帧间隔 远程帧(Remote Frame)—— 请求数据 说明: • 正常通信流程:帧间隔 → 数据帧/远程帧 → 帧间隔 • 异常时:任何帧都可能被错误帧中断 • 过载帧只在接收节点忙时插入,不影响帧结构完整性

2.7 实战中的帧结构调试技巧

说了这么多理论,来点实际的。我调试CAN总线时,最常用的三板斧:

  1. 看SOF和EOF:用示波器抓波形,先找到帧起始的下降沿和帧结束的7个隐性位。如果EOF不完整,说明帧被错误帧打断了。
  2. 数填充位:连续5个相同位后,必须有一个填充位。如果发现连续6个相同位,那就是填充错误,节点会发错误帧。
  3. 查ACK:发送节点在ACK槽位会释放总线(隐性),接收节点必须拉成显性。如果ACK槽一直是隐性,说明没有节点收到这帧——要么ID不匹配,要么节点离线了。

核心总结:数据帧是主力,远程帧是辅助,错误帧是保镖,过载帧是缓冲,帧间隔是呼吸。把这五种帧吃透了,CAN总线对你来说就没有秘密了。