第2章:CAN总线基础

各位同学,今天我们来聊聊CAN总线。说实话,CAN总线是我在车载系统里打交道最多的通信协议之一。记得我刚入行那会儿,第一次调试CAN网络,一个错误帧就把我折腾了一整天。嗯,今天我就把这些经验分享给你们。

2.1 CAN协议原理

CAN的全称是Controller Area Network,控制器局域网。它最早是德国Bosch公司为汽车开发的。你想想看,一辆车上几十个ECU要互相通信,总不能用一堆线直接连吧?CAN总线就是干这个的。

CAN协议的核心思想其实很简单:所有节点共享一条总线,谁想说话谁就说。但问题来了——如果两个节点同时说话怎么办?这就涉及到它的仲裁机制了。

关键特性:

  • 多主通信:任何节点都可以主动发送数据
  • 非破坏性仲裁:优先级高的报文自动获胜,不会丢失数据
  • 错误检测与恢复:5种错误检测机制,自动重发
  • 实时性:最坏情况下的响应时间可计算

我个人习惯把CAN总线比作一个会议室。谁想发言就举手(发送数据),但如果两个人同时举手,ID小的(优先级高)先讲。这就是非破坏性仲裁的精髓。

2.2 CAN帧结构

CAN总线上传输的数据,我们叫它"帧"。一共有4种帧类型,但最常用的是数据帧和远程帧。我重点讲这两个。

2.2.1 数据帧

数据帧是干活的主力。它负责把数据从一个节点传到另一个节点。标准格式长这样:

SOF | 11位ID | RTR | IDE | r0 | DLC | 0-8字节数据 | CRC | ACK | EOF
 1     11       1     1     1     4       0-64       15     2     7

我来拆开讲:

  • SOF(Start of Frame):1位,标志帧开始。说白了就是"我要说话了"
  • ID(标识符):11位(标准帧)或29位(扩展帧)。这个ID决定了优先级,数值越小优先级越高
  • RTR(Remote Transmission Request):1位,数据帧里固定为0
  • DLC(Data Length Code):4位,表示数据长度,0到8字节
  • 数据段:0-8字节,真正要传的内容
  • CRC:15位校验码,保证数据没被干扰
  • ACK:应答位,接收节点告诉发送节点"我收到了"

经验之谈:我在项目中遇到过一个问题——某个传感器老是丢数据。查了半天,发现是DLC设置错了。发送方设了8字节,但实际只填了4字节有效数据,接收方把后面的垃圾数据也当有效数据用了。所以,DLC一定要和实际数据长度一致。

2.2.2 远程帧

远程帧,说白了就是"请求帧"。一个节点想从另一个节点要数据,就发个远程帧过去。

远程帧和数据帧长得几乎一样,唯一的区别是RTR位为1。而且远程帧没有数据段,DLC表示它想要多少字节的数据。

举个例子:发动机ECU想请求车速传感器的数据,就发一个远程帧,ID是车速传感器的ID,DLC=8。车速传感器收到后,就会发一个数据帧回来。

注意:远程帧的DLC必须和响应数据帧的DLC一致。我曾经见过一个新手,远程帧设DLC=8,但传感器只返回4字节数据,结果接收方一直等数据,导致总线阻塞。嗯,这个坑我踩过。

2.2.3 错误帧

错误帧是CAN总线的"交警"。当某个节点检测到总线错误时,就会发送错误帧,通知所有节点"刚才的数据有问题,别用"。

错误帧由两部分组成:

  • 错误标志:6个连续的显性位(主动错误)或6个连续的隐性位(被动错误)
  • 错误界定符:8个连续的隐性位

CAN总线有5种错误检测机制:位错误、填充错误、CRC错误、格式错误、应答错误。说实话,你不需要全记住,但要知道——CAN总线的容错能力很强,这也是为什么它在汽车上用了这么多年。

2.3 CAN总线物理层

物理层,说白了就是"线怎么接"。CAN总线用两条线:CAN_H和CAN_L。信号靠这两条线的电压差来传输。

信号状态CAN_H电压CAN_L电压差分电压
显性(逻辑0)3.5V1.5V2.0V
隐性(逻辑1)2.5V2.5V0V

你想想看,为什么用差分信号?因为抗干扰能力强。车上的电磁环境多复杂啊,发动机点火、电机运转,到处都是干扰。差分信号能抵消共模干扰,保证通信可靠。

物理层关键参数:

  • 总线电平:显性0V,隐性2.5V(差分)
  • 终端电阻:120Ω,总线两端各一个
  • 最大通信距离:与波特率有关,1Mbps时约40米
  • 最大节点数:理论上110个,实际建议不超过30个

我记得有一次调试,总线一直报错。量了CAN_H和CAN_L的电压,发现只有1.8V。查了半天,原来是终端电阻焊错了,用了10Ω的电阻。嗯,终端电阻一定要用120Ω,而且只在总线两端各放一个。

2.4 CAN网络拓扑

CAN总线的拓扑结构,说白了就是"一条线串起所有节点"。最常用的是总线型拓扑。

总线型拓扑的特点:

  • 所有节点并联在一条总线上
  • 总线两端各有一个120Ω终端电阻
  • 节点通过CAN收发器连接到总线
  • 任意节点故障不影响其他节点通信

除了总线型,还有星型拓扑和环型拓扑,但在车载系统里很少用。我建议你老老实实用总线型,简单可靠。

布线建议:

  • CAN_H和CAN_L要双绞,绞距约2-3cm
  • 总线长度尽量短,分支长度不超过30cm
  • 远离高压线、电机等强干扰源
  • 屏蔽层单端接地,避免地环路

我曾经在一个项目里,为了走线方便,把CAN总线绕了一大圈,结果通信速率只能降到125kbps才能稳定。后来重新布线,缩短了总线长度,速率直接上到500kbps。所以,布线真的不能马虎。

2.5 小结

好了,这一章的内容就这些。CAN总线看起来复杂,但说白了就是一套"谁先说话谁有理"的通信规则。你只要记住:

  • 数据帧是干活的主力
  • 远程帧是"给我数据"的请求
  • 错误帧是总线的"交警"
  • 物理层用差分信号抗干扰
  • 拓扑结构用总线型最靠谱

下一章,我们会讲CAN驱动开发。到时候我会带你们手写一个CAN驱动,把今天学的这些帧结构用代码实现出来。嗯,那才是真正有意思的部分。