控制器区域网络 CAN 总线协议图解
控制器区域网络(CAN,Controller Area Network)总线协议规范正式发布于 1986 年,由德国博世公司为解决汽车电子系统当中,复杂的线束问题而设计。1991 年发布的 CAN 2.0 A/B 规范的推出标志着其开启了标准化的进程。1993 年推出的 ISO 11898 标准进一步巩固了其国际规范地位。伴随汽车电子和工业控制需求的增长,2012 年发布的 CAN FD 进一步提升了带宽与数据长度。而 2020 年发布的 CAN XL 则能够支持更大的数据量传输,从而适应未来的高速场景。
CAN 总线协议发展到今天,已经以其低成本、实时性、高可靠性的优势,成为了一款应用非常广泛的标准化协议。工程技术的最佳学习方式,往往是基于最为直观的理解,而大量的示意图和表格正是化繁为简的利器。本文就将会通过丰富的图片与表格,展示 CAN 总线协议相关的各类技术细节。
CAN 总线发展历程
控制器区域网络(CAN,Controller Area Network)是一款广泛应用于汽车和工业领域的现场总线协议,由德国博世 BOSCH 公司于 1983 年推出,用于解决汽车电子系统中复杂的线束问题,实现各个电子控制单元(ECU,Electronic Control Unit)之间的可靠通信。
特性 | CAN 1.0 | CAN 2.0 | CAN FD | CAN XL |
---|---|---|---|---|
标准 | 博世公司率先发布 | ISO 11898-1:1993/2003 | ISO 11898-1:2015 | ISO 11898-1:2024 |
数据长度 | 8 字节 | 8 字节 | 64 字节 | 2048 字节 |
通信速率 | 1 Mbit/s |
1 Mbit/s |
2/5/8 Mbit/s |
20 Mbit/s |
标识符长度 | 11 位 标准格式 |
11/29 位 扩展格式 |
同 CAN 2.0 | 同 CAN 2.0 |
CRC 校验位 | 15 位 | 15 位 | 17/21 位 | 32 位 |
- CAN FD:CAN 灵活数据速率总线(Controller Area Network Flexible Data Rate);
- CAN XL:CAN 扩展数据域长度总线(Controller Area Network Extended Data-field Length);
注意:ISO 11898-1 国际标准定义了 CAN 规范的核心部分,即数据链路层(Data Link Layer)和物理层(Physical Layer)的相关标准。
ISO 11898 标准化规范
ISO 11898 是 ISO 国际标准化组织针对 CAN 总线制定的一系列标准,广泛应用于汽车、工业控制等领域。该系列标准分为多个部分,分别针对不同的 CAN 总线类型和速率:
协议部分 | 协议名称 | 英文名称 |
---|---|---|
ISO 11898-1 | CAN 数据链路层 | Data Link Layer |
ISO 11898-2 | 高速 CAN | High-Speed CAN |
ISO 11898-3 | 低速容错 CAN | Low-Speed Fault-Tolerant CAN |
ISO 11898-4 | 时间触发 CAN | Time-Triggered CAN |
ISO 11898-5 | 灵活数据速率 CAN | Flexible Data Rate |
ISO 11898-6 | 扩展数据域长度 CAN | Extended Data-field Length |
上面表格当中的 ISO 11898-1 主要定义了 CAN 总线的 数据链路层,也就是定义了数据在单个链路上如何进行传输,主要解决了如下几个问题:
- 如何将数据组装为数据块(该数据块就是帧,是数据链路层的基本传送单位);
- 如何控制帧在物理信道上的传输(包括如何处理传输错误,如何调节发送速率);
- 提供网络节点之间数据链路的管理(建立、维持、释放)。
注意:许多书籍和资料上提到的 ISO 11519-2 已经于 2006 年被 ISO 11898-3 整合并且取代,成为新的低速容错 CAN 标准。
CAN 总线与 OSI 模型
开放系统互连模型(OSI,Open System Interconnect)由
ISO 国际标准化组织于 1985
年正式制订使用,主要定义了网络互连的七层框架(物理层
、数据链路层
、网络层
、传输层
、会话层
、表示层
、应用层
),通常也被称作
OSI 参考模型:
CAN 总线规范 ISO 11898 与 OSI 模型的对应关系如下图所示,其中 ISO 11898-1 定义了 CAN 协议的数据链路层(Data Link),而 ISO 11898-2 则是定义了高速 CAN 总线的物理层(Physical)。简而言之,ISO 11898-1 是协议基础,而 ISO 11898-2 是物理层实现:
除此之外,数据链路层还被进一步划分为了媒介访问控制(MAC,Medium Access Control)和逻辑链路控制(LLC,Logical Link Control)两个子层。
CAN 总线的基本拓扑
CAN 总线依赖于 CANH
(CAN High)和 CANL
(CAN
Low)两根差分信号线进行通信,并且两端分别连接有一枚 120Ω
的端接电阻器,防止信号在 CAN 总线上出现反射干扰:
注意:通常情况下,CAN 总线上的设备节点都会连接到公共的地平面,从而具备有相等的接地电位。
如上图所示,CAN 总线网络采用了阻抗为 120Ω
的闭环总线结构,两端分别连接了一枚 120Ω
的端接电阻,线材方面通常使用的是双绞线。而 CAN
总线上的隐性电平与显性电平的取值范围,分别如下面两个表格所示:
隐性电平 | 最小值 | 典型值 | 最大值 |
---|---|---|---|
CAN_High | 2.00 V |
2.50 V |
3.00 V |
CAN_Low | 2.00 V |
2.50 V |
3.00 V |
电位差 | -0.5 V |
0 V |
0.05 V |
显性电平 | 最小值 | 典型值 | 最大值 |
---|---|---|---|
CAN_High | 2.75 V |
3.50 V |
4.50 V |
CAN_Low | 0.50 V |
1.50 V |
2.25 V |
电位差 | 1.5 V |
2.0 V |
3.0 V |
差分信号传输原理
CAN 总线之所以采用差分信号(Differential
Signaling)进行传输,原因在于单端信号(Single-Ended
Signaling)的连接方式容易受到电磁干扰,导致传输线路上出现尖峰电压,致使系统错误的将其判断为高电平
1
,从而破坏传输信号的完整性。
例如上面的波形图当中,应当传输的正确信号为
00011000
,由于受到尖峰电压的干扰,接收端实际读取到的信号变成了
01011011
。而 CAN 总线采用 CANH
和
CANL
两个相位相反,幅值一致的差分信号来传输数据,并且从信号的电位差当中提取有效的电平数据:
\[ V_{有效电平} = V_{CANH} - V_{CANL} \]
例如对于使用 3.3V
电平信号的 CAN
总线,其数据使用显性和隐性两种状态进行传输(这些状态源自于
CANH
和 CANL
两条信号线之间的电位差):
- 显性状态(Dominant State):表示逻辑信号
0
,此时CANH
和CANL
之间的电位差约为3.5V - 1.5V = 2V
; - 隐性状态(Recessive State):表示逻辑信号
1
,此时CANH
和CANL
之间的电位差约为2.5V - 2.5V = 0V
;
CAN 总线差分信号传输方式的抗干扰能力,主要来源于 CANH
和
CANL
组成的双绞线,它们同时接收到的尖峰电压噪声幅值基本一致。而噪声幅值保持一致的两个信号,其电位差等效于没有受到噪声的干扰,具体请参见下面的示意图:
CAN 总线节点的构成
通常情况下,MCU 微控制器只能产生数字信号,因而需要额外连接一片用于产生差分信号的 CAN 收发器,共同形成一个 CAN 总线节点:
CAN 总线属于异步半双工通信协议,因而 CAN
收发器通常携带有 TXD
(数据发送)和
RXD
(数据接收)两个引脚,用于与 MCU
微控制器交换数据,并将单端的 TXD/RXD
数字信号转换为差分的
CANH/CANL
信号:
CAN 收发器 芯片的额定工作电压通常为
5V
,在与工作电压同样为 5V
的 MCU
微控制器协同工作的时候,双方都可以通过 5V
的
LDO 或者 DC-DC
电源进行供电,并且两者需要形成共地连接:
如果 MCU 微控制器的额定工作电压为 3.3V
,
那么就必须分别采用两颗 3.3V
和 5V
的电源进行供电,并且两者依然需要形成共地连接关系:
速率单位 MB/s 与 Mbps
兆字节每秒(MB/s,Megabytes Per Second)和 兆比特每秒(Mbps 或 Mbit/s,Megabits Per Second)都是用于衡量数据传输速率的单位:
1 MB/s
表示每秒传输1
百万个字节Bytes
的数据。1 Mbps
表示每秒传输1
百万个比特位bits
的数据。
根据 1 Byte = 8 Bits
,可以将 MB/s
与
Mbps
的换算关系联立为如下的推导公式:
\[ 1 Byte = 8 Bits \implies \begin{cases} 1 MB/s = 8 Mbps \\ 1 Mbps = 0.125 MB/s \end{cases} \]
注意:大写的
B
通常用于表示字节Byte
,而小写的b
则通常用来表示比特位bit
。
通信帧类型的划分
CAN
总线协议当中的帧类型,主要用于区分不同用途的数据传输格式。CAN
总线协议存在有
数据帧
、遥控帧
、错误帧
、过载帧
、帧间隔
五种帧(Frame)类型,其中 数据帧
和
遥控帧
拥有标准和扩展两种格式(标准格式拥有
11 位标识符,扩展格式拥有 29 位的标识符):
- 数据帧:用于
发送单元
向接收单元
传送数据。 - 远程帧:用于
接收单元
向具有相同标识符的发送单元
请求数据。 - 错误帧:用于在检测出错误的时候,向其它单元通知错误。
- 过载帧:用于
接收单元
通知其尚未做好接收准备。 - 帧间隔:用于分离
数据帧
、遥控帧
与其它的帧。
CAN
总线协议当中的标识符,在许多英文资料的原文当中被称为
ID
,也就是英文 Identifier
的缩写形式。在接下来的内容里,我们将会分门别类、图文并茂的介绍这五种帧类型。
注意:技术资料当中经常提到的报文是指通信总线上传输的完整信息单元,而帧则主要是指报文在物理层面上的传输格式。
帧类型 - 数据帧
CAN 总线网络里的数据帧(Data Frame),主要由如下图所示的 7 个信号片段所构成:
- 帧起始段:表示数据帧开始的段。
- 仲裁段:表示该数据帧优先级的段。
- 控制段:表示数据的字节数以及保留位的段。
- 数据段:数据携带的具体内容,可以发送
0~8
个字节的数据。 - CRC 段:用于检查数据帧传输错误的段。
- ACK 段:用于确认正常接收的段。
- 帧结束段:表示数据帧结束的段
帧起始段
帧起始指的是帧最开始的一位,也被称为
SOF(Start of Frame),帧起始总是为显性位
0
,表示 CAN_H
和 CAN_L
上面存在了电位差,即总线上一旦出现 SOF 就表明有报文出现。
CAN 总线上总是存在有 显性电平(逻辑
0
)和 隐性电平(逻辑
1
)两种信号:
- 显性状态(Dominant [ˈdɑːmɪnənt]):相当于逻辑电平
0
,即本文示例图片当中的英文标识D
; - 隐性状态(Recessive [rɪˈsesɪv]):相当于逻辑电平
1
,即本文示例图片当中的英文标识R
;
注意:只要有一个单元输出显性电平,CAN 总线就会表现为显性电平。只有当所有单元都输出隐性电平,CAN 总线才会表现为隐性电平。
仲裁段
仲裁段用于判定帧的优先级,标准格式和扩展格式在仲裁段的构成有所不同。其中,标准格式拥有
11 位标识符,而扩展格式则拥有
29
位标识符(11位基本标识符 + 18位扩展标识符
):
标准格式当中的远程传输请求位(RTR,Remote
Transmission Request)同样是 CAN 总线数据帧 仲裁段
的组成部分,主要用于区分数据帧和远程帧,其状态决定了当前帧是用于
发送数据
还是 请求数据
。
注意:标准格式的 11 位标识符,以及扩展格式的 11 位基本标识符,都禁止仲裁段的高 7 位全部为隐性的逻辑
1
,即禁止被设定为ID = 1111111XXXX
。
控制段
控制段用于表达数据段的字节长度,主要由 6 个位构成(2 个保留位,4 个数据长度位),标准格式和扩展格式在控制段的构成也有所不同:
上图当中的保留位 r0
和 r1
两个位必须全部以显性电平(逻辑
0
)发送。而数据长度码(DLC,Data Length
Code)则由四个位构成,其与数据段字节长度的对应关系如下面表格所示:
数据段长度 | 数据长度码第 3 位 | 数据长度码第 2 位 | 数据长度码第 1 位 | 数据长度码第 0 位 |
---|---|---|---|---|
0 字节 | 显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
1 字节 | 显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
隐性 R(逻辑
1 ) |
2 字节 | 显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
隐性 R(逻辑
1 ) |
显性 D(逻辑
0 ) |
3 字节 | 显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
隐性 R(逻辑
1 ) |
隐性 R(逻辑
1 ) |
4 字节 | 显性 D(逻辑
0 ) |
隐性 R(逻辑
1 ) |
显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
5 字节 | 显性 D(逻辑
0 ) |
隐性 R(逻辑
1 ) |
显性 D(逻辑
0 ) |
隐性 R(逻辑
1 ) |
6 字节 | 显性 D(逻辑
0 ) |
隐性 R(逻辑
1 ) |
隐性 R(逻辑
1 ) |
显性 D(逻辑
0 ) |
7 字节 | 显性 D(逻辑
0 ) |
隐性 R(逻辑
1 ) |
隐性 R(逻辑
1 ) |
隐性 R(逻辑
1 ) |
8 字节 | 隐性 R(逻辑
1 ) |
显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
显性 D(逻辑
0 ) |
注意:数据段的有效字节长度只有
0 ~ 8
个字节,但是接收方并不会将9 ~ 15
的值视为错误。
数据段
数据段可以存放 0 ~ 8
个字节的数据(长度由控制段中的数据长度码进行标识),数据传输时遵循高位优先的原则:
CRC 段
CRC 段主要是由 15
位的 CRC
计算值,和 1
位的 CRC
界定符构成:
CAN 总线引入了循环冗余校验(CRC,Cyclic Redundancy
Check)来检测传输错误,收发双方通过核对基于
帧起始
、仲裁段
、控制段
、数据段
计算得到 CRC 值来检测数据传输错误。
ACK 段
ACK 段用来确认是否正常接收(通过
接收单元
发送,而 发送单元
无需发送),主要由
1 位的 ACK 槽(ACK Slot)和 1 位的 ACK
界定符(ACK Delimiter)共同组成:
ACK 是英文
Acknowledgment
(应答信息)的缩写形式,顾名思义,主要是用于确认数据帧、遥控帧是否被至少一个
CAN 总线节点正确接收(不存在
填充错误
、格式错误
、CRC 校验错误
)。
帧结束段
帧结束段(EOF,End of
Frame)用于表示数据帧结束, 用于标识一个
数据帧
、遥控帧
的结束,从而确保 CAN
总线恢复到空闲状态,其值固定为 7 位 隐性位(逻辑
1
),就也就连续的 7 个 1
(也就是
1111111
)。
帧类型 - 远程帧
远程帧(Remote Frame)用于在 CAN 总线网络当中请求数据,远程帧主要由如下 6 个信号片段组成(相比于前面介绍的数据帧,两者最大的区别在于远程帧没有数据段):
- 帧起始段:表示数据帧开始的段。
- 仲裁段:表示该数据帧优先级的段。
- 控制段:表示数据的字节数以及保留位的段。
- CRC 段:用于检查数据帧传输错误的段。
- ACK 段:用于确认正常接收的段。
- 帧结束段:表示数据帧结束的段
对于远程帧与没有 数据段
的数据帧(可用于各节点之间的心跳连接,或者其
仲裁段
就携带着有效信息),可以通过远程帧当中的远程传输请求位
RTR
进行区分,远程帧的 RTR
位总是保持为隐性(逻辑
1
)。除此之外,由于远程帧没有数据段,所以其控制段当中的
数据长度码
需要以其所请求的数据帧的 数据长度码
进行表示。
帧类型 - 错误帧
CAN 总线的错误帧(Error Frame)用于在检测到错误时通知其它节点,并且触发错误恢复机制。错误帧主要由错误标志(Error Flag)和错误界定符(Error Delimiter)两部分组成:
- 错误标志:包含主动错误标志(由 6
个显性位逻辑
0
组成)和被动错误标志(由 6 个隐性位逻辑1
组成)两种类型(具体取决于节点的错误状态属于主动还是被动)。 - 错误界定符:由 8 个隐性位逻辑
1
组成,用于标识该错误帧结束。
帧类型 - 过载帧
过载帧(Overload Frame)是 CAN 总线协议当中,用于处理节点接收过载(无法及时处理数据)的一种机制,过载帧由 过载标志(Overload Flag)和 过载界定符(Overload Delimiter)两部分组成:
- 过载标志:用于标识当前节点出现过载,由 6
个显性位逻辑
0
组成。 - 过载界定符:用于标识当前节点出现过载,由 8
个隐性位逻辑
1
组成。
注意:过载帧的结构与错误帧类似,但是各自的触发条件与用途不同。
帧类型 - 帧间隔
帧间隔(Inter Frame Space)用于分隔
数据帧 和
远程帧,即将本帧与前面的其它帧分隔开来(过载帧和错误帧前面,不能插入帧间隔),从而确保前一帧完全结束(此时可以认为总线空闲)。帧间隔由
3 个隐性位(逻辑 1
)组成(即
111
),位于帧结束段(EOF)之后。
优先级仲裁机制
当 CAN
总线网络空闲的时候,最先发送消息的节点优先级更高。多个节点同时发送数据时,每个节点的发送单元会从仲裁段的第
1 位开始逐位进行仲裁,连续输出显性电平(逻辑
0
)最多的节点,所发送数据的优先级更高。
CAN 总线的优先级仲裁机制基于非破坏性逐位仲裁(Bitwise Arbitration)进行判断,确保高优先级报文在总线冲突时无损传输。
控制器区域网络 CAN 总线协议图解