本文力求以图文并茂来接好CAN通讯协议的基础知识,希望能给有兴趣的朋友带来一些收获。
为了便于大家理解与接受,请先看一幅图:
简单地讲CAN总线就如上图1中两根粗黄线,其通讯原理:好比开一个电话会议,大家都拨进来了,这时会议的状态可能是:
- 一人说,其他人听;
- 两人甚至多人同时开口了,但只会让另一人说,其他人听;
- 一人要求另一人说;
- 有人睡着了,掉线了,电话卡顿了… …
针对于上述各种情况,要保证这个电话会议的有序高效地进行,那么我们需要有一些约定俗成的规定或协议,大家都遵守。CAN总线通讯与这种电话会议形式有异曲同工之处,那么CAN总线通讯到底具体是怎么回事?接下来将以理论与实践相结合方法来介绍CAN通讯协议。
第1部分 概览
控制器局域网CAN( Controller Area Network)属于现场总线的范畴,是一种有效支持分布式控制系统的串行通信网络。是由德国博世公司在20世纪80年代专门为汽车行业开发的一种串行通信总线。由于其高性能、高可靠性以及独特的设计而越来越受到人们的重视,被广泛应用于汽车业、航空业、工业控制、安全防护等领域。
随着CAN总线在各个行业和领域的广泛应用,对其的通信格式标准化也提出了更严格的要求。1991年CAN总线技术规范(Version2.0)制定并发布。该技术规范共包括A和B两个部分。其中2.0A给出了CAN报文标准格式,而2.0B给出了标准的和扩展的两种格式。
1.1 CAN总线架构简介
CAN总线是一种用于在不同的ECU(电子控制单元)之间传输数据的线,CAN总线协议是一种ISO 国际标准化的串行通信协议,有 ISO-11898 和 ISO-11519两个系列。其定义有:
- ISO-11898 定义了通信速率为 125 kbps ~1Mbps 的高速 CAN
通信标准,属于闭环总线,传输速率可达1Mbps,总线长度 ≤ 40米,如图2。 - ISO11519 定义了通信速率为 10~125 kbps 的低速 CAN
通信标准,属于开环总线,传输速率为40kbps时,总线长度可达1000米,如图2。
高速CAN和低速CAN广泛应用于汽车总线,如下图3。
CAN通讯速率(位速率)与CAN总线长度的关系大致如下图。
以上介绍了高低速CAN两种总线架构的基本概念,接下来具体看看这两种CAN总线。
1.2 CAN总线结构信息
将上图2细化,我们可以看到两种CAN总线结构都有CAN_H,CAN_L两根线和多个节点。其中CAN_H和CAN_L线是以双绞形式缠绕,每个节点都有CAN收发器(transceiver)和CAN控制器(controller),CAN收发器和CAN控制器可能集成在芯片(on-chip),也可能是独立于芯片(off-chip)。(图3列举了两种CAN收发器–TJA1054和82C250)
1.3 CAN总线信号
CAN总线上,信号表现为电压形式,通过CAN_H和CAN_L线上的电位差来表示CAN信号,分为显性电平(dominant)和隐性电平(recessive)两种类型。其中显性电平规定为逻辑0,隐性电平则为逻辑1。其具体定义可通过下图来理解。
具体说,如上图第1幅图:当CAN_H和CAN_L的电压均为2.5v,两者电压差为0,就规定CAN信号为隐性电平;当CAN_H的电压为3.5v,CAN_L的电压为1.5v,两者电压差为2V,就规定CAN信号为显性电平。这里实际的规定是:电压差满足定义的一定范围,就可以认为是显性电平或者隐性电平,比如电压差在1.5-2.5v范围,都认为是显性电平。
为了加深理解,看了一段实际采集的电压形式的CAN信号:
1.4 CAN信号传输
上述的电位差(差分电平)由CAN收发器实现。在发送过程,CAN控制器将CPU传来的信号转换为逻辑电平。CAN收发器接收逻辑电平之后,再将其转换为差分电平输出到CAN总线上。
在接收过程,CAN收发器将CAN_H 和 CAN_L 线上传来的差分电平转换为逻辑电平输出到CAN控制器,CAN控制器再把该逻辑电平转化为相应的信号发送到CPU上。
通俗地讲,就是发送方通过CAN收发器使总线电平发生变化,将其信息传递到CAN总线上。接收方通过监听总线电平,将总线上的消息读入自己的CAN收发器。
由上可知:CAN总线有2种架构,CAN信号有2种形式,CAN信号发送和接收2个过程。
第2部分 CAN总线特性
为了有助于理解后面讲述的内容,先看CAN总线有什么特性。
2.1 多主工作方式
CAN总线上的所有节点没有主从之分,反应在数据传输上是:在总线空闲状态下,任意节点都可以向总线上发送信息。另外:最先向总线发送信息的节点获得总线的发送权;当多个节点同时向总线发送消息时,所发送消息的优先权高的那个节点获得总线的发送权。
说明:0x12优先级高于0x67,所以0x12先于0x67发送;紧接着0x52也要求发送,同样其优先级也高于0x67,所以0x52先于0x67发送,依次类推。这里0x12优先级高于0x67是怎么判断的呢?这就下个特点相关。
2.2 非破坏性仲裁机制
非破坏性仲裁机制是一种既不会造成已发送数据的延迟,也不会破坏已经发送的数据的仲裁机制,其具体实施需要了解CAN协议帧结构,线与机制等。其中,线与机制简单说就是位与计算,显性电平会覆盖隐性电平(换种方式理解:电路通路情况下,有一个端点接地(GND),那么整个电路电压就接地了)。
再了解线与机制后,看一个简单的仲裁例子,如下图:
上图:假设CAN总线上只有两个节点 A和B,它俩的ID用逻辑电平表示,我们规定:从SOF位开始,从左往右逐位比较,只要出现位不一样,比较就结束,显性电平者胜出,有权发送。
当节点A,B都发送请求时,开始逐位比较,直到它俩的ID7位,节点A为显性电平,节点B为隐性电平。根据线与机制,节点A胜出,优先发送。这就是一个大致的非破坏性仲裁过程。为了精准地实施仲裁过程,对CAN协议帧结构有严谨的设计,后续将会详细分析。
2.3 系统的柔软性
与总线相连的节点没有类似于“地址”的信息。因此在总线上增加节点时,连接在总线上的其它节点的软硬件及应用层都不需要改变。
2.4 通信速度
根据整个网络的规模,可设定适合的通信速度。在同一网络中,所有单元必须设定成统一的通信速度。即使有一个单元的通信速度与其它的不一样,此单元也会输出错误信号,妨碍整个网络的通信。不同网络间则可以有不同的通信速度。(简单一句话理解:双方必须需要在同一频道交流,不然沟通就有障碍)。
2.5 远程数据请求可通过发送“遥控帧” 请求其他单元发送数据。
2.6 信息广播信息广播就如:节点A发送一条ID 0x12的信息,然后节点B,C,D都能收到。
上图节点B,C,D最终是否会接收这个0x12发送信息,与他们设置相关,如下图只有节点B设置接收,C,D将会丢弃该条信息,这个过程与报文过滤相关。
第3部分 CAN协议帧结构
上述仲裁机制部分我们提到CAN协议帧,总的来说CAN协议帧有5种类型,下面逐个展开。
由于数据帧与遥控帧的最大差别在于遥控帧没有数据段,所以将两者放在一起讲述:
3.1数据帧和遥控帧
数据帧和遥控帧都有标准格式和扩展格式,这2种格式都具有相同的帧结构。
数据帧由7个段构成,遥控帧由6个段构成。先看数据帧:
这里结合实际采集的CAN总线电压信号来看下标准格式的数据帧。
再看遥控帧(也叫远程帧):
通过图13和15对比数据帧和遥控帧有:
通过对数据帧和遥控帧有了基本认识,下面我们再具体了解下每个段。
1) 帧起始(SOF, Start of Frame)
表示帧开始的段,1个位的显性位。(总线空闲时为隐性位,故帧起始以显性位非常好识别),对于数据帧和遥控帧的标准/扩展格式均如此。
2) 仲裁段(Arbitration field)
表示数据的优先级的段,起作用就是根据报文ID来确定其发送优先级。标准格式和扩展格式在此的构成有所不同。
这里对比数据帧与遥控帧各自的两个格式,其不同为:
针对上表的这种设计,后面会具体分析其在仲裁过程的作用。
3) 控制段(Control field)
表述数据段的字节数,由6个位构成,标准格式和扩展格式的构成有所不同。
4) 数据段(Data Field)
数据段可包含0-8个字节的数据,从MSB(最高位)开始输出。遥控帧没有此段。
5) CRC段(Cyclic Redundancy Check Field)
检查帧传输错误的帧,由15个位的CRC顺序和1个位的CRC界定符(用于分隔位)构成。CRC界定符恒为隐性。
这里CRC顺序是根据多项式生成的CRC值,CRC的计算范围包括帧起始,仲裁段,控制段和数据段。
6) ACK段(Acknowledge Field)
用来确认是否正常接收。由ACK槽(ACK Slot)和ACK界定符2个位构成。
7) 帧结束(End of Frame)
表示该帧的结束的段。由7个位的隐性位构成。
3.2 错误帧
用于在接收和发送消息时检测出错误通知错误的帧,错误帧由错误标志和错误界定符构成。
上图的错误标志包括主动错误标志(6个位的显性位)和被动错误标志(6个位的隐性位)两种。主动错误标志处于主动错误状态下的单元检测出错误时输出的错误标志。被动错误标志处于被动错误状态的单元检测出错误时输出的错误标志。错误界定符由8个位的隐性位构成。
注意上图0~6位的错误标志重叠,这段怎么确定呢?需先介绍2个概念:位填充和错误类型。
1)位填充(Bit Stuffing)
位填充是为防止突发错误而设定的功能。当同样的电平持续5位则添加一个位的反型数据位:
注意:位填充作用范围为SOF-CRC段机间的数据。
2)错误类型
针对上述位错误再做说明(引自[3]):
所谓“发出的电平与从总线上回读的电平不一致”,指的就是节点向总线发出隐性位,却从总线上回读到显性位或者节点向总线发出显性位,却从总线上回读到隐性位这两种情况。有三种例外情况不属于位错误:
在仲裁区,节点向总线发送隐性位却回读到显性位,不认为是位错误,这种情况表示该节点仲裁失败;
在ACK槽,节点向总线发送隐性位却回读到显性位,不认为是位错误,这种情况表示,该节点当前发送的这一帧报文至少被一个其它节点正确接收;
一个节点发送被动错误标志,该节点向总线发送连续六个隐性位(被动错误标志)却回读到显性位,不认为是位错误。因为被动错误标志是六个连续的隐性位,所以在总线上按照线与机制,有可能这六个连续隐性位被其它节点发送的显性电平覆盖。
3)错误处理
错误状态的种类有:主动错误状态,被动错误状态和总线关闭态3种状态。单元始终处于3种状态之一。
(1)主动错误状态:可以正常参加总线通信的状态,处于主动错误状态的单元检测出错误时,输出主动错误标志。
(2)被动错误状态:是易引起错误的状态。处于被动错误状态的单元虽能参加总线通信,但为不妨碍其他单元通信,接收时不能积极地发送错误通知;处于被动错误状态的单元即使检测出错误,而其它处于主动错误状态的单元如果没发现错误,整个总线也被认为是没有错误的。处于被动错误状态的单元检测出错误时,输出被动错误标志。另外,处于被动错误状态的单元在不能马上再次开始发送。在开始下次发送前,在间隔帧期间内必须插入“延迟传送”(8个位的隐性位)。
(3)总线关闭态是不能参加总线上通信的状态。信息的接收和发送均被禁止。
以上这些状态依靠发送错误计算和接收错误计数来管理,根据计数值决定进入何种状态。错误状态和计数值的关系如下表:
发送错误计数值和接收错误计数值根据一定的条件发送变化。错误计数值的变动条件如下表,一次数据的接收和发送可能同时满足多个条件。错误计数器在错误标志的第一个位出现的时间点上开始计数。
4)错误帧发送
检查到错误后,什么时候发送错误帧呢?按照CAN协议的规定:
- 位错误、填充错误、格式错误、ACK错误。在错误产生的那一位的下一位开始发送错误帧。
- CRC错误。紧随ACK界定符后的位发送错误帧。
具体来看一个例子:
- 1)发送节点Node_A发送一个显性位,但是却从总线上听到一个隐形位,于是Node_A节点就会检测到一个位错误;
- 2)Node_A检测到位错误之后,立即在下一位开始发送主动错误帧:6个连续显性位的主动错误标志+8个连续隐性位的错误界定符;
- 3)对应Node_A发出的主动错误标志,总线上电平为6个连续显性位;
- 4)接收节点Node_B和Node_C从总线上听到连续6个显性位,那么就会检测到一个填充错误,于是这两个节点都会发送主动错误帧;
- 5)对应Node_B和Node_C发出的主动错误标志,总线电平又有6个连续显性电平,对应Node_B和Node_C发出的错误界定符,总线电平有8个连续的隐性电平。
- 6)在间歇场之后,Node_A节点重新发送刚刚出错的报文。
在了解了错误帧的发送后,回到之前提到错误标志重叠部分是怎样形成的,再看一个例子:
在这个例子,我们知道位错误的错误标志与填充错误的错误标志重叠2位,剩下部分还有4位:
3.3 过载帧
过载帧是用于接收单元通知其尚未完成接收准备的帧。过载帧由过载标志(6个位的显性位)和过载界定符(8个位的隐性位)构成。过载界定符的构成与错误界定符的构成相同。过载帧的构成如下图所示。
对于过载帧的帧结构我们可以这样理解:接收节点达到接收极限时,就会发出过载帧到总线上,显然,过载标志的6个连续显性位会屏蔽掉总线上其它节点的发送,也就是说这个时候的接收节点通过发送过载帧的方式来破坏其它节点的发送,这样在接收节点发送过载帧期间,其它节点就不能成功发送报文,于是就相当于把其它节点的发送推迟了,也就是说接收节点在其发送过载帧的这段时间得以“休息”。
有3种情况会引起过载帧:
- 接收节点自身原因。接收节点由于某种原因需要延迟接收下一个数据帧或者遥控帧。
- 在帧间隔的间歇段的第一位和第二位检测到一个显性位(正常的间歇段都是隐性位)。帧间隔的间隔段本应是三个连续的隐性位,如果接收节点在间隔段检测到显性位,那么就意味着此时有报文发向接收节点,但这个时候是不应该有报文发来的,于是接收节点发送过载帧。
- CAN节点在错误界定符或过载界定符的第八位(最后一位)听到一个显性位0,节点会发送一个过载帧,且错误计数器不会增加。接收节点在错误界定符和过载界定符的最后一位听到显性位,也意味着有报文发向接收节点,但这个时候是不应该有报文发来的,于是接收节点发送过载帧。
3.4 帧间隔
帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。过载帧和错误帧前不能插入帧间隔。
针对上图,间隔为3个位的隐性位;总线空闲为隐性电平,无长度限制(0亦可);延迟传送为8个位的隐性位,只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。这里为什么需要延迟传送段呢?
首先,考虑主动错误状态的节点A,发送主动错误标志之后,随之就要重新发送刚刚发送失败的报文,但是为了间隔开与前面刚刚发送的错误帧,总线在错误帧之后就会插入3个隐形位的帧间隔,在这3个隐形位期间,其它的节点不足以判定总线空闲(需要连续11个隐性位才能判定),所以节点A仍然占据着总线的控制权,于是在帧间隔之后,节点A能够接着发送报文。现在节点A转入到被动错误状态了,说明它已经不是很可靠了,这个时候如果没有延迟传送段,在节点A发出被动错误标志之后,它仍然能够在3位的帧间隔之后立即重新发送报文,这是不符合我们对被动错误状态的处理要求的当然也是不符合CAN协议的,于是乎对于发送出被动错误标志的节点,总线在帧间隔中加入了8个连续隐性位的延迟传送段,这样的3+8=11个连续隐性位。就能让节点A在这个帧间隔期间失去对总线的控制权,从而优先保证其它正常(处于主动错误状态)节点能够使用总线,而不必等着一个已经不可靠的节点A占据总线。
到此CAN协议帧结构就基本介绍完了,下面综上所述来分析下具体的总线仲裁:
第4部分 总线仲裁
基于上节的仲裁段和控制段,这里主要考虑几种情况的仲裁:
假设一条CAN总线上有两个节点Node_A和Node_B。在总线空闲时,总线上为隐性电平,就在这个时候Node_A 和 Node_B 这两个节点同时向总线上发送数据,如下图,其中,Tx表示发送,Rx表示接收,也就是说每个节点都有发送与接收。
当作为发送方的节点会去接收自己发送的内容进行检查,即回读机制(节点在向总线上发送报文的过程中,同时也对总线上的二进制位进行“回读”,对比该节点发出的二进制位与总线上当前的二进制位是否一致,就可节点数据是否被正确接收。)
情况1:仲裁在前11位ID就结束 ,如上图。从D28-D18,采用线与机制,逐位进行比较,一旦某位出现不同,上图的ID25,则显性位覆盖隐性位,仲裁结束,显性位的对应节点胜出,上图的Node_A。
情况2:仲裁在前11位ID未结束,即说明前11位ID相同在这种情况下,我们就需要回顾一下前面的一个表:
根据这个表,我们可以进一步分为4种情况:
- 标准格式的数据帧与遥控帧,看RTR位,数据帧的RTR位恒为显性,遥控帧的RTR位恒为隐性。故前11位ID号相同时,标准数据帧优先级高于标准遥控帧。
- 扩展格式的数据帧与遥控帧,在前11位ID和后18位ID全相同的情况,与上条一致。
- 数据帧的标准格式与扩展格式,比较标准格式的RTR位与扩展格式的SRR位,标准格式的RTR位恒为显性,扩展格式的SRR位恒为隐性。故前11位ID号相同时,标准数据帧优先级高于扩展数据帧。
- 遥控帧的标准格式与扩展格式,看IDE位,扩展格式的IDE位恒为隐性,标准格式的IDE位在控制段,恒为显性。故前11位ID号相同时,标准遥控帧优先级高于扩展遥控帧。
通过上述分析,我们可以知道在前11位ID号相同时,根据协议设定的RTR, SRR, IDE,就可以保证如下:
- RTR:保证数据帧优先级高于遥控帧;
- SRR :保证标准数据帧的优先级高于扩展数据帧;
- IDE :保证标准遥控帧的优先级高于扩展遥控帧。
第5部分 报文过滤
在CAN总线中没有地址的概念,CAN总线是通过报文ID来实现收发数据的。CAN节点上都会有一个验收滤波ID表,其位于CAN节点的验收滤波器中,如果总线上的报文的ID号在某个节点的验收滤波ID表中,那么这一帧报文就能通过该节点验收滤波器的验收,该节点就会接收这一帧报文。假设有设置:
可看报文过滤过程如下图示意:
第6部分 数据传输同步
6.1 位速率概念
位速率(也叫做比特率)表示的是单位时间内,总线上传输的信息量,即每秒能够传输的二进制位的数量,R=1/T ,单位是bit per second。比如比特率为8bit/s,意思为一秒传输了8bit,包含了8个二进制事件的信息量。注意位速率与波特率不是同一概念。
摘自:https://zhuanlan.zhihu.com/p/103511011 实际传输中,传输速率以每秒发送的符号(baud)数量进行计算,即波特率。 当一个符号只包含两种可能,即一个事件两种可能,那么此时1baud=1bit。此时波特率等于比特率。 一个符号也有可能包含多个可能,例2中,一个符号中包含四个电平,那么接受端的一个事件,有了abcd四种可能,那么1baud=2bit。此时波特率为比特率的两倍。
6.2 位时序
第3部分讲到帧结构,我们知道每一帧数据(即一个完整的数据帧)有很多位组成,当发送方发送一帧数据到总线时,接收方怎么准确接收到这帧数据呢?实际采用逐位逐位地接收数据。
具体来说,将一个位分为4段,如上图所示。这些段又由可称为Time Quantum(以下称为Tq)的最小时间单位构成。1位分为4个段,每个段又由若干个Tq构成,这称为位时序。1位由多少个Tq构成,每个段又由多少个Tq构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。各段的作用和Tq数如下表:
所谓采样点是读取总线电平,并将读到的电平作为位值的点,位置在PBS1结束处。
CAN协议的通信方法为NRZ方式,各个位的开头或者结尾都没有附加同步信号。发送单元以与位时序同步的方式开始发送数据。另外,接收单元根据总线上电平的变化进行同步并进行接收工作。但是,发送单元和接收单元存在的时钟频率误差及传输路径上的(电缆/驱动器等)相位延迟会引起同步偏差,因此接收单元通过硬件同步或者再同步的方法调整时序进行接收。6.3 硬同步
在总线空闲状态,接收节点检测出帧起始(SOF位)时,会调整当前位的同步段,调整宽度不限。如下图假设这时检测的时SOF位。
那么硬同步简单说就是接收节点直接与发送节点同步(真有硬的味道),如下:
6.4 再同步
接收节点检测出除SOF位以外的其他位时,进行的同步调整。重同步会通过加长PSB1段,或缩短PBS2段来调整同步,以保证采样点的准确。
对于再同步,需一个概念SJW(同步跳转宽度),是指PSB1和PSB2再同步时允许跳转的最大宽度,其必须满足以下2个条件:
- SJW必须小于PBS1和PBS2的最小值;
- SJW最大值不能超过4。
下面看一下再同步的两种情况:
情况1: PSB1段加长(发的晚,收的早)
情况2:PSB2段缩短(发的早,收的晚)
6.5 调整同步的规则
硬件同步和再同步遵从如下规则。
- 1 个位中只进行一次同步调整。
- 只有当上次采样点的总线值和边沿后的总线值不同时,该边沿才能用于调整同步。
- 在总线空闲且存在隐性电平到显性电平的边沿时,则一定要进行硬件同步。
- 在总线非空闲时检测到的隐性电平到显性电平的边沿如果满足条件(1)和(2),将进行再同步。
但还要满足下面条件。 - 发送单元观测到自身输出的显性电平有延迟时不进行再同步。
- 发送单元在帧起始到仲裁段有多个单元同时发送的情况下,对延迟边沿不进行再同步。