CAN通信 :协议介绍

Posted 码好每一天

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CAN通信 :协议介绍相关的知识,希望对你有一定的参考价值。

  CAN 协议经 ISO 标准化后有 ISO11898 标准和 ISO11519-2 标准两种。ISO11898 和 ISO11519-2 标准对于数据链路层的定义相同,但物理层不同。

   在阅读完上文后,对CAN总线中的一个极其重要的知识点需要搞明白:回读机制。
  指的是节点在向总线上发送报文的过程中,同时也对总线上的二进制位进行“回读”。通过这种机制,节点就可以判断出本节点发出的二进制位与总线上当前的二进制位是否一致。

1.1 帧的种类

帧类型帧用途
数据帧 用于发送单元向接收单元传送数据的帧。
遥控帧 用于接收单元向具有相同 ID 的发送单元请求数据的帧。
错误帧 用于当检测出错误时向其它单元通知错误的帧。
过载帧 用于接收单元通知其尚未做好接收准备的帧。
帧间隔 用于将数据帧及遥控帧与前面的帧分离开来的帧

  另外,数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有 11 个位的标识符(Identifier: 以下称 ID),扩展格式有 29 个位的 ID。

1.1.1 数据帧

 数据帧标准格式各个位的介绍
 SOF:联系前文可知,当数据帧发出第一位时(0为显性电位),总线就由空闲状态转为传输状态,同一时间只能允许一个节点传输数据。
 Identify:接下来的仲裁段有11位,即本数据帧的 ID 信息,决定着数据帧发送的优先级,也决定着其它设备是否会接收这个数据帧,禁止高 7 位都为隐性(禁止设定:ID=1111111XXXX), ID 信息的作用:① 如果同时有多个节点发送数据时,作为优先级依据(仲裁机制);② 目标节点通过 ID 信息来接受数据(验收滤波技术)。这些将在下文提出。
 RTR:(Remote Transmission Request BIT) 位用于标识是否是远程帧(0,数据帧;1,远程帧),在数据帧里这一位为显性(逻辑 0)。
 IDE:(Identifier Extension Bit),是用于区分标准格式与扩展格式,在标准格式中 IDE 位为显性,在扩展格式里 IDE 位为隐性。
 r0:保留位,必须以显性电平发送。
 DLC:由 4 位组成,MSB 先行(高位先行),它的二进制编码用于表示本报文中的数据段含有多少个字节,DLC 段表示的数字为0到8,若接收方接收到 9~15 的时候并不认为是错误。
 Data:数据帧的核心内容,它由 0~8 个字节(0 ~ 64位)组成,MSB 先行。
 CRC:该段用于检查帧传输错误,发送方以一定的方法计算包括:帧起始、仲裁段、控制段、数据段;接收方以同样的算法计算 CRC 值并进行比较,如果不同则会向发送端反馈出错信息,重新发送;计算和出错处理一般由 CAN 控制器硬件完成或由软件控制最大重发数。该段由 15 个位的 CRC 顺序和 1 个位的 CRC 界定符(用于分隔的位)组成,它为隐性位,主要作用是把CRC 校验码与后面的 ACK 段间隔起来。
 ACK:由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位组成,在 ACK 槽位中,发送端发送的为隐性位,而接收端则在这一位中发送显性位以示应答。在 ACK 槽和帧结束之间由 ACK 界定符间隔开,为隐性位。(发送 ACK/返回 ACK这个过程使用到回读机制,即发送方先在 ACK 槽发送隐性位后,回读到的总线上的电平为显性0,发送方才知道它发送成功了,不用重发)
 EOF:由发送端发送 7 个隐性位表示结束。

在数据帧的拓展格式中,与标准格式不同处在于:

仲裁段为 29 位;
多出的SRR 位(Substitute Remote Request BIT),用于替代标准格式中的 RTR 位。SRR 位为隐性位,由于 RTR 在数据帧为显性位,所以在两个 ID 相同的标准格式报文与扩展格式报文中,标准格式的优先级较高;
控制段中的 r1 和 r0 一样都为保留位,默认设置为显性位;
扩展格式的 ID 有 29 个位。基本 ID 从 ID28 到 ID18,扩展 ID 由 ID17 到 ID0 表示。基本 ID 和标准格式的 ID 相同。禁止高 7 位都为隐性。(禁止设定:基本 ID=1111111XXXX)

