控制器区域网络 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 灵活数据速率总线(CAN FD,Controller Area Network Flexible Data Rate);
- CAN 扩展数据域长度总线(CAN XL,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 总线被划分为高速 CAN(定义于
ISO 11898-2
规范),以及低速容错
CAN(定义于 ISO 11519-2
以及后续的
ISO 11898-3
规范)两种类型,这种划分方式会体现在
CAN
收发器芯片的规格书当中,进行参数选型时需要格外关注这个参数(下图是
NXP 公司的经典 CAN 收发器芯片 TJA1050
的数据手册首页):
高速 CAN
属于闭环总线网络,总线两端各连接一个 120 Ω
的电阻,并且通过信号线形成回路,适用于高速、短距离的通信,通信速率通常在
125Kbps ~ 1Mbps
,其在 1 Mbps
通讯速率下,总线通信距离可以达到 40m
长度,其基本网络拓扑如下图所示:
低速容错 CAN
属于开环总线网络,两条信号线分别串联一个
2.2KΩ
电阻,然后独立连接到 CAN 总线的 CAN_High
与 CAN_Low
上面,并不会构成环路,适用于低速、远距离的通信。通信速率最高只能达到
125 Kbps
,其在 40 Kbps
速率时,总线最长通信距离可以高达 1000m
长度:
CAN 总线上的数据采用 CANH
(即上图中的
CAN_High
)和 CANL
(即上图中的
CAN_Low
)两条信号线进行差分传输(后续会讨论采用差分信号传输的原因),然后通过两个信号之间的差值,来获取当前
CAN 总线网络上传输的有效电平值:
\[ V_{有效电平} = V_{CANH} - V_{CANL} \]
注意:有效电平为显性(Dominant [ˈdɒmɪnənt])表示逻辑信号
0
,有效电平为隐性(Recessive [rɪˈsesɪv])表示逻辑信号1
。
根据 ISO11898-2 和 ISO11898-3
两款国际规范,差分信号线 CANH
与 CANL
上面传输的电平值,需要遵循下面表格当中定义的范围:
根据上面表格当中的数据,就可以获得不同 CAN 总线网络上面,隐性电平与显性电平的典型电压差值:
- 高速 CAN
总线:隐性电平(相当于逻辑
1
)典型值为 \(V_{CANH} - V_{CANL} = 0V\) 表示,显性电平(相当于逻辑0
)典型值为 \(V_{CANH} - V_{CANL} = 2.0V\)。 - 低速容错 CAN
总线:隐性电平(相当于逻辑
1
)典型值为 \(V_{CANH} - V_{CANL} = -1.5V\),显性电平(相当于逻辑0
)典型值为 \(V_{CANH} - V_{CANL} = 3.0V\)。
注意:CAN 总线网络当中,只要一个节点输出显性电平,整个总线就会呈现出显性电平。只有当所有的节点都输出隐性电平的时候,总线才会呈现为隐性电平。
差分信号传输原理
下图所示的高速 CAN 总线网络,采用了阻抗为 120Ω
的闭环总线结构,两端分别连接有一枚 120Ω
的端接电阻(防止信号在 CAN
总线上出现反射),线材方面通常使用的是双绞线:
注意:通常情况下,CAN 总线上的设备节点都会连接到公共的地平面,从而具备有相等的接地电位。
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
的电源进行供电,并且两者依然需要形成共地连接关系:
CAN 控制器/收发器
上面已经简单介绍过一个CAN 总线节点通常是由 CAN 控制器(CAN Controller)和 CAN 收发器(CAN Transceive)共同构成的,接下来的内容会对两者的功能进行明确的定义,以避免大家在器件选型的时候出现混淆:
- CAN 控制器:负责 CAN
总线数据链路层的处理,其核心功能包括
报文的封装/解析
(帧格式、ID、数据长度等)、错误检测
(CRC 校验、帧校验等)、总线仲裁
(管理多节点的优先级)、位定时控制
(时序同步、位填充等)。 - CAN 收发器:负责在物理层将 CAN
控制器发出的逻辑电平
TX/RX
转换为差分信号CAN_H/CAN_L
,并且通常还具备有避免共模干扰
、进行电气隔离
的作用。
为了便于大家理解,在接下来的表格里,言简意赅的总结了 CAN 控制器和 CAN 收发器的区别:
特性 | CAN 控制器芯片 | CAN 收发器芯片 |
---|---|---|
核心功能 | 协议处理 | 电平转换 |
接口方向 | 连接至主控芯片 | 连接至物理 CAN 总线(双绞线) |
通信层级 | 数据链路层(OSI Layer 2) | 物理层(OSI Layer 1) |
典型芯片 | MCP2515 、SJA1000 、MCU 片内外设 |
TJA1050 、SN65HVD230 |
速率单位 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
上面存在电位差,CAN
总线上面一旦出现 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 总线数据帧
仲裁段
的组成部分,主要用于区分数据帧和远程帧,其状态决定了当前帧是用于发送数据
还是请求数据
。 - 扩展格式仲裁段当中的替代远程请求位(SRR,Substitute
Remote Request):主要用于兼容
标准帧
与扩展帧
的仲裁机制,确保扩展帧
不会错误的覆盖标准帧
,同时确保 CAN 总线的优先级机制。 - 扩展格式仲裁段当中的标识符扩展位(IDE,Identifier
Extension):用于区分标准帧和扩展帧,其在扩展帧当中固定取值为隐性(逻辑
1
),其值会影响到标识符ID
的长度与仲裁的优先级。
注意:标准格式的 11 位标识符,以及扩展格式的 11 位基本标识符,都禁止仲裁段的高 7 位全部是隐性的逻辑
1
,即禁止被设定为ID = 1111111XXXX
。
控制段
控制段用于表达数据段的字节长度,主要由 6 个位构成(其中 2 个保留位,4 个数据长度位),标准格式和扩展格式在控制段的构成也有所不同:
上图当中的保留位 r0
和 r1
两个位必须全部以显性电平(逻辑
0
)发送。而数据长度码(DLC,Data Length
Code)则由四个位构成(也就是 0 ~ 8
的四位二进制表示),其与数据段字节长度的对应关系如下面表格所示:
数据段长度 | 数据长度码第 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),确保优先级高的报文会优先发送,而优先级低的报文自动延迟发送。
数据帧 & 遥控帧
具有相同 ID
的数据帧和远程帧在竞争总线优先级时,仲裁段最后的远程传输请求位
RTR
为显性(逻辑
0
)的数据帧具有更高的优先权,其仲裁过程如下面示意图所示:
标准格式 & 扩展格式
当 CAN 总线当中,标准格式和扩展格式前 11 位的 ID 标识符相同时,其优先级将会通过逐位仲裁机制进行比较,此时仲裁段当中的以下数据会参与到优先级的仲裁:
数据段 | 标准帧(11 位标识符) | 扩展帧(29 位标识符) |
---|---|---|
前 11 位 | 完整 ID(只有 11 位) | 扩展帧前 11 位(与标准帧相同) |
SRR 位 |
无,等效为显性(逻辑
0 ) |
固定隐性(逻辑
1 ,替代 RTR 位) |
IDE 位 |
无,等效为显性(逻辑
0 ) |
固定隐性(逻辑
1 ,标识扩展帧) |
参考上面的这张示意图,可以将 CAN 总线的优先级仲裁流程总结成下面的三个步骤:
- 比较 11 位标识符:如果前 11 位不同,ID 值更小的帧优先级更高(显性 0 优先于隐性 1)。如果前 11 位相同,继续比较后续控制位(SRR 和 IDE)。
- 比较替代远程请求位
SRR
(仅扩展帧):标准帧没有显式的SRR
位,默认被隐式的等效为显性电平(逻辑0
),而 扩展帧的SRR
位固定为隐性电平(逻辑1
)。由于标准帧显性电平(逻辑0
)的优先级高于扩展帧的隐性电平(逻辑1
),因而相比较而言,标准帧的优先级会更高。 - 比较标识符扩展位
IDE
:标准帧同样没有显式的IDE
位,同样被默认等效为显性电平(逻辑0
),而 扩展帧的IDE
位固定为隐性电平(逻辑1
),所以标准帧的优先级依然更高。
位填充机制
CAN 总线的位填充(Bit Stuffing)机制是在连续 5 个相同电平位之后,自动插入 1 个反向的电平位。该机制主要用于同步 CAN 总线的时钟和进行错误检测,从而确保数据传输的可靠性。
CAN 收发器的发送单元与接收单元,它们各自的位填充机制分别如下面列表所示:
- 发送单元在发送数据帧和远程帧时,对于
SOF ~ CRC
位之间的数据,相同电平如果持续 5 位,就会在第 6 位插入一位与前 5 位反向的电平。 - 接收单元在接收数据帧和远程帧时,对于
SOF ~ CRC
位之间的数据,相同电平如果持续 5 位,就需要删除第 6 位之后再进行接收。如果第 6 位的电平值与前 5 位相同,那么就会被视为位填充错误,并且触发错误帧的发送。
错误处理机制
CAN 总线上的错误可以划分为
位错误
、填充错误
、CRC 错误
、格式错误
、ACK 错误
一共五种类型,这些错误的种类、内容、发生帧、检测单元,已经被分门别类的整理到下面的表格当中:
注意:上述表格当中的这些错误,即可能单独发生,也可能同时发生。
接下来的列表里,说明了 位错误
、格式错误
以及 填充错误
之间,一些容易混淆的触发原因:
- 当仲裁段输出隐性电平,但是检测出显性电平时,将会被视为仲裁失利,而非是位错误。
- 在仲裁段作为填充位输出隐性电平时,但检测出显性电平时,将不会被视为位错误,而是填充错误。
- 发送单元在 ACK 段输出隐性电平,但检测到显性电平时,将会被判断为其它单元的 ACK 应答,而非位错误。
- 当错误帧输出由 6 个隐性位(逻辑
1
)组成的被动错误标志,但是检测到其中一位是显性位(逻辑0
)的时候,这种情况下 CAN 总线将会等待检测出 6 个显性或者隐性的连续相同位,并不会被视为位错误。 - 当接收单元检测出
EOF
帧结束段(由 7 个隐性位组成)的时候,如果接收到的第 8 位为显性电平,这种情况不会被视为格式错误。 - 当接收单元检测到
DLC
数据长度码(长度仅0 ~ 8
个字节)出现 9∼15 的值时,也不会被视为格式错误。
当 CAN
总线当中检测到上述的错误时,就会开始在错误帧当中输出
错误标志
(Error Flag):
- 主动错误标志:由处于主动错误状态的 CAN 总线节点输出;
- 被动错误标志:由处于被动错误状态的 CAN 总线节点输出;
当 CAN 总线节点的错误帧发送完毕之后,就会再次发送数据帧或者远程帧。不同错误类型的输出时序(也就是输出的时机)会有所区别,具体如下面列表所示:
位错误
、填充错误
、格式错误
、ACK 错误
:从检测到错误之后的下一位开始,就会输出错误标志。CRC 错误
:从 ACK 段 的 ACK 界定符 之后的下一位,开始输出错误标志。
数据位的构成
位速率(Bit Rate)和波特率(Baud Rate)都是表达信号传输速率的单位,它们各自的定义分别如下所示:
- 位速率:表示的是每一秒钟所能够传输的二进制位的数量,也被称作比特率,例如
8bit/s
表示的就是 1 秒时间传输了 8 个位。 - 波特率:表示每一种钟所能够传输的码元数量(即脉冲个数或者信号变化次数),这里的码元可以是多进制的,既可以携带
1bit
的数据(此时就等效于比特率),也可以携带2bit
甚至4bit
的数据。
CAN 总线的传输速率采用比特位 bit
来进行描述,其中传输的每一个比特位都会被划分为
SS
、PTS
、PBS1
、PBS2
四个段,每个段又会由若干个时间量子(Tq,
Time Quantum)构成(这里的 Tq
就是 CAN
总线时序的最基本单位):
- 同步段(SS,Sync Segment):CAN 总线上 1
个位的输出是从同步段开始的,如果信号的跳变沿位于同步段范围以内,就表示该节点与
CAN 总线的时序同步,此时采样点的电平状态就会被采纳,同步段的大小固定为
1Tq
。 - 传播段(PTS,Propagation Segment):用于补偿信号在
CAN 总线网络传播的物理延迟,包括
发送节点的输出延迟
、CAN 总线信号的传播延迟
、接收节点的输入延迟
,该段的时间为各个延迟时间之和的两倍,该段长度可以被配置为1Tq ~ 8Tq
。 - 相位缓冲段 1(PBS1,Phase Buffer Segment
1):用于补偿信号边沿阶段产生的误差,其时间长度可以延长,但是不能缩短,该段长度可以配置为
1Tq ~ 8Tq
(CAN 总线电平的采样点位于该段的结束位置)。 - 相位缓冲段 2(PBS2,Phase Buffer Segment
2):同样用于补偿信号边沿阶段带来的误差,其时间长度可以缩短,但是不能延长,该段长度可以配置为
2Tq ~ 8Tq
。
CAN 总线上 1
个比特位的组成除了上述四个段之外,还存在着一个再同步补偿宽度(SJW,Synchronization
Jump Width)的概念,其主要用于补偿
时钟频率
、传送延迟
等带来的误差,通常取值在
1Tq ~ 4Tq
范围。
位时序同步机制
CAN 总线上的每一个节点,都拥有着自己的本地时钟,由于硬件差异和传输延迟的存在,这个时钟可能存在微小偏差。CAN 总线通过位同步(Bit Synchronization)机制来确保所有节点,都能够正确的识别数据位的起始和结束,避免由于时钟偏差导致的通信错误:
- 调整接收节点的采样点,使其尽可能接近发送节点的最佳采样位置。
- 补偿时钟频率偏差,确保长时间通信不会因为累积误差导致采样错误。
注意:CAN 总线采用非归零码(NRZ,Non Return to Zero)方式进行数字信号的编码,即恒定使用高低电平来表示逻辑
0
和1
,电平信号不会在每一个位之后归零,而是保持当前电平状态,直至下一个位的开始。
CAN 总线上传输的每一个比特位 bit
的开头或者结尾都没有附加同步信号,发送节点以与位时序同步的方式发送数据,接收节点根据总线上电平的变化同步进行接收。但是发送节点与接收节点存在的时钟频率误差,以及传输路径上的相位延迟,都会引发位时序同步出现偏差,因而接收节点会通过硬件同步或者再同步的方法调整接收时序:
硬同步(Hard
Synchronization)发生在帧起始 SOF
位置,用于对齐 CAN
总线节点之间的位时间(强制接收节点的位时间计数器重新从
0
开始,也就是与发送节点帧起始位置的下降沿对齐)。
再同步(Resynchronization)发生在数据帧的接收过程,用于微调接收节点的位时间,当检测到从
隐性
到 显性
电平的跳变时就会触发(排除帧起始位置)。即每当检测出跳变沿时,就会根据再同步补偿宽度
SJW
的值,通过延长相位缓冲段 1
PBS1
段,或者缩短相位缓冲段 2
PBS2
段,达到与位时序同步的目的(如果发生超出再同步补偿宽度
SJW
值的误差,那么其最大调整量不能超过 SJW
的取值)。
概而言之,我们可以将上述 CAN 总线的位同步机制概括为下面三个步骤:
- 检测从
隐性
到显性
的电平边沿跳变; - 计算相位误差,如果跳变发生在同步段
SS
之外,就说明当前存在着误差; - 通过相位缓冲段 1
PBS1
或相位缓冲段 2PBS2
调整误差,如果跳变发生在PBS1
区域,那么延长PBS1
;如果跳变发生在PBS2
区域,那么缩短PBS2
(延长和缩短的值都不得超过再同步补偿宽度SJW
)。
控制器区域网络 CAN 总线协议图解