第3章 CAN总线仲裁机制:CSMA/CA原理、显性位与隐性位仲裁、优先级判定规则、实际波形分析

各位工程师朋友,咱们今天聊一个硬核话题——CAN总线的仲裁机制。

说实话,我刚入行那会儿,总觉得仲裁这事儿挺玄乎的。多个节点同时发数据,总线怎么知道听谁的?后来亲手抓了几次波形,才真正搞明白。嗯,今天我就把这点干货掰开了讲给你听。

3.1 CSMA/CA原理:先听后说,边说边听

CAN总线用的不是CSMA/CD(碰撞检测),而是CSMA/CA(碰撞避免)。

你想想看,如果两个节点同时发数据,总线直接短路了怎么办?CAN的解决办法很聪明——先监听,再发送,发送过程中继续监听

具体流程是这样的:

  1. 监听总线:每个节点在发送前,先看看总线是不是空闲的。
  2. 检测到空闲:如果总线连续11个隐性位(这是帧间隔),说明没人用,可以发。
  3. 边发边听:发送的同时,节点还在读总线上的电平。
  4. 发现冲突:如果读到的电平和自己发的不一致,说明有更高优先级的节点也在发。
  5. 主动退让:低优先级节点立刻停止发送,转为接收模式。

核心要点:CAN的仲裁是“无损”的。高优先级节点不受任何影响,低优先级节点自动退让,总线利用率极高。

我在项目中遇到过一个问题:有个同事把CAN节点的采样点设得太靠后,结果仲裁位没来得及判断,导致低优先级节点反复重发。后来我把采样点调到75%位置,问题就解决了。嗯,细节决定成败。

3.2 显性位与隐性位:总线上的“0”和“1”

CAN总线只有两根线——CAN_H和CAN_L。但这两根线能表达三种状态:显性、隐性、空闲。

说白了,这就是个“线与”逻辑:

  • 显性位(Dominant):CAN_H拉高到3.5V,CAN_L拉低到1.5V,差分电压约2V。逻辑上代表“0”。
  • 隐性位(Recessive):CAN_H和CAN_L都维持在2.5V,差分电压约0V。逻辑上代表“1”。
  • 仲裁规则:显性位“覆盖”隐性位。只要有一个节点发显性,总线就是显性。

为什么会这样?因为CAN收发器的输出级是开漏结构。显性位是主动驱动,隐性位是靠上拉电阻维持的。你想想看,主动拉低肯定比被动上拉“力气大”。

状态 CAN_H电压 CAN_L电压 差分电压 逻辑值 优先级
显性 3.5V 1.5V ~2V 0
隐性 2.5V 2.5V ~0V 1
空闲 2.5V 2.5V ~0V (无)

个人习惯:我调试时喜欢用差分探头看CAN_H和CAN_L的差值。只看单端信号容易误判,尤其是地线有噪声的时候。

3.3 优先级判定规则:谁ID小谁先走

CAN的仲裁字段就是标识符(ID)。规则简单粗暴:ID越小,优先级越高

为什么?因为ID是从高位到低位逐位仲裁的。显性位(0)赢隐性位(1)。所以ID的二进制值越小,前面“0”就越多,赢面就越大。

举个例子:

  • 节点A:ID = 0x100(二进制:001 0000 0000)
  • 节点B:ID = 0x200(二进制:010 0000 0000)

仲裁过程:

  1. 第1位:A发0(显性),B发0(显性)→ 总线显性,平局。
  2. 第2位:A发0(显性),B发1(隐性)→ 总线显性,A赢,B退让。

你看,A的ID小,赢了。B乖乖闭嘴,等下一轮。

我曾经踩过的坑:在设计网络时,把ECU的ID设成了0x000。结果这个节点永远抢不到总线——因为ID全0意味着它一直在仲裁中“赢”,但RTR位(远程帧请求位)如果也是0,就会和标准帧冲突。后来我规定ID最低从0x001开始,留出0x000做特殊用途。

3.4 实际波形分析:用示波器看仲裁

光说理论不过瘾,咱们看看真实波形。我拿一个实际案例来讲。

场景:两个节点同时发送数据帧。

  • 节点1:ID = 0x123(标准帧)
  • 节点2:ID = 0x124(标准帧)

抓到的波形长这样(我用文字描述一下):

SOF  ID10 ID9 ID8 ID7 ID6 ID5 ID4 ID3 ID2 ID1 ID0 RTR
 0    0   0   1   0   0   1   0   0   0   1   1   0   (节点1)
 0    0   0   1   0   0   1   0   0   0   1   0   0   (节点2)

注意看ID1位(倒数第2位):

  • 节点1发的是1(隐性)
  • 节点2发的是0(显性)
  • 总线结果是0(显性)

节点1发现自己发的1和总线上的0不一致,立刻停止发送。节点2继续完成后续数据。

从波形上看,你会看到:

  • SOF之后,波形一直重叠,直到ID1位出现“分叉”
  • 分叉点之后,节点1的波形变成隐性(高阻态),节点2的波形继续
  • 整个过程中,总线电平没有“毛刺”或“异常跳变”

关键观察点:仲裁失败的节点,其波形会在仲裁位之后“消失”。但总线波形是连续的,没有中断。这就是“无损仲裁”的物理表现。

我记得有一次帮客户排查问题,发现总线波形在仲裁位之后出现了一个“毛刺”。后来查出来是收发器的上拉电阻值不匹配,导致隐性电平恢复太慢。嗯,这种问题用眼图分析一下就清楚了。

3.5 避坑指南:仲裁相关的常见问题

做CAN项目这么多年,我总结了几条仲裁相关的坑:

  • ID分配不合理:把高优先级ID给了低频报文,低优先级ID给了高频报文。结果高优先级报文把总线占满了,低优先级的一直发不出去。
  • 采样点设置不当:仲裁位发生在帧起始阶段,如果采样点太靠前或太靠后,可能误判仲裁结果。我一般设在75%~80%位置。
  • 总线长度过长:CAN总线的传播延迟会影响仲裁。总线越长,仲裁位需要的时间越长。超过1km时,建议用CAN FD或者降低波特率。
  • 终端电阻不匹配:电阻值不对,会导致隐性电平不稳定,仲裁时误判。标准是120Ω,两端各一个。

我的调试习惯:遇到仲裁问题,先抓波形看ID字段。如果波形在ID位有“抖动”,大概率是采样点或终端电阻的问题。如果波形干净但节点就是发不出去,查查ID优先级是不是太低了。

好了,关于CAN总线仲裁机制,今天就聊到这儿。下一章咱们讲CAN的帧结构——数据帧、远程帧、错误帧、过载帧,每个帧的格式和用途我都会结合实际案例来讲。到时候见。