1.1.2 遥控帧

  接收单元向发送单元请求发送数据所用的帧。遥控帧由 6 个段组成。遥控帧没有数据帧的数据段。举个例子,车钥匙需要知道车门的状态,一个远程帧过去,车门把自己的状态发回来了。

 

  遥控帧与数据帧的不同之处:

  • 遥控帧的 RTR 位为隐性位,没有数据段;
  • 没有数据段的数据帧和遥控帧可通过 RTR 位区别开来;
  • 遥控帧的数据长度码以所请求数据帧的数据长度码表示;

1.1.3 错误帧

  用于在接收和发送消息时检测出错误通知错误的帧。错误帧由错误标志和错误界定符构成。

 

 (1) 错误标志
  错误标志包括主动错误标志和被动错误标志两种。
    ① 主动错误标志:6 个位的显性位。
    ② 被动错误标志:6 个位的隐性位。
 (2) 错误界定符
  错误界定符由 8 个位的隐性位构成。

 (3)错误标志之后还有0~6个错误标志重叠部分
  处于主动错误状态的节点检测到错误时会发送主动错误标志,6个连续显性位会违反位填充规则和位场的固定形式,进而造成其它节点也检测到错误并发送错误标志。所有节点所发送的显性序列叠加组成错误标志重叠部分,错误标志重叠部分的长度在6-12个显性位之间。

对主动错误和被动错误的通俗理解:
 
  首先建议把广泛使用的“主动错误”和“被动错误”概念换成“主动报错”和“被动报错”。
 
  1.主动报错站点
  只要检查到错误,它立即“主动地”发出错标识。所谓“出错标识“,它本身就是一个“错误的位序列”(连续的6 个显性位,不满足CAN协议的“最多5个连续的同性位”要求),
目的是“主动地”告诉大家:即使你们没有发现“刚才我已发现”的错误,现在我“以身作则”出错啦
!你们该看到这个错误了吧!     2.被动报错站点   如果检查到错误,它只能干瞪眼“被动地”等别人(主动报错站点)报错,等待的时候它可不能去动总线,直到识别出由主动报错站点发出的“错误的位序列”,
它才松了一口气:有人正式报错了
!然后他就可以去竞争总线,该干啥干啥。

1.1.4 过载帧

  过载帧是接收节点向总线上其它节点报告自身接收能力达到极限的帧,可以理解为:接收节点Node_A接收报文的能力达到极限了,于是Node_A就会发出过载帧来告诉总线上的其它节点(包括发送节点),我接收节点Node_A已经没有能力处理你们发来的报文了。过载帧由过载标志和过载界定符构成。

   (1) 过载标志
  6 个位的显性位。
  过载标志的构成与主动错误标志的构成相同。
 (2) 过载界定符
  8 个位的隐性位。
  过载界定符的构成与错误界定符的构成相同。

1.1.5 帧间隔

  帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。过载帧和错误帧前不能插入帧间隔。

 

 

(1) 间隔
  3 个位的隐性位。
(2) 总线空闲
  隐性电平,无长度限制(0 亦可)。
  本状态下,可视为总线空闲,要发送的单元可开始访问总线。
 (3) 延迟传送(发送暂时停止)
  8 个位的隐性位。
  只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。

1.2 位填充

  为防止突发错误而设定,CAN协议中规定,当相同极性的电平持续五位时,则添加一个极性相反的位。填充位的添加和删除是由发送节点和接收节点完成的,CAN-BUS只负责传输,不会操纵信号。

 

对于发送节点而言:
在发送数据帧和遥控帧时,对于SOF~CRC(除去CRC界定符) 之间的位流,相同极性的电平如果持续5位,那么在下一个位插入一个与之前5位反型的电平;
对于接收节点而言:
在接收数据帧和遥控帧时,对于SOF~CRC(除去CRC界定符)之间的位流,相同极性的电平如果持续5位,那么需要删除下一位再接收。如果这个第 6 个位的电平与前 5 位相同,将被视为错误并发送错误帧

