上一篇文章讲了 CAN 总线的历史、标准、物理层,现在接着介绍 CAN 总线数据链路层,和 CAN 总线同步机制。本文转载于 知乎:一口气从零读懂 CAN 总线。
在 SPI 通信中,片选、时钟信号、数据输入及数据输出这四个信号都有单独的信号线。而 CAN 使用的是两条差分信号线,只能表达一个信号。简洁的物理层决定了 CAN 必然要配上一套更为复杂的协议。如何用一个信号通道实现同样甚至更强大的功能,答案就是对数据或操作命令进行打包。
安全敏感的应用(如汽车动力)对通信系统的可靠性要求很高。将总线能否正常工作归结到单一节点是非常危险的,比较合理的方案是对总线接入的去中心化,即每个节点都有接入总线的能力。这也是 CAN 总线采用多主控(Multi-Master)线性拓扑结构的原因。
在 CAN 总线上,每个节点都有往总线上发送消息的能力,而消息的发送不必遵从任何预先设定的时序,通信是事件驱动的。只有当有新的信息传递时,CAN 总线才处于忙碌的状态,这使得节点接入总线速度非常快。CAN 总线理论最高数据传输速率为 1 Mbps,对于异步事件反应迅速,基本对于 ms 级别的实时应用没有任何问题。
不同于其它类型的总线,CAN 总线不设定节点的地址,而是通过消息的标识符(Identifier)来区别消息。这种机制虽然会增加消息的复杂度(增加标识符),但是节点在此情况下可以无需了解其他节点的状况,而相互间独立工作。在总线上增加节点时仅需关注消息类型,而非系统上其他节点的状况。这种以消息标识符寻址的方式,让总线上增加节点变得更加灵活。
CAN 总线通信原理可简单描述为多路载波侦听 + 基于消息优先级的冲突检测和非破坏性的仲裁机制(CSMA/CD+AMP)。CSMA(Carrie Sense Multiple Access)指的是所有节点必须都等到总线处于空闲状态时才能往总线上发送消息;CD+AMP(Collision
Detection + Arbitration on Message Priority)指的是如果多个节点往总线上发送消息时,具备最高优先级的消息获得总线。
发送低优先级报文的节点退出仲裁后,在下次总线空闲时自动重发报文。
CAN 控制器大多具有根据 ID 过滤报文的功能,即只接收某些 ID 的报文。节点对接收到的报文进行过滤:比较消息 ID 与选择器(Accepter)中和接受过滤相关位是否相同。如果相同,接收;如果不相同,则过滤。
在原始数据段的前面加上传输起始标签、片选(识别)标签、控制标签,在数据的尾段加上 CRC 校验标签、应答标签和传输结束标签。把这些内容按特定的格式打包好,就可以用一个通道表达各种信号了。各种各样的标签,起到了协同传输的作用。当整个数据包被传输到其他设备时,只要这些设备按格式去解读,就能还原出原始数据。类似这样的数据包就被称为 CAN 的数据帧。
为了更有效的控制通信,CAN 一共规定了 5 种类型的帧,帧也称为报文。
数据帧在 CAN 通信中最主要,也最复杂。数据帧以一个显性位(逻辑 0)开始,以 7 个连续的隐性位(逻辑 1)结束。CAN 总线的数据帧有标准格式(Standard Format)和扩展格式(Extended Format)的区分。
帧起始(SOF)
标识一个数据帧的开始,固定一个显性位。
用于同步, 总线空闲期间的任何隐性到显性的跳变都将引起节点进行硬同步。只有总线在空闲期间节点才能够发送 SOF。
仲裁段(Arbitration Field)
仲裁段的内容主要为本数据帧的 ID 信息。数据帧分为标准格式和扩展格式两种,区别就在于 ID 信息的长度:标准格式的 ID 为 11 位;扩展格式为 29 位。在 CAN 协议中,ID 决定着数据帧发送的优先级,也决定着其他设备是否会接收这个数据帧。
仲裁段除了报文 ID 外,还有 RTR, IDE, SRR 位。
注:RTR(Remote TransmissionRequest)远程发送请求,IDE(Identifier Extension)标志符扩展,SRR(Substitude Remote Request)替代远程请求。
控制段
在控制段,r1(reserved1)和 r0(reserved0)为保留位,默认设置为显性位。最主要的是 DLC(Data Length Code)段,它是用二进制编码表示本报文中的数据段包含多少个字节。DLC 段由 4 位组成,DLC 3−DLC 0,表示的数字为 0-8。
CRC 段
为了保证报文的正确传输,CAN 的报文包含了一段 15 位的 CRC 校验码,一旦接收端计算出的 CRC 码跟接收到的 CRC 码不同,就会向发送端反馈出错信息以及重新发送。CRC 部分的计算和出错处理一般由 CAN 控制器硬件完成,或由软件控制最大重发数。在 CRC 校验码之后,有一个 CRC 界定符,它为隐性位,主要作用是把 CRC 校验码与后面的 ACK 段隔开。
ACK 段duan
包含确认位(ACK slot)和界定符(Delimiter, DEL)。ACK 在发送节点发送时,为隐性位。当接收节点正确接收到报文时,对其用显性位覆盖。DEL 界定符同样为隐性位,用于隔开。
CAN 总线使用位同步的方式来确保通信时序,以及对总线的电平进行正确采样。
在讲位时序之前,先介绍几个基本概念。
Time Quantum 时间份额 tQ :CAN 控制器工作的最小时间单位,通常对系统时钟分频得到。
波特率:单位时间内(1 s)传输的数据位,公式:1 / 位时间。举个栗子,系统时钟频率 36 MHz,预分频因子为 4,则 CAN 时钟频率为 9 MHz,则 Tq = 1 / 9 M。假设一个 CAN 位包含 10 个 Tq,则一个位周期 T = 10 Tq,从而波特率为 1 / T = 0.9 MHz。
为了实现位同步,CAN 协议把每一位的时序分解成下图所示的四段。这四段的长度加起来即为一个 CAN 数据位的长度。一个完整的位由 8-25 个 Tq 组成。
同步端(SS,Synchronization Segment)
一个位的输出从同步段开始。若总线的跳变沿被包含在 SS 段的范围之内,则表示节点与总线的时序同步。节点与总线同步时,采样点采集到的总线电平即可被确定为该电平的电位。SS 段的大小为 1 Tq
传播段(PTS,Propagation Time Segment)
用于补偿信号在网络和节点传播的物理延时时间,是总线上输入比较器延时和输出驱动器延时总和的两倍。通常 1-8 Tq
相位缓冲段 1(PBS1, Phase Buffer Segment 1)
主要用于补偿边沿阶段的误差,其时间长度在重新同步时可以加长。初始大小 1-8 Tq
相位缓冲段 2(PBS2,Phase Buffer Segment 2)
也是用于补偿边沿阶段的误差,其时间长度在重新同步时可以缩短。初始大小 2-8 Tq
CAN 同步分为硬同步和重新同步。
同步规则:
当总线上出现帧起始信号(SOF,即隐性到显性的边沿)时,其他节点的控制器根据总线上的这个下降沿对自己的位时序进行调整,把该下降沿包含到 SS 段内。这样根据起始帧来进行的同步称为硬同步。
可以看到在总线出现帧起始信号时,该节点原来的位时序与总线时序不同步,因而这个状态的采样点采集到的数据是不正确的。所以节点以硬同步的方式调整,把自己的位时序中的SS段平移至总线出现下降沿的部分,获得同步,这时采样点采集到的数据是正确数据。
因为硬同步时只是在有帧起始信号时起作用,无法确保后续一连串的位时序都是同步的,所以 CAN 引入了重新同步的方式。在检测到总线上的时序与节点使用的时序有相位差时(即总线上的跳变沿不在节点时序的 SS 段范围),通过延长 PBS1 段或缩短 PBS2 段来获得同步,这样的方式称为重新同步。
分两种情况:第一种, 节点从总线的边沿跳变中,检测到它的时序比总线的时序相对滞后 2 个 Tq,这时控制器在下一个时序中的 PBS1 段增加 2 Tq 的时间长度,使得节点与总线时序重新同步。
第二种,节点从总线的边沿跳变中,检测到它的时序相对超前 2 Tq,这时控制器在前一个位时序中的 PBS2 段减少 2 Tq 的时间长度,获得同步。
在重新同步的时候,PBS1 和 PBS2 段的允许加长或缩短的时间长度定义为重新同步补偿宽度(SJW,reSynchronization Jump Width)。这里设置的 PBS1 和 PBS2 能够增减的最大时间长度 SJW = 2 Tq,若 SJW 设置的太小则重新同步的调整速度慢,若太大,则影响传输速率。