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 过载帧——总线的“慢一点”信号
过载帧跟错误帧结构一样,但触发条件不同。它表示“我忙不过来了,等一下”。
触发条件有两个:
- 接收节点还没准备好接收下一帧(比如内部缓冲区满了)。
- 帧间隔的间歇场检测到显性位(这属于异常情况)。
过载帧在实际项目中很少见。如果频繁出现,说明你的节点处理速度跟不上总线速率。我建议先检查中断优先级和DMA配置,别急着换硬件。
2.5 帧间隔——帧与帧之间的“呼吸”
帧间隔不是一帧,而是帧与帧之间的空闲时间。它由三部分组成:
- 间歇场:3位隐性。所有节点必须在这3位内保持隐性,否则视为过载。
- 总线空闲:任意长度隐性位。节点可以在这期间开始发送。
- 暂停发送场:仅错误被动节点有,8位隐性。让错误被动节点多等一会儿,别抢总线。
你想想看,如果没有帧间隔,总线上的帧会连在一起,接收节点根本分不清哪帧是哪帧。所以帧间隔是必须的。
2.6 五种帧的关系图
下面这张图展示了五种帧在总线上的出现顺序和关系:
2.7 位填充规则——保证时钟同步
CAN总线有个特殊规则:连续5个相同电平后,必须插入一个相反电平。这叫位填充。
为什么?因为CAN节点靠电平跳变来同步时钟。如果长时间没有跳变,时钟就会漂移。位填充保证了最多5位就有一个跳变。
填充位在接收端会被自动移除,所以软件层看不到。但错误帧和过载帧的6位错误标志不遵守位填充规则——这是故意的,用来破坏当前帧。
小技巧:用示波器看CAN波形时,数一下连续相同电平的位数。如果超过5位还没跳变,说明位填充逻辑有问题。我遇到过国产CAN控制器在这块有bug,换了芯片就好了。
2.8 帧优先级与仲裁
多个节点同时发送时,谁赢?看ID。ID越小,优先级越高。仲裁发生在SOF之后的ID位,逐位比较。
标准帧和扩展帧同时发送时,标准帧赢。因为扩展帧的SRR位是隐性,标准帧的RTR位是显性。所以扩展帧在仲裁上吃亏。
我个人建议:关键控制信号用标准帧,大数据传输用扩展帧。这样关键信号永远优先。
| 帧类型 | 优先级 | 典型用途 |
|---|---|---|
| 标准数据帧 | 最高 | 控制指令、紧急信号 |
| 扩展数据帧 | 中等 | 诊断、大数据传输 |
| 标准远程帧 | 较低 | 请求数据 |
| 扩展远程帧 | 最低 | 请求大数据 |
好了,五种帧的结构和用法就这些。记住:数据帧装数据,远程帧要数据,错误帧报故障,过载帧喊慢点,帧间隔做分隔。把这五个角色搞清楚,CAN协议你就入门了。