通讯协议之路主要分为两部分,第一部分从理论上面讲解各类协议的通讯原理以及通讯格式,第二部分从具体运用上讲解各类通讯协议的具体应用方法。
后续文章会同时发表在个人博客(jason1016.club)、CSDN;视频会发布在bilibili(UID:399951374)
序、个人理解
- can通信属于异步半双工通信
- can通信支持多设备通信,通讯设备ECU通过can收发器接入到can通信网络中,can通信网络中将接入网络进行通讯的设备称之为节点
- can同行采用多主多从的方式通讯,在通讯协议中的各个节点中,每个节点都可以充当信号的发送者,也可以充当信号的接收者
- can通信网络中接入的节点会拥有个人专属的设备识别码(默认是11位),识别码对应着节点的通信优先级
- 节点优先级具有下面规则:0越多优先级越高,0在的位数越高优先级越高
- can通信原理将单片机发送出来的TTL电平转化为差分信号(CAN_HIGH和CAN_LOW)
- can通信中差分信号差值(HIGH-LOW)决定着逻辑信号
-
- 差分信号差值为2V为逻辑0(显性信号)
- 差分信号差值为0V为逻辑1(隐性信号)
- can通信采用双绞线同时传输,具有强干扰性,因此低速can通信传输距离可达1000m
- can协议在通讯过程中具有五类传输数据帧类型,最后共同组成can通信五类的数据传输格式。下图为数据传输的过程。
- 空闲状态:当总线连续表现为11个位的隐形电平(高电平)
- 工作状态:
-
- 起始位:一位逻辑0
- 识别码:11位识别码,起片选作用,同时对多个设备的通信优先级进行判断。
- RTR位:1位区分该通信格式为数据帧或远程通信帧。0为数据帧;1为远程通信帧
- 控制码(6位):
- IDE位:1位,区分该协议的识别码为标准格式或拓展格式
- 空闲位:1位预留位,为逻辑0
- DLC(Data Link Control):决定后面数据码的程度,DLC为四位,对应8个选项,0001对应1个字节(八位),1000对应8个字节(64位),下图DLC为0001,因此后续数据码为8位
- 数据码:传输数据,长度有前面的DLC码决定
- CRC码(16位,循环冗余校验位):
- CRC校验码:15位,设备接受段根据数据计算出CRC位,如果计算结果和接收到的CRC不一致,说明数据存在问题,就会重新发送一次数据帧
- CRC界定符:1位逻辑1,用于将后续数据隔开
- ACK码(2位):
- ACK确认槽:发送端发送的是逻辑1,接收端回复逻辑0表示应答
- ACK界定符:1位逻辑1,用于将后续数据隔开
- 结束位:7位逻辑1,表示数据帧传输结束
1. 总体概述
1.1 基本概念
CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO 国际标准化的串行通信协议。在北美和西欧,CAN 总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以 CAN 为底层协议专为大型货车和重工机械车辆设计的 J1939 协议。
1.2 通讯方式
回顾前面学到的 RS232 IIC SPI RS485 等通信
UART:(Universal Asynchronous Receiver Transmitter:通用异步收发器/异步串行通信口),是一种通用的串行数据总线,用于异步通信,支持全双工。它包括了RS232、RS499、RS423、RS422和RS485等接口标准规范和总线标准规范,即UART是异步串行通信口的总称。
IIC总线协议:I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。
SPI总线协议:SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议。
RS232接口缺陷:
(1)接口的信号电平值较高( +/-12V),易损坏接口电路的芯片。
(2)传输速率较低,在异步传输时,波特率为20Kbps。
(3)接口使用一根信号线和一根信号返回线而构成共地的传输形式,这种共地传输容易产生共模干扰,所以抗噪声干扰性弱。
(4)传输距离有限,最大传输距离标准值为50英尺,实际上也只能用在50米左右。
RS485是对RS232的改进,特点包括:
①接口电平低,不易损坏芯片。RS485的电气特性:逻辑“1”以两线间的电压差为+(2 ~ 6)V表示,逻辑“0”以两线间的电压差为-(2~6)V表示。接口信号电平比RS232降低了,不易损坏接口电路的芯片。
②传输速率高。10米时,RS485的数据最高传输速率可达35Mbps,在1200m时,传输速度可达100Kbps。
③抗干扰能力强。RS485接口是采用平衡驱动器和差分接收器的组合,抗共模干扰能力增强,即抗噪声干扰性好。
④传输距离远,支持节点多。RS485总线最长可以传输1200m以上(速率≤100Kbps)一般最大支持32个节点,如果使用特制的485芯片,可以达到128个或者256个节点,最大的可以支持到400个节点。
CAN总线通信系统是串行通信的一种,要优于RS485总线,是目前比较常用的一种工业总线,如汽车的电气部分就采用CAN总线实现通信。
与I2C、SPI等具有时钟信号的同步通讯方式不同,CAN通讯并不是以时钟信号来进行同步的,它是一种异步半双工通讯。(同步即在同一个时钟驱动下数据通信,半双工即接受与发送不能同时进行)
1.3 为什么使用CAN?
汽车工业蓬勃发展,汽车的电子控制单元逐渐增多。各电控单元之间的信号交换导致汽车线束的级数增加,复杂粗大的线束与汽车有限的布线空间之间矛盾越来越突出,繁多的线束导致电气系统可靠性下降,同时增加了重量。
CAN总线将汽车内部各电控单元之间连接成一个局域网络,实现了信息的共享,大大减少了汽车的线束,如下面的示意图:
比如上图中,每个部分的多个器件都挂载在CAN总线上(一个CAN总线上的所有器件通讯速率必须相同),各个部分再汇集到网关,由网关分配实现各个不同速率的部分之间通讯,这样就很方便轻松实现了对汽车整体电控部分的检测与控制。
在汽车、工业控制领域,数据通信的稳定性和正确性要求极高,因为设备的工作环境既有振荡、高温、辐射等各种不定因素,那不是一般的通信协议能够满足的。除此之外,CAN通信还有许多优秀的特点,比如多主控制、故障封闭功能等,非常适用于工控领域方面,将在下文再提。
1.4 CAN的协议及组成
CAN协议经过ISO标准化后有两个标准ISO11898标准和IS011519-2标准。其中ISO11898是针对通信速率为125Kbps~1Mbps的高速通信标准(闭环),而IS011519-2是针对通信速率为125Kbps以下的低速通信标准(开环)。
Kbps:总线的通信速率,指的是位速率。或称为比特率(和波特率不是一回事),表示的是:单位时间内,通信线路上传输的二进制位的数量,其基本单位是 bps 或者 b/s (bit per second)。
CAN的组成一般有两种方式:
1:CPU与CAN控制器集成到一起、再外接CAN收发器;
2:另一种是CPU与CAN控制器分开的,使用的时候需要配置CAN接口电路,比较麻烦。
STM32中就是采用第一种方式,将CAN接口集成在芯片内,使用的时候再外接CAN收发器(顾名思义,可发送,可接收),常用的有TJA1050或者82C250。
CAN收发器是用于TTL电平与差分电压信号相互转换的,TTL电平即单片机引脚直接提供的电平,逻辑0代表低电平,逻辑1代表高电平;而差分电压信号则为固定的电压值。
2. 上帝视角看CAN的通讯过程
以ISO11898 标准的高速、短距离闭环网络为例,总线最大长度为 40m,通信速度最高为 1Mbps。在 CAN 总线的起止端有一个 120Ω的终端电阻,是用来来做阻抗匹配,以减少回波反射。
2.1 数据传输原理实现
由上图可知,CAN通信是通过两根线完成的:
* 一条是黄色的CAN_High
*一条是绿色的CAN_Low
按照定义:
- CAN_High - CAN_Low < 0.5V 时候为隐性的,逻辑信号表现为"逻辑1",即高电平。
- CAN_High - CAN_Low > 0.9V 时候为显性的,逻辑信号表现为"逻辑0",即低电平。
由上图可知, 没有数据发送或者发送数据0时,两条线的电平一样都为2.5V,两条线的电压差小于0.5V;当发送数据1时,CAN_High电压升高,CAN_Low电压降低,两条线电压差大于0.9V时,认为数据为逻辑0;
所以CAN使用的是差分信号,差分信号稳定性更好,因为即使环境问题导致CAN_High电压发送变化,则CAN_L也会发送同等变化,两者做差即可抵消由于这个环境引起的变化。
隐性、显性之间存在天然的优先级特性:显性(逻辑0)的优先级比隐性(逻辑1)高;该优先级的特性,可以用来进行多主机的仲裁;
在总线上显性电平具有优先权,只要有一个节点输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强)
上图为CAN的收发器:CAN_Rx和CAN_Tx分别是从MCU中接出来的引脚,比如MCU要发送一个逻辑1,则只要将CAN_Tx设置为1,经过CAN收发器转换,CAN_High和CAN_Low 线上的电压均为 2.5v,即传到总线的电压差 Vh-Vl=0V,总线上的状态则就是逻辑1。同样,当CAN_High和CAN_Low 读取到 CAN总线电压分别3.5V和1.5V,即压差为2V,经过收发器转换,MCU则可通过CAN_Rx读取到信号0。
2.2 通信的整个过程
那么是如何通过一个节点的MCU向总线上那么多节点中的某个节点进行发送信息的?一个节点又是如何知道某个信息是发给自己的或者不是发给自己的?这里或许让你想起 IIC 中以地址方式进行主从点对点的通信,但其实在CAN中并无地址的概念。
少了像IIC中的SCL地址线、SPI中的片选信号线,简洁的物理层决定了 CAN 必然要配上一套更复杂的协议。如何用一个信号通道实现同样、甚至更强大的功能呢?答案是对数据或操作命令进行打包。
2.2.1 空闲状态
先规定空闲状态,所谓的空闲状态就是指没有节点正在传输数据的时候;
在CAN协议中,当总线上的上出现连续的11位隐性电平(两根线电压差小于0.5V),表示总线就处于空闲状态。
也就是说对于任意一个节点而言,只要它监听到总线上连续出现了11位隐性电平,那么该节点就会认为总线当前处于空闲状态。
怎么让总线连续出现11位隐形电平呢?由于显性电平的高优先级特性,必须所有CAN主机都连续发送11个隐性电平,或者不发送时,总线才能出现连续11个隐性电平,即处于空闲状态
所以,现在可以先简单地理解为,需要在总线一开始工作的时候,所有节点都输出隐性电平;已知在一次传输时该节点输出显性电平,则在传输完成后该节点再输出隐性电平即可,这样就能将总线在无数据传输时保持空闲状态。(真实的实现过程比较复杂,这里仅作为暂时理解,后面会继续提到)
2.2.2 开始数据传输
每次发送数据前,节点都会监听总线的状态,如果总线状态为空闲时,它就会立即向总线上发送自己的数据,这个数据里不仅有数据,还有本身的ID信息或者其他的控制指令,应称为数据包(数据帧),也叫做报文。当报文被传输到其它节点时,只要这些节点按格式去解读,就能还原出原始数据。
报文: 在原始数据段的前面加上传输起始标签、片选(识别)标签、控制标签,在数据的尾段加上 CRC 校验标签、应答标签和传输结束标签。类似这样的数据包就被称为 CAN 的数据帧。为了更有效地控制通讯,CAN 一共规定了 5 种类型的帧,帧也称为报文。
数据帧是在 CAN 通讯中最主要、最复杂的报文,它以一个显性位(逻辑 0)开始,以 7 个连续的隐性位(逻辑 1)结束。在它们之间,分为仲裁段、控制段、数据段、CRC 段和 ACK 段,以标准数据帧为例。
域段 | 域段名 | 位宽:bit | 描述 |
帧起始 | SOF(Start Of Frame) | 1 | 数据帧起始标志,固定为1bit显性('b0) |
仲裁段 | Identify(ID) | 11 | 本数据帧的 ID 信息, ID 信息的作用:① 如果同时有多个节点发送数据时,作为优先级依据(仲裁机制);② 目标节点通过 ID 信息来接受数据(验收滤波技术) |
RTR | Remote Transmission Request BIT | 1 | RTR标识是否是远程帧(0,数据帧;1,远程帧),在数据帧里这一位为显性('b0) |
IDE | Identifier Extension Bit | 1 | IDE用于区分标准格式与扩展格式,在标准格式中 IDE 位为显性(‘b0),在扩展格式里 IDE 位为隐性(’b1) |
R0 | 保留位 | 1 | 1bit保留位,固定为1'b0 |
DLC | data length | 4 | 由 4 位组成,MSB 先行(高位先行),它的二进制编码用于表示本报文中的数据段含有多少个字节,DLC 段表示的数字为0到8,若接收方接收到 9~15 的时候并不认为是错误 |
数据段 | data | 0~64 | 据帧的核心内容,它由 0~8 个字节(0 ~ 64位)组成,MSB 先行 |
CRC段 | CRC | 15 | 段用于检查帧传输错误,发送方以一定的方法计算包括:帧起始、仲裁段、控制段、数据段;接收方以同样的算法计算 CRC 值并进行比较,如果不同则会向发送端反馈出错信息,重新发送;计算和出错处理一般由 CAN 控制器硬件完成或由软件控制最大重发数。 |
CRC界定符 | 1 | CRC 界定符(用于分隔的位),为隐性位(1'b1),主要作用是把CRC 校验码与后面的 ACK 段间隔起来 | |
ACK 槽 | ACK slot | 1 | 在 ACK 槽位中,发送端发送的为隐性位,而接收端则在这一位中发送显性位以示应答;发送 ACK/返回 ACK这个过程使用到回读机制,即发送方先在 ACK 槽发送隐性位后,回读到的总线上的电平为显性0,发送方才知道它发送成功了,不用重发 |
ACK界定符 | 1 | 在 ACK 槽和帧结束之间由 ACK 界定符间隔开,为隐性位 | |
帧结束 | EOF | 7 | 由发送端发送 7 个隐性位表示结束 |
比如总线上有3个节点,节点1设置ID为000101 00010,节点2验收滤波ID表中有节点1的ID号,而节点3中的验收滤波ID表中没有节点1的ID号,节点1向节点2发送1字节的信息。
报文信息:0 000101 00010 0 0 0 0001 0101 1000 XXXXXXXXXXXXXXX 1 1 1 1111111
通过总线发送时,在ID信息发送阶段,只有节点2才能收到总线上的数据,因为节点3的验收滤波ID表中没有节点1的ID号
在报文发送到ACK槽时,会等待并回读节点2的反馈,从节点2的角度看,此时总线为空闲状态,当验证CRC正确,则向总线发送显性电平,接着当节点1回读到显性电平,才会继续发送剩下的EOF
以上只是简单的理解,实际传输的过程比这个复杂许多,下文继续。
2.2.3 仲裁机制
运用到线与机制和回读机制
以上只是节点1主动发送数据,但是万一节点1和节点2同时向节点3发送数据的时候,如何判定先后呢?采用非破坏性位仲裁机制,即对各个消息的标识符(即ID号)进行逐位仲裁(比较),如果某个节点发送的消息仲裁获胜,那么这个节点将获取总线的发送权,仲裁失败的节点则立即停止发送并转变为监听(接收)状态。
从上文可知,显性的优先级高于隐性,即仲裁比较的就是哪个ID中的0多,0最多的那个就可以获得发送权,比如 000000 00010 就比 000000 00011 的优先级要高,仲裁的过程由硬件实现;同时要注意,仲裁段除了报文 ID 外,还有 RTR、IDE、SRR 位(在拓展模式中,下文价绍),也就是说当ID全都一样时,会继续比较接下来的几位。
至于如何做到“0多即胜”,可以理解为一种回读和线与机制,即显性能够将隐性覆盖,将自己要比较的位与总线上的状态相与,只有线与的结果与本身一致时,仲裁才能够通过。
其实在报文发送上去的过程,采用的是广播的方式,在节点1和节点2总裁的同时,总线上所有的节点都能够监听到它们的ID号,只不过也在同时进行验收滤波,只有监听到的ID号存在ID表中,该节点才会选择继续监听后面的报文。
2.2.4 位时序
以上已经基本解决了CAN通信的基本问题,可以思考一下,由于 CAN 没有时钟信号线,而且它的报文中并没有包含用于同步的标志,要怎么做才能对总线的电平进行正确的采样呢?比如我节点1发送3个位出去了,节点2应该在什么时候接收才能保证此时此刻它所接收到的就是第3位或者接收到的电平是正确的? CAN中提出了位同步的方式来确保通讯时序。
位时序的主要知识点
CAN总线通讯协议的每一个数据帧可以看作一连串的电平信号,每一个电平信号代表一位(一个字节8位的位),所以一帧中包含了很多个位,由发送单元在非同步的情况下发送的每秒钟的位数称为位速率。 一位又分为4段, 同步段(SS)、传播时间段(PTS)、相位缓冲段 1(PBS1)、相位缓冲段 2(PBS2)。分解后最小的时间单位是 Tq,而一个完整的位由 8~25 个 Tq 组成。
- 1 位分为 4 个段,每个段又由若干个 Tq 构成,这称为位时序。
- 1 位由多少个 Tq 构成、每个段又由多少个 Tq 构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。
SS 段(SYNC SEG):同步段,比如当总线上出现帧起始信号(SOF)时,其它节点上的控制器根据总线上的这个下降沿,对自己的位时序进行调整,把该下降沿包含到 SS 段内,这样根据起始帧来进行同步的方式称为硬同步。其中 SS 段的大小为 1Tq。总线上信号的跳变沿被包含在节点的 SS 段的范围之内,则表示节点与总线的时序是同步的,采样点采集到的总线电平即可被确定为该位的电平。
PTS 段(PROP SEG):传播时间段,这个时间段是用于补偿网络的物理延时时间,包括发送单元的输出延迟、总线上信号的传播延迟、接收单元的输入延迟,这个段的时间为以上各延迟时间的和的两倍。大小可以为 1~8Tq。
PBS1 段(PHASE SEG1):相位缓冲段,主要用来补偿边沿阶段的误差,它的时间长度在重新同步的时候可以加长。 PBS1 段的初始大小可以为 1~8Tq。
PBS2 段(PHASE SEG2):另一个相位缓冲段,也是用来补偿边沿阶段误差的,它的时间长度在重新同步时可以缩短。 PBS2 段的初始大小可以为 2~8Tq。
(对于PBS段而言,当信号边沿不能被包含于 SS 段中时,可在此段进行补偿,以及可以吸收时钟误差)
SJW (reSynchronization Jump Width):重新同步补偿宽度,即在重新同步的时候,PBS1 和 PBS2 段的允许加长或缩短的时间长度,SJW 加大后允许误差加大,但通信速度下降。SJW 为补偿此误差的最大值(即每一次误差补偿都不能超过这个值,1~4Tq)。
CAN 的同步分为硬同步和重新同步:
硬同步:在帧起始信号时同步总线上所有器件的位时序,无法确保后续一连串的位时序都是同步的。
重新同步:在检测到总线上的时序与节点使用的时序有相位差时(即总线上的跳变沿不在节点时序的 SS 段范围),通过延长 PBS1 段或缩短 PBS2 段,来获得同步。
采样点: 读取总线电平的时刻,并将读到的电平作为位值的点。位置在 PBS1 结束处。
延长/缩短PBS段来达到同步: PTS+PBS1小而PBS2加大时采样点前移,PTS+PBS1大而PBS2减小时采样点后移。
同步过程:
在硬同步阶段,当节点检测到本身SS段并不在总线电平下降沿跳变处,节点则会把自己的位时序中的 SS 段平移至总线出现下降沿的部分,后面三段也跟着上去,以获得同步。(可以理解为节点在检测到帧起始信号时才开始“设置段”)
在重新同步阶段,利用普通数据位的高至低电平的跳变沿来同步(帧起始信号是特殊的跳变沿)。重新同步与硬同步方式相似的地方是它们都使用 SS 段来进行检测,同步的目的都是使节点内的 SS 段把跳变沿包含起来。重新同步的方式分为超前和滞后两种情况,以总线跳变沿与 SS 段的相对位置进行区分,下面举例设SJW为2Tq。
① 相位超前,节点从总线的边沿跳变中,检测到它内部的时序比总线的时序相对超前 2Tq,这时控制器在下一个位时序中的 PBS1 段增加 2Tq 的时间长度,使得节点与总线时序重新同步。
② 相位相位滞后,节点从总线的边沿跳变中,检测到它的时序比总线的时序相对滞后 2Tq,这时控制器在前一个位时序中的 PBS2 段减少 2Tq 的时间长度,获得同步。
理解上面重新同步过程时,需要知道前一次SS到下一次SS之间的长度是可伸展的(暂时称之为 L ),当检测到前一次SS出现得太快(还没等到下降沿到来),这就是相位超前了,如果不把 L 缩短一点,那么下一次SS将也会超前。缩短 L 的方法就是调整 PBS 的长度,这个过程由CAN控制器完成,即(新的PBS长度 = 当前 PBS长度-SJW)。
2.2.5 一次数据传输的例子
比如总线上有3个节点,节点1设置ID为000100 00110,节点2设置ID为000100 00111,节点3验收滤波ID表中有节点1和节点2的ID号,节点1和节点2同时向节点3发送1字节的信息。
- 总线空闲,节点1和节点2同时发送帧起始信号,3个节点同时调整位时序(硬同步);
- 节点1和节点2开始仲裁,两者同时向总线发送第一位0,同时回读总线状态与本身状态相与,得0,两者第1位仲裁均通过;一直持续到第9位1,两者同时向总线发送1,同时回读总线状态,得1,两者第9位仲裁均通过;
- 直到第11位,当两个节点回读总线状态与本身状态相与时,总线得显性将隐性屏蔽,即总线状态为显性,则节点1得0(与本身状态相同),而节点2得0(与本身状态不同),此时节点1仲裁胜利,节点2放弃发送请求;
- 从第1位仲裁到第11位仲裁得同时,节点1向其他节点广播了本身的ID,当然节点1本身也接收到节点2的ID信息,因此节点2和节点3也都收到了节点1的ID信息,只不过节点2对节点1不敢兴趣,因而选择了忽略节点1后续的信息,节点3则开始接收节点1的数据;
- 从硬同步之后,每当节点1和节点2发出一个仲裁位,三个节点的CAN控制器都在检测本身的位时序与总线位时序是否一致,当有相位超前或者滞后时则自动进行位时序的重新同步。在后续的报文传送中亦是如此。
3. CAN总线协议层的详细介绍
CAN 协议经 ISO 标准化后有 ISO11898 标准和 ISO11519-2 标准两种。ISO11898 和 ISO11519-2 标准对于数据链路层的定义相同,但物理层不同。
在阅读完上文后,对CAN总线中的一个极其重要的知识点需要搞明白:回读机制。
指的是节点在向总线上发送报文的过程中,同时也对总线上的二进制位进行“回读”。通过这种机制,节点就可以判断出本节点发出的二进制位与总线上当前的二进制位是否一致。
3.1 帧的种类
帧类型 | 帧用途 |
数据帧 | 用于发送单元向接收单元传送数据的帧。 |
遥控帧 | 用于接收单元向具有相同 ID 的发送单元请求数据的帧。 |
错误帧 | 用于当检测出错误时向其它单元通知错误的帧。 |
过载帧 | 用于接收单元通知其尚未做好接收准备的帧。 |
帧间隔 | 用于将数据帧及遥控帧与前面的帧分离开来的帧 |
另外,数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有 11 个位的标识符(Identifier: 以下称 ID),扩展格式有 29 个位的 ID。
3.1.1 数据帧
关于数据帧的标准格式各个位的介绍可以查看本文的【2.2.2节】,在数据帧的拓展格式中,与标准格式不同处在于:
- 仲裁段为 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)
3.1.2 遥控帧
接收单元向发送单元请求发送数据所用的帧。遥控帧由 6 个段组成。遥控帧没有数据帧的数据段。举个例子,车钥匙需要知道车门的状态,一个远程帧过去,车门把自己的状态发回来了。
遥控帧与数据帧的不同之处:
- 遥控帧的 RTR 位为隐性位,没有数据段;
- 没有数据段的数据帧和遥控帧可通过 RTR 位区别开来;
- 遥控帧的数据长度码以所请求数据帧的数据长度码表示;
3.1.3 错误帧
用于在接收和发送消息时检测出错误通知错误的帧。错误帧由错误标志和错误界定符构成。
(1) 错误标志
错误标志包括主动错误标志和被动错误标志两种。
① 主动错误标志:6 个位的显性位。
② 被动错误标志:6 个位的隐性位。
(2) 错误界定符
错误界定符由 8 个位的隐性位构成。
(3)错误标志之后还有0~6个错误标志重叠部分
处于主动错误状态的节点检测到错误时会发送主动错误标志,6个连续显性位会违反位填充规则和位场的固定形式,进而造成其它节点也检测到错误并发送错误标志。所有节点所发送的显性序列叠加组成错误标志重叠部分,错误标志重叠部分的长度在6-12个显性位之间。
对主动错误和被动错误的通俗理解:
首先建议把广泛使用的“主动错误”和“被动错误”概念换成“主动报错”和“被动报错”。
1.主动报错站点
只要检查到错误,它立即“主动地”发出错标识。所谓“出错标识“,它本身就是一个“错误的位序列”(连续的6 个显性位,不满足CAN协议的“最多5个连续的同性位”要求),目的是“主动地”告诉大家:即使你们没有发现“刚才我已发现”的错误,现在我“以身作则”出错啦!你们该看到这个错误了吧!
2.被动报错站点
如果检查到错误,它只能干瞪眼“被动地”等别人(主动报错站点)报错,等待的时候它可不能去动总线,直到识别出由主动报错站点发出的“错误的位序列”,它才松了一口气:有人正式报错了!然后他就可以去竞争总线,该干啥干啥。
(错误帧这里看不明白没关系,后文会有详细介绍)
3.1.4 过载帧
过载帧是接收节点向总线上其它节点报告自身接收能力达到极限的帧,可以理解为:接收节点Node_A接收报文的能力达到极限了,于是Node_A就会发出过载帧来告诉总线上的其它节点(包括发送节点),我接收节点Node_A已经没有能力处理你们发来的报文了。过载帧由过载标志和过载界定符构成。
(1) 过载标志
6 个位的显性位。
过载标志的构成与主动错误标志的构成相同。
(2) 过载界定符
8 个位的隐性位。
过载界定符的构成与错误界定符的构成相同。
3.1.5 帧间隔
帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。过载帧和错误帧前不能插入帧间隔。
(1) 间隔
3 个位的隐性位。
(2) 总线空闲
隐性电平,无长度限制(0 亦可)。
本状态下,可视为总线空闲,要发送的单元可开始访问总线。
(3) 延迟传送(发送暂时停止)
8 个位的隐性位。
只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。
3.2 位填充
为防止突发错误而设定,CAN协议中规定,当相同极性的电平持续五位时,则添加一个极性相反的位。填充位的添加和删除是由发送节点和接收节点完成的,CAN-BUS只负责传输,不会操纵信号。
- 对于发送节点而言:
在发送数据帧和遥控帧时,对于SOF~CRC(除去CRC界定符) 之间的位流,相同极性的电平如果持续5位,那么在下一个位插入一个与之前5位反型的电平;
- 对于接收节点而言:
在接收数据帧和遥控帧时,对于SOF~CRC(除去CRC界定符)之间的位流,相同极性的电平如果持续5位,那么需要删除下一位再接收。如果这个第 6 个位的电平与前 5 位相同,将被视为错误并发送错误帧。
3.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;
错误帧界定符
过载帧界定符
3.4 错误通知
在检测到错误之后,检测到错误的节点就要发送错误帧到总线上来通知总线上的其他节点。
3.4.1 节点错误状态
对于错误界定,节点存在如下三种状态:
- 主动错误: 错误标志由6个连续的显性位组成(这种连续的6个显性位与常规的填充位和其它帧固定格式不相同,正因为如此,硬件才容易区别)
- 被动错误 :被动错误标志由6个连续的隐性位组成,当发送结束后,处于被动错误状态的节点在下一次再次发送时之前需要等待一些额外时间。
- 总线关闭: 处于总线关闭状态的节点不允许发送和接收任何形式的帧报文。且只能通过用户请求进行恢复。
3.4.2 错误状态的转换
一个CAN节点在什么情况下处于主动错误状态,什么情况下处于被动错误状态呢?
在CAN节点内,有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)
错误界定并非是依据错误的类型去界定CAN节点的错误状态,而是依据错误计数器【TEC/REC】的值来界定CAN节点的错误状态;当该节点检测到错误后,内部REC/TEC计数器会相应的增加,基于REC/TEC的值判定节点状态。
需要注意的是:这两个计数器计得不是收发报文的数量,也不是收发错误帧的数量。TEC和RCE计数值的变化,是根据下表的规定来进行的。
节点错误状态的转换就是一个 “量变”到“质变” 的过程:
- 主动错误状态:【REC
初步可判定该节点相对稳定可靠,该错误计数很可能是由于某个节点异常导致的,那么其他节点很可能也会触发该错误,那么允许该节点破坏CAN总线的异常报文并告知其他节点;
节点检测到一个错误就会发送带有主动错误标志的错误帧,因为主动错误标志是连续六个显性位,所以这个时候主动错误标志将会“覆盖”掉总线上其它节点的发送,而之前在CAN总线上传输的报文就被这“六个连续显性位”破坏掉了。
如果发出主动错误帧的节点是发送节点,这个情况下就相当于:刚刚发送的那一帧报文我发错了,现在我破坏掉它(发送主动错误帧),你们不管收到什么都不算数;
如果发出主动错误帧的节点是接收节点,这个情况就相当于:刚刚我收报文的时候发现了错误,不管你们有没有发现这个错误,我现在主动站出来告诉大家这个错误,并把这一帧报文破坏掉(发送主动错误帧),刚才你们收到的东西不管对错都不算数了。
- 被动错误状态:【REC>128 或TEC>128】
节点发送错误帧的次数较多,初步可判定该节点相对不可靠,该错误计数很可能是由于自身节点问题导致,即该错误很可能仅有该节点才有,对于其他节点而言是可以正常交互的,总线不信任该节点提供的错误标识,将不允许破坏总线数据,那么允许该节点发送错误帧“6个连续隐性位”至CAN总线,仅告知其他节点异常;
如果发出被动错误帧的节点为报文的发送节点,那么在发送被动错误帧之后,刚刚正在发送的报文被破坏,并且该节点不能在错误帧之后随着连续发送刚刚发送失败的那个报文。随之而来的是帧间隔,并且连带着8位隐性位的 “延迟传送” 段;这样总线电平就呈现出连续11位隐性位,总线上的其它节点就能判定总线处于空闲状态,就能参与总线竞争。
此时如果该节点能够竞争成功,那么它就能接着发送,如果竞争不能成功,那么就接着等待下一次竞争。这种机制的目的正是为了让其它正常节点(处于主动错误)优先使用总线。
- 总线关闭状态:【TEC>255】
一个处于被动错误状态的节点,仍然多次发送被动错误帧,使该节点转为总线关闭态;
该节点不能向总线上发送报文,也不能从总线上接收报文,整个节点脱离总线。等到检测到128次11个连续的隐性位时,TEC和REC置0,重新回到主动错误状态。
由于存在实现方式的不同,CAN总线关闭状态存在只允许用户请求恢复和检测到128个11位连续的隐性位时自恢复两种不同的恢复形式。
如果总线上只有一个节点,该节点发送数据帧后得不到应答,TEC最大只能计数到128,即这种情况下节点只会进入被动错误状态而不会进入总线关闭状态。
3.4.3 错误帧的发送
按照CAN协议的规定:
发生位错误、填充错误、格式错误、ACK错误时,则在错误产生的那一位的下一位开始发送错误帧。
发生CRC错误时,紧随ACK界定符后的位发送错误帧。
错误帧发送完成后,总线空闲时自动重发出错的数据帧。
3.4.4 仲裁机制与位时序
仲裁存在于当同时有多个节点竞争总线发送权时,关键词是同时,比如节点1和节点2两者同时向总线发送一个位,是同时发送的,总线只是导线(理解成自带线与功能),如果节点1发送的是1,节点2发送的是0,线与后总线的状态则为0;
与此同时,这里运用到回读机制,即:节点发送位的同时会回读总线的状态并与自身相比较,可知节点1本身状态与总线状态一致,则节点1仲裁胜利。(可查阅本文【【2.2.3节】】)
理解位时序,重点在于同步,分为硬同步和重新同步,在重新同步中,通过设置SJW来调整PBS段的长度(PBS1增长,PBS2缩短),以达到调整一个位中Tq的个数,即长度。(可查阅本文【【2.2.4节】】)
关于波特率的计算:
总线上的各个通讯节点只要约定好 1 个 Tq 的时间长度以及每一个数据位占据多少个Tq,就可以确定 CAN 通讯的波特率。例如,假设1Tq=1us,而每个数据位由 19 个 Tq 组成,则传输一位数据需要时间 T(1bit) =19us,从而每秒可以传输的数据位个数为:1x10^6/19 = 52631.6 (bps),这个每秒可传输的数据位的个数即为通讯中的波特率。
3.4.5 举个栗子
【位错误】举例(情况1):
- 设总线上所有节点处于主动错误状态;
- 当一个发送节点监控到总线上的位数值与发送的位数值不一致时,检测为位错误,并发送主动错误标志(6个连续的显性位);
- 接收节点接收到发送节点发送的6个连续的显性位时,会检测为位填充错误,也会发送主动错误标志;
- 发送节点发送完主动错误标志后,开始监控总线是否为隐性位,当总线为隐性位时,开始发送错误界定符(8个连续的隐性位);
- 当接收节点发送完主动错误标志后,开始向总线发送错误界定符; 等待错误帧发送完成,总线空闲后,发送节点重新发送出错的报文.
由于发送节点发送6个连续的显性位会破坏位填充规则,触发接收节点发送主动错误标志,发送节点和接收节点的结合是形成错误标志叠加部分的原因。
【位错误】举例(情况2):
- 假设发送节点处于被动错误状态,接收节点处于主动错误状态;
- 当发送节点监控到总线上的位数值与发送的位数值不一致时,检测为位错误,并发送被动错误标志(6个连续的隐性位);
- 接收节点接收到发送节点发送的6个连续的隐性位时,会检测为位填充错误,并会发送主动错误标志;
- 发送节点发送完被动错误标志后,开始监控总线是否为隐性位,当总线为隐性位时,开始发送错误界定符(8个连续的隐性位);
- 接收节点发送完主动错误标志后,开始监控总线是否为隐性位,当总线为隐性位时,开始发送错误界定符(8个连续的隐性位);
3.5 CAN的特性总结
1) 多主控制
在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。
2) 系统的柔软性
与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。
3) 通信速度较快,通信距离远。最高 1Mbps(距离小于 40M),最远可达 10KM(速率低于 5Kbps)。
4) 具有错误检测、错误通知和错误恢复功能。所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。
5) 故障封闭功能。CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。
6) 连接节点多。CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。