3、CAN总线入门:从历史到帧结构,一次讲透

各位同学,今天咱们聊聊CAN总线。说实话,这玩意儿在嵌入式通信里,尤其是电池均衡系统里,几乎是绕不开的。我最早接触CAN总线,是在做电动汽车BMS(电池管理系统)的时候。那时候刚上手,觉得这东西比串口复杂多了,后来摸透了才发现——嗯,它其实很优雅。

3.1 CAN总线的历史:为什么会有它?

上世纪80年代,汽车里的电子设备越来越多。你想想看,发动机、变速箱、ABS、气囊……每个模块都要通信。传统的点对点接线,线束比车还重。这时候,博世公司站了出来,在1986年推出了CAN总线(Controller Area Network,控制器局域网)。

它的初衷很简单:用两根线,让所有节点都能互相说话。而且,它天生就是为恶劣环境设计的——抗干扰、实时性高、容错性强。我个人觉得,CAN总线是工业通信领域最成功的发明之一。为什么?因为它活到了现在,还在广泛使用。

核心特点:

  • 多主总线:任何节点都可以主动发消息
  • 实时性强:优先级高的消息不等待
  • 错误检测:5种错误检测机制,几乎不漏检

3.2 物理层特性:差分信号与终端电阻

CAN总线的物理层,说白了就是两根线:CAN_H(高)和CAN_L(低)。它用的是差分信号传输。什么是差分信号?我举个例子你就明白了。

假设你要传一个“1”。单端信号可能是5V对地。但CAN总线不这么干。它让CAN_H拉到3.5V,CAN_L拉到1.5V。接收端看的是两者的差值:3.5 - 1.5 = 2.0V,这就是显性电平(逻辑0)。如果两根线都是2.5V,差值0V,那就是隐性电平(逻辑1)。

为什么会这样设计?抗干扰啊!你想想,如果外部有电磁干扰,两根线上会同时感应到同样的噪声。但差分信号只看差值,噪声被抵消了。我在一个电机驱动项目里遇到过,现场变频器一启动,串口通信就乱码。换成CAN总线后,稳如泰山。这就是差分信号的好处。

避坑指南:我曾经见过一个新手,把CAN_H和CAN_L接反了。结果总线死活不通。记住:CAN_H接CAN_H,CAN_L接CAN_L,别搞混。另外,终端电阻一定要加,不加的话信号会反射,通信会出错。

说到终端电阻,这是另一个关键点。CAN总线要求在总线两端各接一个120Ω的电阻。为什么是120Ω?因为CAN总线的特性阻抗大约是120Ω。匹配了,信号就不反射。我习惯在调试时先量一下CAN_H和CAN_L之间的电阻。如果两端都接了120Ω,那测出来应该是60Ω左右(两个120Ω并联)。如果测出来是120Ω,说明只接了一端;如果是无穷大,说明两端都没接。这个技巧,你记一下。

参数 说明
CAN_H显性电平 3.5V 逻辑0
CAN_L显性电平 1.5V 逻辑0
隐性电平 2.5V(两线相同) 逻辑1
终端电阻 120Ω(两端各一个) 匹配阻抗,防反射

3.3 CAN报文帧结构:四种帧类型

CAN总线上跑的是报文。报文有四种类型:数据帧、远程帧、错误帧、过载帧。咱们一个一个说。

3.3.1 数据帧

数据帧是最常用的。它负责把数据从一个节点发到另一个节点。结构如下:

  • 帧起始(SOF):1个显性位,告诉总线“我要开始发了”。
  • 仲裁场:包含11位标识符(标准帧)或29位标识符(扩展帧)。标识符越小,优先级越高。我习惯把关键消息(比如电池电压)的ID设小一点,这样抢总线时不会输。
  • 控制场:包含IDE位、R0位和DLC(数据长度码)。DLC告诉接收方后面跟了多少字节数据(0-8字节)。
  • 数据场:0-8字节的实际数据。嗯,最多8个字节,别嫌少,够用了。
  • CRC场:15位CRC校验码,加上1位CRC界定符。用来检查数据有没有传错。
  • ACK场:2位。发送方发完数据后,接收方如果正确收到,就在ACK槽里回一个显性位。如果没人回,发送方就知道出问题了。
  • 帧结束(EOF):7个隐性位,表示帧结束。

标准数据帧格式(11位ID):

SOF | 11位ID | RTR | IDE | r0 | DLC | 0-8字节数据 | CRC | ACK | EOF

3.3.2 远程帧

远程帧,说白了就是“请求帧”。一个节点可以发远程帧,问另一个节点:“嘿,把你的数据发给我。”远程帧和数据帧结构很像,但RTR位是隐性(1),而且没有数据场。我在调试BMS时,经常用远程帧去请求某个电芯的电压数据,很方便。

3.3.3 错误帧

错误帧是CAN总线自愈能力的体现。当某个节点检测到错误时,它会主动发错误帧,告诉所有节点:“刚才那帧有问题,大家别用了。”错误帧由6个显性位(错误标志)和8个隐性位(错误界定符)组成。我见过一个案例,总线上一根线断了,结果错误帧满天飞,整个网络瘫痪。后来加了总线诊断,才定位到问题。

注意:错误帧不是用来“报告错误”的,而是用来“破坏错误帧”的。它强制让所有节点知道当前帧无效,然后重发。这是CAN总线容错机制的核心。

3.3.4 过载帧

过载帧,用来告诉发送方:“我忙不过来了,你慢点发。”它和错误帧结构类似,但触发条件不同。过载帧在电池均衡系统中不常见,但如果你遇到节点处理不过来,可以了解一下。我个人觉得,过载帧更像是一种“流量控制”手段。

3.4 总结一下

CAN总线入门,其实就三件事:

  1. 物理层:差分信号+终端电阻,抗干扰能力强。
  2. 帧结构:数据帧最常用,远程帧用来请求,错误帧和过载帧是异常处理。
  3. 优先级:ID越小,优先级越高。关键消息用小编号。

下一章,咱们会深入CAN总线的仲裁机制和位时序。你想想看,多个节点同时发消息,总线怎么决定谁先发?嗯,这就是CAN总线的精髓。到时候再聊。

个人建议:如果你刚开始学CAN总线,别急着看协议栈。先拿一个USB-CAN分析仪,接上两个节点,发几帧数据看看波形。亲眼看到显性位和隐性位的变化,比看一百页文档都管用。我当年就是这么入门的。