1.3 错误的种类

 

  位错误(Bit Check Error):节点将自己发送到总线上的电平与同时从总线上回读到的电平进行比较,如果发现二者不一致,那么这个节点就会检测出一个位错误。

有三种例外情况不属于位错误:

  ① 在仲裁区,节点向总线发送隐性位却回读到显性位,不认为是位错误,这种情况表示该节点仲裁失败;

  ② 在ACK槽,节点向总线发送隐性位却回读到显性位,不认为是位错误,这种情况表示,该节点当前发送的这一帧报文至少被一个其它节点正确接收;

  ③ 该节点发送被动错误标志,节点Node_A向总线发送连续六个隐性位(被动错误标志)却回读到显性位,不认为是位错误。因为被动错误标志是六个连续的隐性位,所以在总线上按照线与机制,有可能这六个连续隐性位被其它节点发送的显性电平“吃掉”;

ACK错误(Acknowledgment Error):按照CAN协议的规定,在一帧报文(数据帧或者遥控帧)发出之后,如果接收节点Node_B成功接收了该帧报文,那么接收节点Node_B就要在该帧报文ACK槽对应的时间段内向总线上发送一个显性位来应答发送节点Node_A。这样发送节点Node_A就会在ACK槽时间段内从总线上回读到一个显性位。

  当发送节点Node_A在ACK槽时间段内没有回读到显性位,那么发送节点Node_A就会检测到一个ACK应答错误。这表示没有一个节点成功接收该帧报文。

填充错误(Fill Error):帧起始到CRC之间,接收节点检测到有6个连续相同的位电平时,也就是违反5位相同位插入1位相反位的“位填充”原则。

 CRC错误:发送节点Node_A在发送数据帧或者遥控帧时,会计算出该帧报文的CRC序列。接收节点Node_B在接收报文时也会执行相同的CRC算法,如果接收节点Node_B计算出的CRC序列值与发送节点Node_A发来的CRC序列值不一致,那么接收节点就检测到一个CRC错误。

格式错误:在一帧报文发送时,如果在必须发送预定值的区域内检测到了非法值,即与任何一种帧格式都不符;CAN报文中,有预定值的区域包括:

  • 数据帧和遥控帧的CRC界定符、ACK界定符、EOF;
  • 错误帧界定符
  • 过载帧界定符

1.4 错误通知

1.4.1 节点错误状态

对于错误界定,节点存在如下三种状态:

主动错误: 错误标志由6个连续的显性位组成(这种连续的6个显性位与常规的填充位和其它帧固定格式不相同,正因为如此,硬件才容易区别)

被动错误 :被动错误标志由6个连续的隐性位组成,当发送结束后,处于被动错误状态的节点在下一次再次发送时之前需要等待一些额外时间。

总线关闭: 处于总线关闭状态的节点不允许发送和接收任何形式的帧报文。且只能通过用户请求进行恢复。

1.4.2 错误状态的转换

  一个CAN节点在什么情况下处于主动错误状态,什么情况下处于被动错误状态呢?

  在CAN节点内,有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)

  错误界定并非是依据错误的类型去界定CAN节点的错误状态,而是依据错误计数器【TEC/REC】的值来界定CAN节点的错误状态;当该节点检测到错误后,内部REC/TEC计数器会相应的增加,基于REC/TEC的值判定节点状态。

 

  需要注意的是:这两个计数器计得不是收发报文的数量,也不是收发错误帧的数量。TEC和RCE计数值的变化,是根据下表的规定来进行的。

 

  节点错误状态的转换就是一个 “量变”到“质变” 的过程:

 

主动错误状态:【REC<127 且TEC<127】
  初步可判定该节点相对稳定可靠,该错误计数很可能是由于某个节点异常导致的,那么其他节点很可能也会触发该错误,那么允许该节点破坏CAN总线的异常报文并告知其他节点;
  节点检测到一个错误就会发送带有主动错误标志的错误帧,因为主动错误标志是连续六个显性位,所以这个时候主动错误标志将会“覆盖”掉总线上其它节点的发送,而之前在CAN总线上传输的报文就被这“六个连续显性位”破坏掉了。

  如果发出主动错误帧的节点是发送节点,这个情况下就相当于:刚刚发送的那一帧报文我发错了,现在我破坏掉它(发送主动错误帧),你们不管收到什么都不算数;
  
  如果发出主动错误帧的节点是接收节点,这个情况就相当于:刚刚我收报文的时候发现了错误,不管你们有没有发现这个错误,我现在主动站出来告诉大家这个错误,并把这一帧报文破坏掉(发送主动错误帧),刚才你们收到的东西不管对错都不算数了。

