3、CAN总线通信原理:多主竞争、显性隐性、位仲裁机制、位填充规则

说到CAN总线,很多朋友第一反应就是“它很可靠”。但可靠在哪?核心就在它那套独特的通信原理上。今天我就把这几个关键点拆开来讲。你看完就能明白,为什么CAN能在汽车、工业这种嘈杂环境里,还能稳稳当当传数据。

我个人习惯,每次讲原理都会先画个整体框架。咱们从最根本的总线电平开始。

核心一句话: CAN总线靠两根线(CAN_H和CAN_L)的差分电压来传信号。电压差大的叫“显性”,电压差小的叫“隐性”。这就是它抗干扰的底气。

3.1 多主竞争:谁都能抢,但得讲规矩

CAN总线上的节点,没有“老大”。任何一个节点,只要总线空闲,都能开始发数据。这就叫“多主”。

你想想看,要是两个节点同时发,不就打架了吗?嗯,确实会。但CAN不是硬碰硬,它有一套“软件握手”的协议。

我在做车身网关项目时,就遇到过两个ECU抢着发报文。一个报车速,一个报转向。结果总线上一团乱。后来我抓包一看,原来是仲裁机制没看懂。

3.2 显性隐性:0和1的物理含义

这个好理解。CAN总线上,电信号有两种状态:

  • 显性(Dominant): 逻辑0。此时CAN_H电压≈3.5V,CAN_L电压≈1.5V,差分电压约2V。
  • 隐性(Recessive): 逻辑1。此时两条线电压都≈2.5V,差分电压≈0V。

关键点来了:显性信号会“覆盖”隐性信号。说白了,只要有一个节点发0,总线就是0。

我的小技巧: 抓包时,看到连续的一段高电平(2.5V),那基本就是隐性位。看到突然跳变到3.5V/1.5V,就是显性位。这个特征在示波器上一眼就能认。

3.3 位仲裁机制:谁优先级高,谁先走

这才是CAN总线的灵魂。

当多个节点同时发送时,它们会从CAN帧的“仲裁段”开始,逐位往总线上发。每个节点都会同时监听总线电平。如果自己发的是隐性(1),但总线上是显性(0),那说明有别人在发优先级更高的数据。它会立刻停止发送,转为接收模式。

这个仲裁过程,比CPU的上下文切换快多了。

举个例子:

节点A发:1010 1100
节点B发:1011 0010

从最高位开始比:

  • 第1位:A发1,B发1,一致,继续。
  • 第2位:A发0,B发1,总线显性(0)→ B发现自己是隐性而总线是显性,B退出。
  • A继续发完剩下的数据。

你看,整个过程没有冲突,没有丢数据,没有重传。这就是CAN的高明之处。

避坑指南: 我曾经遇到一个故障。现场发现几台设备互相干扰,但抓包又看不出明显错误。后来发现是某台设备的CAN_ID设错了,而且仲裁段长度设置不一致,导致仲裁逻辑失效。检查总线时,一定确认所有节点的仲裁段格式和ID范围是统一的。

3.4 位填充规则:确保时钟同步不出错

CAN总线没有单独的时钟线。所有节点都靠总线信号边沿来同步,自己恢复时钟。

但问题来了:如果连续发5个相同的位(比如5个0或5个1),总线就没有跳变沿了。没有跳变,节点就没法纠正自己的时钟偏差。久了就会丢位,整帧数据就毁了。

所以,CAN协议规定:发送器在连续发送5个相同位后,必须插入一个极性相反的位。

发送数据 实际线上波形(含填充)
0000 0 1111 1 0000 01 1111 10
1111 1 0000 0 1111 10 0000 01
注意箭头处的填充位

接收器看到5个相同位后,就知道下一个位是填充的,会自动把它去掉。这样,数据内容一点没变,但总线保证每6个位最多会有一次跳变。

我记得有个同事调试时,线上数据总是对不上,用逻辑分析仪看也没问题。后来我让他把“位填充”的规则手工算一遍,发现接收器误把填充位当成了数据。原因就是他的时钟恢复算法没有正确处理填充位。

总结一下:
  • 位填充解决了时钟同步问题。
  • 发送器在5个连续相同位后,插入一个相反位。
  • 接收器自动删除填充位。
  • 只有数据段和CRC段会做填充。帧起始、仲裁段、控制段、ACK段不填充。

下面这张图,我把CAN总线仲裁和填充的整个流程串起来了。你看一遍,基本就能在大脑里跑一遍总线逻辑。

CAN总线仲裁与位填充核心流程 总线空闲 有节点发送? 否 是 多节点同时发送 逐位对比仲裁 (显性覆盖隐性) 失 败 节点退出 → 接收 获胜节点继续发送 发送数据段 (含位填充) 位填充规则:5个相同位后插反位 帧起始、ACK不参与填充

你看,整个通信过程就像一场有秩序的“辩论赛”。谁先拿到“话筒”(发送权),靠的是ID大小。谁能在长句中间保持“节奏”(时钟同步),靠的是填充规则。这两者一起,保证了CAN总线的高效和可靠。

好了,这一章就到这。记住这三个关键词:显性隐性定胜负,位仲裁定优先,位填充定同步。后面章节我们会用实际抓包数据,一步步验证这些原理。