3、CAN协议基础:CAN远程帧、错误帧、过载帧、帧间隔
好,咱们继续往下聊。前面我们把CAN的数据帧和遥控帧(也就是远程帧)的基本结构讲清楚了。但说实话,一个总线要稳定运行,光靠数据帧和远程帧是远远不够的。你想想看,万一总线上出了错怎么办?某个节点发疯了怎么办?
嗯,这就是我们今天要聊的——错误帧、过载帧和帧间隔。这三兄弟,说白了就是CAN总线的“交警”和“清道夫”。
3.1 远程帧:我只要数据,你别发给我
远程帧,也叫遥控帧。它的作用很简单:一个节点向另一个节点请求数据。
我记得刚入行那会儿,有个老工程师跟我说:“远程帧就是‘我要,你别给’。” 我当时一愣,后来才明白——远程帧本身不携带数据场,它只是告诉目标节点:“嘿,把你那个ID为0x123的数据发给我。”
远程帧的结构和数据帧几乎一样,区别只有两点:
- RTR位为隐性(1):表示这是一个远程帧请求
- 没有数据场:DLC虽然存在,但表示请求的数据长度,而不是实际发送的数据
重要: 远程帧的仲裁场和数据帧完全一样。如果总线上同时出现一个数据帧和一个远程帧,且ID相同,那么数据帧会赢得仲裁(因为RTR=0,显性优先)。
我在项目中遇到过一个问题:某个传感器节点一直发远程帧,但目标节点没响应。查了半天,发现是DLC写错了。目标节点认为请求的是8字节,但实际只准备了2字节的数据,结果一直没发出来。嗯,这种坑,踩过一次就记住了。
3.2 错误帧:总线的“紧急刹车”
错误帧,是CAN总线最核心的容错机制。没有它,CAN就不叫CAN了。
错误帧的长度是6个显性位 + 8个隐性位,总共14位。结构很简单:
- 错误标志(Error Flag):6个连续的显性位
- 错误界定符(Error Delimiter):8个连续的隐性位
为什么会这样?因为一旦某个节点检测到错误,它会立刻拉低总线,发送6个显性位。其他节点收到这个“异常信号”后,也会跟着发送错误标志。这样一来,总线上就会出现6~12个显性位(取决于节点间的同步情况)。
注意: 错误帧的发送时机非常关键。节点只能在检测到错误的下一个位时间开始发送错误帧。如果错过了这个窗口,错误帧就会变成过载帧——嗯,这是另一个故事了。
我曾经调试过一个ECU,它在高温下频繁报错。用CAN分析仪一看,错误帧满天飞。后来发现是晶振漂移了,导致位时序不对。你想想看,一个节点在错误的状态下不断重发错误帧,整个总线都被它拖垮了。这就是所谓的“总线关闭”状态。
3.3 过载帧:我忙,别打扰我
过载帧,说白了就是节点在说:“我处理不过来了,你等会儿。”
过载帧的结构和错误帧几乎一样:
- 过载标志(Overload Flag):6个显性位
- 过载界定符(Overload Delimiter):8个隐性位
但触发条件完全不同。过载帧只在两种情况下产生:
- 接收节点内部条件未准备好:比如CPU太忙,缓冲区满了
- 帧间隔的间歇场检测到显性位:这属于总线异常,但节点用“过载”来响应
我个人习惯把过载帧看作是“礼貌的拒绝”。它不像错误帧那样是“出事了”,而是“我暂时不行”。
小技巧: 如果你的系统频繁出现过载帧,别急着怀疑硬件。先看看接收节点的中断优先级和DMA配置。很多时候,是软件没来得及把数据从CAN控制器读走。
3.4 帧间隔:总线的“呼吸节奏”
帧间隔,是CAN总线上两个帧之间的“休息时间”。它保证了总线上的节点有足够的时间同步和准备。
帧间隔由三部分组成:
| 字段 | 长度 | 说明 |
|---|---|---|
| 间歇场(Intermission) | 3个隐性位 | 所有节点必须等待这3位才能开始下一帧 |
| 总线空闲(Bus Idle) | 任意长度 | 总线处于隐性状态,节点可以开始发送 |
| 暂停发送(Suspend Transmission) | 8个隐性位 | 仅错误被动节点需要等待 |
这里有个细节:间歇场的3个隐性位,是强制性的。任何节点都不能在这3位期间发送数据。如果某个节点在间歇场检测到显性位,它会认为这是一个过载帧的开始,然后发送过载标志。
我记得有一次,一个同事问我:“为什么我的CAN总线在高速运行时,偶尔会丢帧?” 我让他抓波形一看,发现帧间隔被压缩了——某个节点在间歇场就开始发送数据。嗯,这其实是违反了CAN协议的。后来发现是那个节点的晶振精度不够,导致位时间计算有偏差。
3.5 四种帧的对比总结
好了,我们把CAN的四种帧类型放在一起对比一下:
| 帧类型 | 用途 | 数据场 | 触发条件 |
|---|---|---|---|
| 数据帧 | 发送数据 | 有(0~8字节) | 节点主动发送 |
| 远程帧 | 请求数据 | 无 | 节点主动发送 |
| 错误帧 | 报告错误 | 无 | 任何节点检测到错误 |
| 过载帧 | 请求延迟 | 无 | 接收节点忙或间歇场异常 |
你可能会问:“为什么远程帧和过载帧用得少?” 嗯,说实话,在大多数汽车应用中,远程帧确实用得不多。大家更习惯用数据帧来主动上报。而过载帧,只有在系统设计不合理时才会频繁出现。
但作为工程师,你必须理解它们。因为当你遇到总线异常时,能看懂错误帧和过载帧,就等于拿到了诊断的“钥匙”。
核心要点:
- 远程帧:RTR=1,无数据场,用于请求数据
- 错误帧:6显性+8隐性,由错误检测触发
- 过载帧:6显性+8隐性,由接收忙或间歇场异常触发
- 帧间隔:3隐性间歇场 + 总线空闲 + 8隐性暂停(仅错误被动节点)
下一章,我们会深入CAN的位时序和同步机制。嗯,那才是真正考验硬件功底的地方。到时候我会分享一个我当年调CAN波特率的血泪史——保证让你印象深刻。