被动错误状态:【REC>128 或TEC>128】
  节点发送错误帧的次数较多,初步可判定该节点相对不可靠,该错误计数很可能是由于自身节点问题导致,即该错误很可能仅有该节点才有,对于其他节点而言是可以正常交互的,总线不信任该节点提供的错误标识,将不允许破坏总线数据,那么允许该节点发送错误帧“6个连续隐性位”至CAN总线,仅告知其他节点异常;

  如果发出被动错误帧的节点为报文的发送节点,那么在发送被动错误帧之后,刚刚正在发送的报文被破坏,并且该节点不能在错误帧之后随着连续发送刚刚发送失败的那个报文。随之而来的是帧间隔,并且连带着8位隐性位的 “延迟传送” 段;这样总线电平就呈现出连续11位隐性位,总线上的其它节点就能判定总线处于空闲状态,就能参与总线竞争。
  
  此时如果该节点能够竞争成功,那么它就能接着发送,如果竞争不能成功,那么就接着等待下一次竞争。这种机制的目的正是为了让其它正常节点(处于主动错误)优先使用总线。

总线关闭状态:【TEC>255】
  一个处于被动错误状态的节点,仍然多次发送被动错误帧,使该节点转为总线关闭态;
  该节点不能向总线上发送报文,也不能从总线上接收报文,整个节点脱离总线。等到检测到128次11个连续的隐性位时,TEC和REC置0,重新回到主动错误状态。

由于存在实现方式的不同,CAN总线关闭状态存在只允许用户请求恢复和检测到128个11位连续的隐性位时自恢复两种不同的恢复形式。

  如果总线上只有一个节点,该节点发送数据帧后得不到应答,TEC最大只能计数到128,即这种情况下节点只会进入被动错误状态而不会进入总线关闭状态。

 

1.4.3 错误帧的发送

 按照CAN协议的规定:
  发生位错误、填充错误、格式错误、ACK错误时,则在错误产生的那一位的下一位开始发送错误帧。
  发生CRC错误时,紧随ACK界定符后的位发送错误帧。

  错误帧发送完成后,总线空闲时自动重发出错的数据帧。

 

1.4.4 仲裁机制与位时序

仲裁存在于当同时有多个节点竞争总线发送权时,关键词是同时,比如节点1和节点2两者同时向总线发送一个位,是同时发送的,总线只是导线(理解成自带线与功能),如果节点1发送的是1,节点2发送的是0,线与后总线的状态则为0;  与此同时,这里运用到回读机制,即:节点发送位的同时会回读总线的状态并与自身相比较,可知节点1本身状态与总线状态一致,则节点1仲裁胜利。(可查阅【CAN通信(一) 3.2.3】)

  理解位时序,重点在于同步,分为硬同步和重新同步,在重新同步中,通过设置SJW来调整PBS段的长度(PBS1增长,PBS2缩短),以达到调整一个位中Tq的个数,即长度。(可查阅【CAN通信(一) 3.2.4】)

 关于波特率的计算:
  总线上的各个通讯节点只要约定好 1 个 Tq 的时间长度以及每一个数据位占据多少个Tq,就可以确定 CAN 通讯的波特率。例如,假设1Tq=1us,而每个数据位由 19 个 Tq 组成,则传输一位数据需要时间 T(1bit) =19us,从而每秒可以传输的数据位个数为:1x10^6/19 = 52631.6 (bps),这个每秒可传输的数据位的个数即为通讯中的波特率。

1.4.5 举个栗子

 【位错误】举例(情况1):

  • 设总线上所有节点处于主动错误状态;
  • 当一个发送节点监控到总线上的位数值与发送的位数值不一致时,检测为位错误,并发送主动错误标志(6个连续的显性位);
  • 接收节点接收到发送节点发送的6个连续的显性位时,会检测为位填充错误,也会发送主动错误标志;
  • 发送节点发送完主动错误标志后,开始监控总线是否为隐性位,当总线为隐性位时,开始发送错误界定符(8个连续的隐性位);
  • 当接收节点发送完主动错误标志后,开始向总线发送错误界定符; 等待错误帧发送完成,总线空闲后,发送节点重新发送出错的报文.
