2. CAN 协议基础:CAN 总线物理层特性、差分信号与双绞线、CAN 帧结构

好,咱们进入正题。CAN 总线这东西,我做了十几年车载网络,可以说它是整个汽车的「神经系统」。你想想看,发动机、变速箱、ABS、气囊,这些关键部件全靠它来传消息。要是它掉链子,车可就真趴窝了。

这一章,咱们把 CAN 协议的底裤扒干净。从物理层的电压怎么跳,到数据帧里每个 bit 是干嘛的,我都会掰开揉碎了讲。嗯,这里要注意,我讲的都是经典 CAN 2.0,不是 CAN FD,那个咱们后面再说。

2.1 物理层特性:为什么 CAN 能扛造?

先说物理层。说白了,就是信号在线上怎么跑。CAN 总线用的是两根线——CAN_H 和 CAN_L。它不依赖地线,靠的是两根线之间的电压差来传数据。

关键参数:

  • 显性电平(Dominant): CAN_H 约 3.5V,CAN_L 约 1.5V,差分电压约 2V。代表逻辑「0」。
  • 隐性电平(Recessive): CAN_H 约 2.5V,CAN_L 约 2.5V,差分电压约 0V。代表逻辑「1」。
  • 总线速率: 常见的有 125kbps、250kbps、500kbps。高速 CAN 最高能到 1Mbps。

我个人的习惯: 在项目初期定速率时,我一般会留 20% 的余量。比如目标 500kbps,我会按 400kbps 来设计线束和终端电阻。为什么?因为实际线束的寄生电容、节点数量都会拉低极限速率。我曾经吃过这个亏,后来就学乖了。

终端电阻: 每条 CAN 总线两端各需要 120Ω 的电阻。作用是消除信号反射。少了它,波形会振铃,数据就容易出错。

避坑指南: 我曾经遇到过一个项目,总线老是丢帧。查了两天,最后发现是终端电阻焊在了 PCB 中间,而不是线束两端。记住,电阻必须放在物理拓扑的最远端,不是随便找个地方一焊就完事。

2.2 差分信号与双绞线:抗干扰的秘密武器

为什么 CAN 要用两根线?一根线传信号不行吗?

不行。汽车里电磁干扰太严重了。点火线圈、电机、继电器,哪个不是噪声源?单端信号在这种环境里,分分钟被干趴。

差分信号的工作原理:

  • 发送端:把逻辑信号转换成 CAN_H 和 CAN_L 上的互补电压。
  • 接收端:只关心 V_diff = CAN_H - CAN_L 的值。
  • 干扰来了怎么办?两根线同时被干扰,但差分电压基本不变。这就是共模抑制。

说白了,干扰是「共模」的,信号是「差模」的。接收器只认差值,不认绝对值。所以哪怕地电位漂了 1V,只要两根线之间的差值没变,数据就还是对的。

双绞线的作用:

  • 绞合结构让两根线受到的电磁干扰几乎一样。
  • 每英寸绞合次数(Twist Rate)越高,抗干扰越好。我一般要求至少 40 次/米。
  • 双绞线还能减少自身对外辐射。你想想看,两根线电流方向相反,磁场互相抵消。

小技巧: 在实车布线时,CAN 线一定要远离大电流线(比如电机三相线)。如果实在避不开,必须交叉走线,不能平行。平行走线等于给干扰搭了条高速公路。

2.3 CAN 帧结构:四种帧类型详解

好,物理层讲完了,咱们看看数据是怎么打包的。CAN 协议定义了四种帧:数据帧、远程帧、错误帧、过载帧。我一个个说。

2.3.1 数据帧(Data Frame)

这是最常用的帧。一个节点发数据,其他节点收。标准帧有 11 位 ID,扩展帧有 29 位 ID。咱们先看标准帧。

数据帧结构(标准帧):

