学习目标:
1.掌握can通讯的原理
2.实操can通讯的收发
学习内容:
1.can通讯的定义:CAN通讯并不是以时钟信号来进行同步的,它是一种异步半双工通讯。(同步即在同一个时钟驱动下数据通信,半双工即接受与发送不能同时进行)
2.can协议的好处:
CAN总线将汽车内部各电控单元之间连接成一个局域网络,实现了信息的共享,大大减少了汽车的线束。
eg:每个部分的多个器件都挂载在CAN总线上(一个CAN总线上的所有器件通讯速率必须相同),各个部分再汇集到网关,由网关分配实现各个不同速率的部分之间通讯,这样就很方便轻松实现了对汽车整体电控部分的检测与控制。
CAN的组成方式:
1:CPU与CAN控制器集成到一起、再外接CAN收发器;
2:另一种是CPU与CAN控制器分开的,使用的时候需要配置CAN接口电路,比较麻烦。
eg:stm32采用1的组成方式,将CAN接口集成在芯片内,使用的时候再外接CAN收发器(顾名思义,可发送,可接收),常用的有TJA1050或者82C250。
CAN收发器是用于TTL电平与差分电压信号相互转换的,TTL电平即单片机引脚直接提供的电平,逻辑0代表低电平,逻辑1代表高电平;而差分电压信号则为固定的电压值。 (can通过固定差分信号,由单片机引脚的ttl电平控制)
CAN通讯的全过程:
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时,两条线的电平一样都为2.5V,两条线的电压差小于0.5V;当发送数据1时,CAN_High电压升高,CAN_Low电压降低,两条线电压差大于0.9V时,认为数据为逻辑0;
-
隐性、显性之间存在天然的优先级特性:显性(逻辑0)的优先级比隐性(逻辑1)高;该优先级的特性,可以用来进行多主机的仲裁;
在总线上显性电平具有优先权,只要有一个节点输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强)
通信的过程是对数据或操作命令进行打包。
开始传输数据:
每次发送数据前,节点都会监听总线的状态,如果总线状态为空闲时,它就会立即向总线上发送自己的数据,这个数据里不仅有数据,还有本身的ID信息或者其他的控制指令,应称为数据包(数据帧),也叫做报文。当报文被传输到其它节点时,只要这些节点按格式去解读,就能还原出原始数据。
报文: 在原始数据段的前面加上传输起始标签、片选(识别)标签、控制标签,在数据的尾段加上 CRC 校验标签、应答标签和传输结束标签。类似这样的数据包就被称为 CAN 的数据帧。为了更有效地控制通讯,CAN 一共规定了 5 种类型的帧,帧也称为报文。
域段 | 域段名 | 位宽: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 个隐性位表示结束 |
仲裁机制
运用到线与机制和回读机制
以上只是节点1主动发送数据,但是万一节点1和节点2同时向节点3发送数据的时候,如何判定先后呢?采用非破坏性位仲裁机制,即对各个消息的标识符(即ID号)进行逐位仲裁(比较),如果某个节点发送的消息仲裁获胜,那么这个节点将获取总线的发送权,仲裁失败的节点则立即停止发送并转变为监听(接收)状态。
从上文可知,显性的优先级高于隐性,即仲裁比较的就是哪个ID中的0多,0最多的那个就可以获得发送权,比如 000000 00010 就比 000000 00011 的优先级要高,仲裁的过程由硬件实现;同时要注意,仲裁段除了报文 ID 外,还有 RTR、IDE、SRR 位(在拓展模式中,下文价绍),也就是说当ID全都一样时,会继续比较接下来的几位。
至于如何做到“0多即胜”,可以理解为一种回读和线与机制,即显性能够将隐性覆盖,将自己要比较的位与总线上的状态相与,只有线与的结果与本身一致时,仲裁才能够通过。
其实在报文发送上去的过程,采用的是广播的方式,在节点1和节点2总裁的同时,总线上所有的节点都能够监听到它们的ID号,只不过也在同时进行验收滤波,只有监听到的ID号存在ID表中,该节点才会选择继续监听后面的报文。
用位同步来保证通讯同步。
位时序的主要知识点
CAN总线通讯协议的每一个数据帧可以看作一连串的电平信号,每一个电平信号代表一位(一个字节8位的位),所以一帧中包含了很多个位,由发送单元在非同步的情况下发送的每秒钟的位数称为位速率。 一位又分为4段, 同步段(SS)、传播时间段(PTS)、相位缓冲段 1(PBS1)、相位缓冲段 2(PBS2)。分解后最小的时间单位是 Tq,而一个完整的位由 8~25 个 Tq 组成。
CAN 的同步分为硬同步和重新同步:
硬同步:在帧起始信号时同步总线上所有器件的位时序,无法确保后续一连串的位时序都是同步的。
重新同步:在检测到总线上的时序与节点使用的时序有相位差时(即总线上的跳变沿不在节点时序的 SS 段范围),通过延长 PBS1 段或缩短 PBS2 段,来获得同步。
SJW (reSynchronization Jump Width):重新同步补偿宽度,即在重新同步的时候,PBS1 和 PBS2 段的允许加长或缩短的时间长度,SJW 加大后允许误差加大,但通信速度下降。SJW 为补偿此误差的最大值(即每一次误差补偿都不能超过这个值,1~4Tq)。
同步过程:
在硬同步阶段,当节点检测到本身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)。
比如总线上有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控制器都在检测本身的位时序与总线位时序是否一致,当有相位超前或者滞后时则自动进行位时序的重新同步。在后续的报文传送中亦是如此。
回读机制:指的是节点在向总线上发送报文的过程中,同时也对总线上的二进制位进行“回读”。通过这种机制,节点就可以判断出本节点发出的二进制位与总线上当前的二进制位是否一致。
过载帧
过载帧是接收节点向总线上其它节点报告自身接收能力达到极限的帧,可以理解为:接收节点Node_A接收报文的能力达到极限了,于是Node_A就会发出过载帧来告诉总线上的其它节点(包括发送节点),我接收节点Node_A已经没有能力处理你们发来的报文了。过载帧由过载标志和过载界定符构成。
位填充
为防止突发错误而设定,CAN协议中规定,当相同极性的电平持续五位时,则添加一个极性相反的位。填充位的添加和删除是由发送节点和接收节点完成的,CAN-BUS只负责传输,不会操纵信号。
- 对于发送节点而言:
在发送数据帧和遥控帧时,对于SOF~CRC(除去CRC界定符) 之间的位流,相同极性的电平如果持续5位,那么在下一个位插入一个与之前5位反型的电平;
- 对于接收节点而言:
在接收数据帧和遥控帧时,对于SOF~CRC(除去CRC界定符)之间的位流,相同极性的电平如果持续5位,那么需要删除下一位再接收。如果这个第 6 个位的电平与前 5 位相同,将被视为错误并发送错误帧。
- 位错误(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应答错误。这表示没有一个节点成功接收该帧报文。
- 帧起始到CRC之间,接收节点检测到有6个连续相同的位电平时,也就是违反5位相同位插入1位相反位的“位填充”原则。
- CRC错误:发送节点Node_A在发送数据帧或者遥控帧时,会计算出该帧报文的CRC序列。接收节点Node_B在接收报文时也会执行相同的CRC算法,如果接收节点Node_B计算出的CRC序列值与发送节点Node_A发来的CRC序列值不一致,那么接收节点就检测到一个CRC错误。
- 格式错误:在一帧报文发送时,如果在必须发送预定值的区域内检测到了非法值,即与任何一种帧格式都不符;CAN报文中,有预定值的区域包括:
数据帧和遥控帧的CRC界定符、ACK界定符、EOF;
错误帧界定符
过载帧界定符
错误状态的转换
一个CAN节点在什么情况下处于主动错误状态,什么情况下处于被动错误状态呢?
在CAN节点内,有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)
错误界定并非是依据错误的类型去界定CAN节点的错误状态,而是依据错误计数器【TEC/REC】的值来界定CAN节点的错误状态;当该节点检测到错误后,内部REC/TEC计数器会相应的增加,基于REC/TEC的值判定节点状态。
错误帧的发送
按照CAN协议的规定:
发生位错误、填充错误、格式错误、ACK错误时,则在错误产生的那一位的下一位开始发送错误帧。
发生CRC错误时,紧随ACK界定符后的位发送错误帧。
错误帧发送完成后,总线空闲时自动重发出错的数据帧。
关于波特率的计算:
总线上的各个通讯节点只要约定好 1 个 Tq 的时间长度以及每一个数据位占据多少个Tq,就可以确定 CAN 通讯的波特率。例如,假设1Tq=1us,而每个数据位由 19 个 Tq 组成,则传输一位数据需要时间 T(1bit) =19us,从而每秒可以传输的数据位个数为:1x10^6/19 = 52631.6 (bps),这个每秒可传输的数据位的个数即为通讯中的波特率。