由于发送节点发送6个连续的显性位会破坏位填充规则,触发接收节点发送主动错误标志,发送节点和接收节点的结合是形成错误标志叠加部分的原因。

 

 【位错误】举例(情况2):

 
  • 假设发送节点处于被动错误状态,接收节点处于主动错误状态;
  • 当发送节点监控到总线上的位数值与发送的位数值不一致时,检测为位错误,并发送被动错误标志(6个连续的隐性位);
  • 接收节点接收到发送节点发送的6个连续的隐性位时,会检测为位填充错误,并会发送主动错误标志;
  • 发送节点发送完被动错误标志后,开始监控总线是否为隐性位,当总线为隐性位时,开始发送错误界定符(8个连续的隐性位);
  • 接收节点发送完主动错误标志后,开始监控总线是否为隐性位,当总线为隐性位时,开始发送错误界定符(8个连续的隐性位);

 

1.5 CAN的特性总结

1) 多主控制
  在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。

 2) 系统的柔软性
  与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。

 3) 通信速度较快,通信距离远。最高 1Mbps(距离小于 40M),最远可达 10KM(速率低于 5Kbps)。

 4) 具有错误检测、错误通知和错误恢复功能。所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。

 5) 故障封闭功能。CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。

 6) 连接节点多。CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。

CAN总线协议与帧格式的构成


1、CAN总线的介绍

CAN总线简称 — 控制器局域网络,由德国BOSCH公司开发,是一种串行的差分总线,并且这种差分总线只传递数据信息。

CAN总线已经是国际上的一种通信标准(ISO11519),它具有高可靠性、良好的错误检测能力、总线仲裁等优良特点,被广泛应用在汽车控制系统、环境恶劣场所、电磁辐射强、干扰性大等场所中。

CAN是一种异步的通信方式,它的通讯不需要时钟进行同步,线路上只有CAN_H、CAN_L两根通信线,数据以差分信号的方式进行传输。

2、CAN的通信网络

2.1、闭环总线网络

CAN的闭环通信网络如下:

CAN总线协议与帧格式的构成_通信协议

闭环通信网络的特点如下:

1)遵照标准为 ISO11898;

2)最高速度可达1Mbps,总线最大长度为40m;

3)总线的两端要求各有一个120欧姆的电阻。

2.2、开环总线网络

CAN的开环通信网络如下:

CAN总线协议与帧格式的构成_通信协议_02

开环通信网络的特点如下:

1)遵循ISO11519-2标准;

2)最高的通信速度为125Kbps,是一种低速通信的连接方式;

3)最大的通信距离可达1Km;

4)两根总线独立,且要求每根总线上要串联一个2.2K欧姆的电阻。

3、CAN的通信速率

按照 ISO11898 标准中所规定的,CAN总线的通讯波特率最高为 1Mbps。大多数项目常用的CAN总线波特率有125Kbits/s,250Kbits/s,500Kbits/s,1MKbits/s等。

CAN总线的传输距离与速率的对照表:

CAN总线协议与帧格式的构成_通信协议_03

4、CAN的差分信号

CAN总线的数据传输使用的是差分信号的方式进行的。这两根线中的信号振幅相等,相位相反,逻辑1 和 逻辑0 通过两根信号线的电压差值表示出来。

在CAN的应用中,逻辑1也称为隐性电平,逻辑0也称为显性电平。

比如,以高速CAN为例:

逻辑1:CAN_H、CAN_L的电压均为2.5V,电压差为VH - VL = 0V。

逻辑0:CAN_H电压为3.5V,CAN_L电压为1.5V,电压差为 VH - VL = 2V。

示意图如下:

CAN总线协议与帧格式的构成_通信协议_04

两根信号线的电压值根据标准的不同是有所差异的,如下表所示:

CAN总线协议与帧格式的构成_通信协议_05

