2. CAN总线基础:从历史到帧结构,一次讲透

大家好,我是你们的车载系统讲师。今天咱们聊聊CAN总线的基础知识。说实话,CAN总线这东西,我刚开始接触的时候也觉得挺枯燥的——不就是两根线在那传数据吗?但后来在项目里踩过几次坑,才真正体会到,理解这些基础有多重要。

好,咱们直接进入正题。

2.1 CAN协议的历史:为什么会有CAN?

上世纪80年代,汽车里的电子设备越来越多。各种传感器、控制器之间要通信,线束变得又粗又重。我记得有个老工程师跟我说过,那时候一辆豪华车的线束总长度能超过2公里,重量几十公斤。你想想看,这得多浪费燃油?

1983年,德国博世公司开始研发一种新的串行通信协议。1986年,CAN(Controller Area Network)正式发布。它的目标很明确:

  • 减少线束:用两根线代替一堆乱七八糟的线
  • 高可靠性:汽车环境恶劣,通信不能掉链子
  • 实时性:刹车信号、发动机数据,延迟必须可控

1993年,CAN成为国际标准ISO 11898。到现在,几乎每辆车上都有CAN总线。我做过的一个项目里,一辆车上有5条不同的CAN网络,分别负责动力、车身、信息娱乐等不同域。嗯,这就是CAN的生命力。

核心要点:CAN总线诞生的初衷,就是解决汽车电子设备增多带来的线束复杂和通信可靠性问题。它不是为了追求高速,而是为了在恶劣环境下稳定工作。

2.2 物理层特性:差分信号与总线电平

CAN总线的物理层,说白了就是两根线:CAN_H和CAN_L。为什么用两根线?因为要用差分信号。

2.2.1 差分信号

差分信号是什么意思?就是信号不是用一根线对地电压来表示,而是用两根线之间的电压差来表示。CAN_H和CAN_L的电压差,决定了总线上的逻辑电平。

  • 显性电平(Dominant):CAN_H比CAN_L高,电压差约2V。逻辑上代表0。
  • 隐性电平(Recessive):CAN_H和CAN_L电压相等,电压差约0V。逻辑上代表1。

为什么用差分信号?抗干扰能力强。我在一个项目中遇到过,发动机点火时会产生很强的电磁干扰。如果是单端信号,数据早就乱套了。但差分信号不一样,干扰会同时作用在两根线上,电压差基本不变。说白了,就是干扰被抵消了。

个人经验:我曾经在调试一个CAN网络时,发现总线偶尔出现错误帧。排查了半天,最后发现是CAN_H和CAN_L的线束绞合不够紧密。差分信号对线束的绞合度有要求,绞得越密,抗干扰越好。这个细节,很多新手会忽略。

2.2.2 总线电平

CAN总线的电平状态,我习惯用一张表来记:

状态 CAN_H电压 CAN_L电压 电压差 逻辑值
隐性 2.5V 2.5V 0V 1
显性 3.5V 1.5V 2V 0

注意,显性电平会覆盖隐性电平。也就是说,如果多个节点同时发送,只要有一个节点发送显性电平(0),总线就是显性状态。这就是CAN总线仲裁的基础。

避坑指南:我曾经遇到过一个问题,CAN总线在长距离传输时,信号反射导致误码。后来发现是终端电阻没接好。CAN总线两端必须各接一个120Ω的终端电阻,用来匹配阻抗,消除信号反射。这个电阻,千万别省。

2.3 CAN帧结构:数据是怎么传的?

CAN总线上的数据,是以帧(Frame)为单位传输的。帧结构,说白了就是数据包的格式。CAN协议定义了四种帧类型:

  • 数据帧:传输数据
  • 远程帧:请求数据
  • 错误帧:报告错误
  • 过载帧:延迟下一帧

咱们一个一个说。

2.3.1 数据帧

数据帧是最常用的帧类型。它分为标准帧(11位ID)和扩展帧(29位ID)。我平时用得最多的是标准帧,简单够用。

数据帧的结构如下:

帧起始(1bit) + 仲裁场(12/32bit) + 控制场(6bit) + 数据场(0-8byte) + CRC场(16bit) + 应答场(2bit) + 帧结束(7bit)

我来拆解一下:

  • 帧起始:1个显性位,表示一帧开始
  • 仲裁场:包含ID和RTR位。ID决定了优先级,数值越小优先级越高
  • 控制场:包含IDE位、保留位和DLC(数据长度码)
  • 数据场:0到8个字节,实际传输的数据
  • CRC场:循环冗余校验,检测传输错误
  • 应答场:接收节点发送显性位,表示收到
  • 帧结束:7个隐性位,表示一帧结束

你想想看,一帧最多传8个字节数据。为什么这么少?因为CAN总线追求的是实时性和可靠性,不是吞吐量。8个字节,对于汽车上的控制信号来说,完全够用了。

核心要点:数据帧的ID决定了优先级。ID越小,优先级越高。在总线上,多个节点同时发送时,ID小的节点会赢得仲裁,继续发送。这就是CAN总线的非破坏性逐位仲裁机制。

2.3.2 远程帧

远程帧,说白了就是“请求数据”。一个节点发送远程帧,告诉另一个节点:“把你的数据发给我”。

远程帧的结构和数据帧很像,区别在于:

  • RTR位为隐性(1),表示这是远程帧
  • 数据场为空(0字节)

我记得在调试一个传感器节点时,主控需要定期获取传感器数据。我用的就是远程帧来触发传感器发送数据。这样,传感器不需要一直发,省电又省带宽。

2.3.3 错误帧

错误帧,是CAN总线自我纠错的重要机制。当节点检测到总线错误时,会发送错误帧,通知其他节点。

错误帧由两部分组成:

  • 错误标志:6个连续相同位(显性或隐性)
  • 错误界定符:8个隐性位

CAN协议定义了五种错误类型:

  • 位错误
  • 填充错误
  • CRC错误
  • 格式错误
  • 应答错误

我曾经在一个项目中,发现CAN总线频繁出现错误帧。排查下来,是某个节点的晶振频率偏差太大,导致位时序不对。嗯,这个坑我印象很深。

避坑指南:我曾经遇到过,某个节点发送错误帧太频繁,导致整个CAN网络瘫痪。后来发现是那个节点的收发器坏了,一直发送显性错误标志。CAN协议有错误限制机制,节点错误次数过多会自动离线。但在此之前,网络已经被拖垮了。所以,硬件质量很重要。

2.3.4 过载帧

过载帧,用于延迟下一帧的发送。当一个节点来不及处理接收到的数据时,可以发送过载帧,让其他节点等一等。

过载帧的结构和错误帧类似:

  • 过载标志:6个显性位
  • 过载界定符:8个隐性位

说实话,过载帧在实际项目中用得不多。我做了这么多年,也就遇到过一次。那是一个低速CAN网络,某个节点处理能力太弱,偶尔需要过载帧来缓冲。大部分情况下,只要设计合理,过载帧很少出现。

2.4 小结

好,咱们把今天的内容捋一捋:

  • CAN总线诞生于80年代,为了解决汽车线束复杂和通信可靠性问题
  • 物理层用差分信号,抗干扰能力强。显性电平(0)覆盖隐性电平(1)
  • 四种帧类型:数据帧、远程帧、错误帧、过载帧
  • 数据帧最常用,ID决定优先级,最多传8字节数据

下一章,咱们会深入CAN的仲裁机制和位时序。这些东西,在Android Automotive的CAN HAL层开发中会频繁用到。到时候,我会结合具体的代码,带大家实战一把。

今天就到这里。有什么问题,欢迎交流。