3、CAN总线进阶:远程帧、错误帧、过载帧、帧间隔、位填充与仲裁
上一章我们把CAN总线的数据帧聊透了。但一辆车上跑着的CAN报文,远不止数据帧这一种。
你想想看,如果某个节点想主动要数据,怎么办?如果总线上出了错,谁来喊停?如果两个节点同时抢着发消息,谁先走?
这些场景,就引出了我们今天要啃的硬骨头——CAN总线的进阶机制。我个人觉得,这部分才是真正区分“会用”和“懂行”的分水岭。
3.1 远程帧:我要,你给
远程帧,说白了就是“请求帧”。一个节点可以发一个远程帧,告诉另一个节点:“嘿,把你那个ID为0x123的数据发给我。”
它的格式跟数据帧几乎一模一样,唯一的区别就是RTR位(远程传输请求位)。数据帧的RTR是显性(0),远程帧的RTR是隐性(1)。
| 对比项 | 数据帧 | 远程帧 |
|---|---|---|
| RTR位 | 显性(0) | 隐性(1) |
| 数据场 | 有(0~8字节) | 无 |
| 目的 | 发送数据 | 请求数据 |
3.2 错误帧:总线的“刹车灯”
CAN总线最牛的地方之一,就是它的错误检测机制。一旦某个节点发现错误,它会立刻发送一个错误帧,通知所有人:“刚才那帧有问题,别用了!”
错误帧由两部分组成:
- 错误标志: 6个连续的显性位(主动错误)或6个连续的隐性位(被动错误)。
- 错误界定符: 8个连续的隐性位,用来恢复总线。
这里有个关键点——错误标志的6个显性位,会破坏掉原本的位填充规则。其他节点检测到这个违规,也会跟着发错误标志。结果就是,错误标志被叠加,总线上会出现6~12个显性位。
3.3 过载帧:慢点,我跟不上
过载帧的作用很简单:接收方告诉发送方,“我还没处理完,你慢点发。”
它跟错误帧长得有点像,也是6个显性位+8个隐性位。但触发条件完全不同:
- 接收方内部缓冲区满了,需要延迟接收下一帧。
- 接收方在帧间隔期间检测到显性位(这属于异常情况)。
在实际测试中,过载帧出现的频率远低于错误帧。但如果你在测试中发现某个节点频繁发过载帧,那大概率是它的软件处理太慢,或者中断优先级设置有问题。
3.4 帧间隔:总线的“换气时间”
任何两个帧之间,都必须有一段空闲时间,这就是帧间隔。它让总线上的节点有机会同步,也让错误恢复有个缓冲。
帧间隔的长度是固定的:
- 间歇场: 3个隐性位。
- 总线空闲: 任意长度的隐性位(直到有节点开始发送)。
注意,如果是“被动错误”节点,在间歇场之后还要多发送8个隐性位的“挂起传输”场。这是对错误节点的一种惩罚机制——让它多等一会儿,别抢着发。
3.5 位填充机制:保证时钟同步
CAN总线没有单独的时钟线,所有节点靠“边沿”来同步时钟。但如果连续发送5个相同的位(比如00000),总线上就没有跳变沿了,节点之间的时钟就会漂移。
位填充机制就是为了解决这个问题:
- 发送方在连续发送5个相同位之后,自动插入一个相反极性的位。
- 接收方在收到5个相同位之后,自动把第6个位(填充位)去掉。
举个例子:你要发送 11111,实际总线上会变成 111110。接收方看到5个1之后,知道第6个0是填充位,直接丢弃。
3.6 CAN总线仲裁机制:谁先说话?
这是CAN总线最巧妙的设计之一。多个节点同时发送时,不会冲突,而是通过“线与”机制自动决出胜负。
规则很简单:ID越小,优先级越高。
具体过程是这样的:
- 所有节点同时发送SOF(显性位),同步开始。
- 接着发送ID位。每个节点在发送每一位时,都会监听总线电平。
- 如果自己发的是隐性(1),但总线上是显性(0),说明有更高优先级的节点在发,自己立刻退出。
- 退出的节点转为接收模式,不再干扰总线。
整个过程在几个微秒内完成,而且不会丢失任何数据。这就是CAN总线“非破坏性逐位仲裁”的厉害之处。
3.7 知识体系总览
下面这张图,把本章的核心知识点串起来了。你可以把它当作一个快速索引。
3.8 本章小结
远程帧、错误帧、过载帧、帧间隔、位填充、仲裁——这六个机制,构成了CAN总线进阶的核心。它们不是孤立的知识点,而是相互配合的:
- 仲裁决定了谁先发。
- 位填充保证了时钟同步。
- 错误帧和过载帧处理异常情况。
- 帧间隔让总线有序切换。
嗯,说实话,这些内容在入门阶段可能用不上。但当你开始做故障注入测试、分析总线负载、或者排查偶发性的通信中断时,这些知识就是你的武器库。没有它们,你连问题都描述不清楚。