注意:CAN总线上,在同一个时刻只能处于隐性电平(逻辑1)或者显性电平(逻辑0)中的一个状态,且显性电平相比隐性电平具有优先权。比如:CAN总线上有两个节点,在同一个时刻,一个输出隐性电平,一个输出显性电平,这个时候总线上是显性电平状态。

5、CAN的位同步 & 数据同步

5.1、CAN 的位同步

由于CAN总线是异步通信的,它不像IIC、SPI这种同步通行方式一样具有同步时钟,所以总线网络中的节点就需要约定好通信的波特率。

在CAN中使用了 “位同步” 的方式来抵抗干扰、吸收误差,实现对总线电平信号的正常采样,确保通讯正常进行。

同时,这个位同步也是用于调节通信过程中的采样点的。

CAN实现位同步的过程中,会把每一个数据位的时序进行分解,会分解成SS段、PTS段、PBS1段、PBS2段,这四个段加起来就是一个CAN的数据位长度。分解后的最小时间单位为Tq。它们分别如下:

同步段(SS段):该段的大小固定为1Tq。

当总线上的节点在SS段的范围内检测到总线上信号发生了跳变,就认为该节点与总线的时序是同步的。当节点与总线同步时,在采样点采集到的总线电平即可以确认为该位的电平。

传播时间段(PTS段):该段的大小为 1Tq ~ 8Tq。

这个时间段是用于补偿网络的物理延时时间。是总线上输入比较器延时和输出驱动器延时总和的两倍。

相位缓冲段1(PBS1):该段的大小为 1Tq ~ 8Tq。

主要用来补偿边沿阶段的误差,它的时间长度在重新同步的时候可以加长。

相位缓冲段2(PBS2):该段的大小为 1Tq ~ 8Tq。

是用来补偿边沿阶段误差的,它的时间长度在重新同步时可以缩短。

为了方便说明,我就直接用高低电平表示CAN的逻辑1 和 逻辑0 信号,示意图如下:

CAN总线协议与帧格式的构成_通信协议_06

图:CAN数据位分解图

上图是对CAN通信中的逻辑0进行分解的说明示意图。图中就表示每个数据位的长度为19Tq(SS 段占 1Tq,PTS 段占 6Tq,PBS1 段占 5Tq,PBS2 段占 7Tq),信号的采样点位于 PBS1 段与 PBS2 段之间,通过控制各段的长度,可以改变采样点的位置。

5.2、CAN 的数据同步

CAN的数据同步使用到SS段、PTS段、PBS1段、PBS2段,并且数据的同步分为硬同步、重新同步。

(1)硬同步

CAN节点希望通过总线发送数据时,会发送一个由高变低的下降沿作为通讯的起始信号;而节点不发送数据时会时刻检测总线上的信号。

一个硬同步的过程如下图示例:

CAN总线协议与帧格式的构成_通信协议_07

从上图中可以看到当总线上出现了帧起始信号时,某一个节点检测到总线的帧起始信号不在该节点内部时序的 SS 段范围,所以就可以判断它自己的内部时序与总线不同步,因而这种状态下的采样点采集得的数据是不正确的。所以节点以硬同步的方式调整,把自己的位时序中的 SS 段平移至总线出现下降沿的部分,获得同步,同步后采样点就可以采集得正确数据了。

(2)重新同步

硬同步是存在帧起始信号时才起作用,但是假如是一帧很长的数据,这一长串数据内不再出现帧起始信号,那么在节点信号与总线信号出现相位偏移时,用硬同步方式就行不通了。

所以就有了重新同步的方式,这种方式利用普通数据位的电平的高至低的跳变沿来同步同样都是在 SS 段中进行检测,从而实现同步的目的。

注意:同步的目的都是为了能在节点内的 SS 段把跳变沿包含起来。

重新同步可以细分为两种同步方式:相位超前重新同步和相位滞后重新同步。这两种方式以总线跳变沿与 SS 段的相对位置进行区分的。

1)相位超前重新同步

如下图所示:

CAN总线协议与帧格式的构成_通信协议_08

上图中可以看到,节点的SS段相对于总线的边沿跳变往前了两个Tq的时间,即节点的时序比它检测的总线时序相对超前了2Tq。

解决这个问题可以在下一个位时序中的PBS1段增加2Tq的时间长度,使得节点与总线时序重新同步,如下图:

