2. CAN帧结构详解:数据帧、远程帧、错误帧、过载帧、帧间隔

CAN总线上跑的数据,说白了就五种“信封”。每种信封的用途、格式、优先级都不一样。我刚接触CAN时,总觉得帧结构很复杂,后来发现只要抓住几个关键字段,一通百通。

这五种帧分别是:数据帧、远程帧、错误帧、过载帧和帧间隔。咱们一个一个拆开看。

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

数据帧就是用来装数据的。一个节点发,其他节点收。标准格式11位ID,扩展格式29位ID。我个人习惯用标准格式,除非ID不够用。

数据帧结构(标准格式):

SOF + 11位ID + RTR + IDE + r0 + DLC + 数据段(0~8字节) + CRC + ACK + EOF

关键字段说明:

  • SOF(Start of Frame):1位显性,告诉总线“我要发数据了”。
  • ID:11位(标准)或29位(扩展)。ID越小,优先级越高。我遇到过有人把ID设成0x7FF,结果抢不到总线,急得直跺脚。
  • RTR(Remote Transmission Request):数据帧里RTR=0(显性),远程帧里RTR=1(隐性)。
  • DLC(Data Length Code):4位,表示数据字节数(0~8)。注意,DLC可以写0,但数据段就不存在了。
  • 数据段:0~8字节,真正要传的内容。
  • CRC:15位校验 + 1位定界符。校验范围从SOF到数据段结束。
  • ACK:2位。发送方发隐性,接收方如果正确收到,就拉成显性。这就是“应答”机制。
  • EOF(End of Frame):7位隐性,表示帧结束。

我的经验:调试时如果发现ACK总是不对,先查接收节点的验收滤波。我曾经花了两天查硬件,最后发现是滤波配置错了,数据帧根本进不了接收缓冲区。

2.2 远程帧——“请求数据”的指令

远程帧长得跟数据帧很像,但RTR位是隐性(1)。它不携带数据段,DLC写的是请求的数据长度。

举个例子:节点A发一个远程帧,ID=0x123,DLC=4。节点B收到后,就知道A想要ID=0x123的4字节数据。于是B发一个数据帧,ID=0x123,数据段里放4字节内容。

注意:远程帧的DLC必须跟对应数据帧的DLC一致。我曾经见过有人远程帧DLC写8,但数据帧只发2字节,结果接收方直接报错。

远程帧在实际项目中用得不多。我个人更推荐用数据帧主动上报,而不是靠远程帧去“拉”。因为远程帧的响应时机不可控,容易造成总线拥堵。

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

错误帧是节点发现自己或别人出错时主动发的。它由两部分组成:

  • 错误标志:6位相同电平(显性或隐性,取决于错误类型)。
  • 错误定界符:8位隐性。

错误类型有五种:

错误类型 检测位置 说明
位错误 发送节点 发送的电平跟总线电平不一致(仲裁阶段除外)
填充错误 所有节点 连续6个相同电平,违反位填充规则
CRC错误 接收节点 计算出的CRC跟收到的CRC不一致
格式错误 所有节点 固定格式位(如CRC定界符、EOF)电平不对
ACK错误 发送节点 发送节点没收到显性ACK

嗯,这里要注意:错误帧一旦发出,当前传输的帧就作废了。所有节点都会丢弃这个帧,然后重新仲裁。我调试时经常用示波器抓错误帧,一看波形就知道是哪类错误。

避坑指南:我曾经遇到过总线频繁出现错误帧,查了半天发现是终端电阻没焊。两个120Ω电阻缺一个,信号反射严重,CRC错误率飙升。

2.4 过载帧——总线的“慢一点”信号

过载帧跟错误帧结构一样,但触发条件不同。它表示“我忙不过来了,等一下”。

触发条件有两个:

  1. 接收节点还没准备好接收下一帧(比如内部缓冲区满了)。
  2. 帧间隔的间歇场检测到显性位(这属于异常情况)。

过载帧在实际项目中很少见。如果频繁出现,说明你的节点处理速度跟不上总线速率。我建议先检查中断优先级和DMA配置,别急着换硬件。

2.5 帧间隔——帧与帧之间的“呼吸”

帧间隔不是一帧,而是帧与帧之间的空闲时间。它由三部分组成:

  • 间歇场:3位隐性。所有节点必须在这3位内保持隐性,否则视为过载。
  • 总线空闲:任意长度隐性位。节点可以在这期间开始发送。
  • 暂停发送场:仅错误被动节点有,8位隐性。让错误被动节点多等一会儿,别抢总线。

你想想看,如果没有帧间隔,总线上的帧会连在一起,接收节点根本分不清哪帧是哪帧。所以帧间隔是必须的。

2.6 五种帧的关系图

下面这张图展示了五种帧在总线上的出现顺序和关系:

CAN五种帧关系图 CAN五种帧关系图 数据帧 远程帧 错误帧 过载帧 帧间隔 说明:数据帧和远程帧是正常通信帧,错误帧和过载帧是异常处理帧,帧间隔是帧与帧之间的分隔 所有帧结束后都必须跟一个帧间隔,才能开始下一帧

2.7 位填充规则——保证时钟同步

CAN总线有个特殊规则:连续5个相同电平后,必须插入一个相反电平。这叫位填充。

为什么?因为CAN节点靠电平跳变来同步时钟。如果长时间没有跳变,时钟就会漂移。位填充保证了最多5位就有一个跳变。

填充位在接收端会被自动移除,所以软件层看不到。但错误帧和过载帧的6位错误标志不遵守位填充规则——这是故意的,用来破坏当前帧。

小技巧:用示波器看CAN波形时,数一下连续相同电平的位数。如果超过5位还没跳变,说明位填充逻辑有问题。我遇到过国产CAN控制器在这块有bug,换了芯片就好了。

2.8 帧优先级与仲裁

多个节点同时发送时,谁赢?看ID。ID越小,优先级越高。仲裁发生在SOF之后的ID位,逐位比较。

标准帧和扩展帧同时发送时,标准帧赢。因为扩展帧的SRR位是隐性,标准帧的RTR位是显性。所以扩展帧在仲裁上吃亏。

我个人建议:关键控制信号用标准帧,大数据传输用扩展帧。这样关键信号永远优先。

帧类型 优先级 典型用途
标准数据帧 最高 控制指令、紧急信号
扩展数据帧 中等 诊断、大数据传输
标准远程帧 较低 请求数据
扩展远程帧 最低 请求大数据

好了,五种帧的结构和用法就这些。记住:数据帧装数据,远程帧要数据,错误帧报故障,过载帧喊慢点,帧间隔做分隔。把这五个角色搞清楚,CAN协议你就入门了。