字段 位数 说明
SOF 1 帧起始,显性电平,同步所有节点
仲裁场 12 11位ID + RTR位(数据帧为显性)
控制场 6 IDE位、保留位、DLC(数据长度)
数据场 0~64 实际数据,最多8字节
CRC场 16 15位CRC + 1位CRC界定符
ACK场 2 ACK槽 + ACK界定符
EOF 7 帧结束,隐性电平

仲裁机制: 这是 CAN 最牛的地方。多个节点同时发数据怎么办?谁 ID 小谁赢。ID 越小,优先级越高。仲裁时,显性位(0)会覆盖隐性位(1)。所以 ID 全是 0 的节点,永远抢不到总线?不对,ID 全 0 优先级最高。

我遇到过的一个坑: 有一次,两个 ECU 的 ID 设成了同一个值。结果总线上一片混乱,数据全错。后来查规范才发现,CAN 协议要求每个节点必须有唯一 ID。这不是建议,是强制要求。否则仲裁机制就失效了。

2.3.2 远程帧(Remote Frame)

远程帧是用来请求数据的。一个节点发远程帧,另一个节点收到后,会发对应的数据帧。

  • 远程帧的 RTR 位是隐性(1),数据帧是显性(0)。
  • 远程帧没有数据场,DLC 表示请求的数据长度。
  • 实际项目中,远程帧用得不多。我一般建议用周期性发送代替远程请求,更可靠。

2.3.3 错误帧(Error Frame)

错误帧是节点发现总线错误时主动发的。它由两部分组成:

  • 错误标志: 6 个连续显性位。这会破坏其他帧的填充规则,强制所有节点发现错误。
  • 错误界定符: 8 个连续隐性位,用于恢复总线。

节点有三种错误状态:主动错误、被动错误、总线关闭。主动错误节点可以发主动错误帧,被动错误节点只能发被动错误帧(6 个隐性位)。总线关闭节点彻底闭嘴,不参与任何通信。

注意: 如果一个节点频繁发错误帧,说明它有问题。我曾经见过一个 ECU,因为晶振漂移,导致位时序不对,疯狂发错误帧,把整条总线都拖垮了。排查方法很简单:用示波器看总线波形,如果看到连续 6 个显性位,基本就是错误帧在捣乱。

2.3.4 过载帧(Overload Frame)

过载帧用于节点表示自己「忙不过来」。比如接收缓冲区满了,或者内部处理延迟。

  • 过载帧的结构和错误帧很像,也是 6 个显性位 + 8 个隐性位。
  • 区别在于:过载帧只在帧间空间(Interframe Space)里发,不会在帧中间发。
  • 实际项目中,过载帧很少见。如果频繁出现,说明节点处理能力不足,或者总线负载太高。

2.4 位填充与同步:保证数据不出错

CAN 协议有个很聪明的设计——位填充(Bit Stuffing)。

规则: 连续发送 5 个相同电平后,必须插入一个相反电平。比如连续 5 个显性位,第 6 位强制发隐性位。

为什么? 为了同步。接收节点靠电平跳变来同步时钟。如果长时间没跳变,时钟就漂了。位填充保证了每 5 个 bit 至少有一次跳变。

例外: CRC 界定符、ACK 场、EOF 这些固定格式的字段,不进行位填充。

经验之谈: 位填充也意味着,实际传输的 bit 数可能比理论值多。比如数据场全是 0x00,那就会频繁插入填充位。计算总线负载时,我一般按 20% 的填充开销来估算,留足余量。

2.5 小结

这一章内容不少,我帮你捋一下重点:

  • CAN 物理层靠差分信号抗干扰,双绞线是标配,终端电阻不能省。
  • 数据帧是主力,远程帧是辅助,错误帧和过载帧是异常处理。
  • 仲裁靠 ID 大小,ID 越小优先级越高。
  • 位填充保证时钟同步,但会增加总线负载。

下一章,咱们聊 CAN 控制器和收发器的硬件设计。到时候我会讲讲怎么选型、怎么布局、怎么处理 EMC 问题。都是实战经验,别错过。