CAN总线协议与帧格式的构成_通信协议_09

2)相位滞后重新同步

如下图所示:

CAN总线协议与帧格式的构成_通信协议_10

上图中可以看到,节点的SS段相对于总线的边沿跳变延迟了两个Tq的时间,即节点的时序比它检测的总线时序相对落后了2Tq。

解决这个问题可以在下一个位时序中的PBS2段减少2Tq的时间长度,使得节点与总线时序重新同步,如下图:

CAN总线协议与帧格式的构成_通信协议_11

6、CAN的波特率

在CAN总线的通讯中,各个通讯的节点只要确定了1个Tq的时间长度以及每个数据位占多少个Tq,由此就可以算出CAN通讯的波特率。

在CAN中,波特率也就只是约定了每个数据位的长度而已。

比如,上图(图:CAN数据位分解图)中,假设1Tq = 1us,每个数据位由19个Tq组成,则每传输1Bit数据需要的时间为:19Tq = 19us。

则一秒可以传输的数据位(bit)为:

1000000 / 19 = 52.6316K(bps)

注意:波特率指的是每秒可以传输的数据位(bit)的个数。

7、CAN的帧种类和用途

CAN的帧种类有如下几种:

CAN总线协议与帧格式的构成_通信协议_12


特别地,数据帧和遥控帧有标准格式和扩展格式两种格式。

标准格式 — 有 11 个位的标识符 ID

扩展格式 — 有 29 个位的 标识符 ID


7.1、CAN总线的数据帧

数据帧一般由 7 个段构成,即:

CAN总线协议与帧格式的构成_通信协议_13


这几个段的作用如下:

1) 帧起始。表示数据帧开始的段。

2) 仲裁段。表示该帧优先级的段,即ID信息。

3) 控制段。表示数据的字节数及保留位的段。

4) 数据段。数据的内容,一帧可发送 0~8 个字节的数据。

5) CRC 段。检查帧的传输错误的段。

6) ACK 段。表示确认正常接收的段。

7) 帧结束。表示数据帧结束的段。

CAN的数据帧有标准格式和扩展格式两种,这两者不同的地方如下图如下:

CAN总线协议与帧格式的构成_通信协议_14

数据帧的标准格式和扩展格式两者的不同之处主要在于仲裁段中,控制段中有细微的不同。

1)标准格式的ID是11位。

从ID28到ID18一次发送,禁止高7位都为隐形(禁止ID=1111111XXXX)。

2)扩展格式的ID有29个位。

基本ID从ID28到ID18,扩展ID由ID17到ID0表示。基本ID和标准格式的ID相同。

RTR位:帧选择位

0:数据帧 1:远程帧

IDE位:

0:标准标识符 1:扩展标识符

SRR位:

远程请求位,为隐形位,代替了标准帧中的RTR位。

r0、r1位:

保留位,发送时必须全部是显性电平,但是接收时可以是显性、隐形、任意组合的电平。

7.1.1、起始帧

CAN的数据帧和远程帧开始发送时,是需要发送一个开始的标志的,称之为帧起始。它是一个显性位(逻辑0)。

一个CAN节点只有在总线处于空闲状态时才可以发送起始帧。

7.1.2、仲裁段

起始帧发送完成之后,紧接着发送出的就是仲裁段的数据。

CAN2.0A的仲裁场一共有12位,如下图所示。

CAN总线协议与帧格式的构成_通信协议_15

在这12位中,前11位表示的是11位标识符,第12位是远程发送请求RTR。在数据帧中RTR为显性,在远程帧中RTR为隐性。如果相同标识符的数据帧与远程帧发生冲突,数据帧优先。

CAN2.0B的仲裁场一共有32位,它在CAN2.0A的基础上,将CAN ID扩展到了29位,并且向CAN2.0A兼容,如下图所示。

CAN总线协议与帧格式的构成_通信协议_16

7.1.3、控制段

仲裁之段后便是控制场。控制场的头两位为保留位(R1、R0),为隐性。

后面是数据长度代码DLC(Data Length Code)。数据长度代码指示了数据场中有效的字节个数。DLC的长度为4位二进制数,虽然可以最大范围可以表示到0~15,但是由于CAN总线的数据域长度最大为8个字节,所以DLC的大小可以认为是最大为8。

控制场示意图如下:

CAN总线协议与帧格式的构成_通信协议_17

详细示意图如下:

CAN总线协议与帧格式的构成_通信协议_18

7.1.4、数据段

控制场传输完成之后,紧接着传输的就是数据场了,数据场里面传输的就是我们想要传输的数据,长度为8个字节,如下图所示。

CAN总线协议与帧格式的构成_通信协议_19

详细示意图如下:

CAN总线协议与帧格式的构成_通信协议_20

7.1.5、CRC段

CAN数据每次发送的时候,都会将CAN数据帧里面的有效数据进行CRC校验,并且将最终生成的CRC信息一起包含在数据帧中的CRC域内进行发送。接收端接收到一帧CAN总线数据后,会将接收到的数据进行CRC计算,并且同发出端的CRC校验码进行比较,如果相同,则代表当前接收到的信息是正确的。

CRC段的示意如下:

CAN总线协议与帧格式的构成_通信协议_21

CRC校验域的格式如下图所示。

CAN总线协议与帧格式的构成_通信协议_22

在经典CAN中,使用15位CRC。在硬件可使用移位和异或运算完成CRC的计算。CAN总线中使用的几种CRC生成多项式公式如下图所示。

CAN总线协议与帧格式的构成_通信协议_23


7.1.6、应答段

CAN总线的应答场长度为2个位,包含应答间隙(ACK SLOT)和应答界定符(ACK DELIMITER)。

在应答场里,发送站发送两个“隐性”位。当接收器正确地接收到有效的报文,接收器就会在应答间隙(ACK SLOT)期间(发送ACK信号)向发送器发送一“显性”的位以示应答。

应答间隙:所有接收到匹配CRC序列(CRC SEQUENCE)的站会在应答间隙(ACK SLOT)期间用以“显性”的位写入发送器的“隐性”位来作出回答。

ACK界定符:ACK界定符是ACK场的第二个位,并且是一个必须为“隐性”的位。因此,应答间隙(ACK SLOT)被两个“隐性”的位所包围,也就是CRC界定符(CRC DELIMITER)和ACK界定符(ACK DELIMITER)。

CAN总线的应答场如下图所示:

CAN总线协议与帧格式的构成_通信协议_24

详细如下图所示:

CAN总线协议与帧格式的构成_通信协议_25

7.1.7、帧结束

应答段之后的7位数据是CAN总线的结束帧,是为7位连续的1(隐性电平),如下图所示。

CAN总线协议与帧格式的构成_通信协议_26

8、CAN通信的数据段示例

下图可以看到一个CAN数据帧排列的所有数据域。下图展示了一个完整的数据段的通信过程,如下图:

CAN总线协议与帧格式的构成_通信协议_27

9、STM32的CAN的配置示例

这里以STM32F407的CAN外设的配置为例。代码如下:

配置CAN1,并配置使用CAN1中断接收CAN消息:

 GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //使能CAN1时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA11,PA12

GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1); //GPIOA11复用为CAN1
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1); //GPIOA12复用为CAN1

CAN_InitStructure.CAN_TTCM = DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM = DISABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM = DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN_InitStructure.CAN_NART = ENABLE; //启动禁止自动重传,即不自动重传
CAN_InitStructure.CAN_RFLM = DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP = DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; //模式设置
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq; //Tbs2范围CAN_BS2_1tq ~CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler = 6; //分频系数(Fdiv)为brp+1 波特率=Fpclk1/((BS1+1+BS2+1+1)*Prescaler),即42M/((6+7+1)*6)=500Kbps
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1

CAN_FilterInitStructure.CAN_FilterNumber = 0; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; //32位
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; ////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; //32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; //过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure); //滤波器初始化

CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //FIFO0消息挂号中断允许.

NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);





CAN总线协议与帧格式的构成_通信协议_28

以上是关于CAN通信 :协议介绍的主要内容,如果未能解决你的问题,请参考以下文章

基于FPGA的CAN接口开发

基于FPGA的CAN接口开发

CAN总线协议与帧格式的构成

通信教程 | CAN总线协议基础原理

CAN通信协议

17 . CAN 通讯实验