本文主要是介绍通信协议学习:CAN总线协议,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
以下的学习主要是观看江科大视频后的总结,需要学习建议观看原视频:https://www.bilibili.com/video/BV1vu4m1F7Gt/?p=1&spm_id_from=pageDriver&vd_source=0a52d160c212359f7f490eb9a868d174
CAN总线简介
CAN总线(Controller Area Network Bus)原名控制器局域网总线。
CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线,广泛应用于汽车、嵌入式、工业控制等领域。
CAN总线特征:
- 两根通信线(CAN_H、CAN_L),线路少,无需共地
- 差分信号通信,抗干扰能力强
- 高速CAN(ISO11898):125k~1Mbps, <40m
- 低速CAN(ISO11519):10k~125kbps, <1km
- 异步,无需时钟线,通信速率由设备各自约定
- 半双工,可挂载多设备,多设备同时发送数据时通过仲裁判断先后顺序
- 11位/29位报文ID,用于区分消息功能,同时决定优先级
- 可配置1~8字节的有效载荷,也就是1-8字节的数据
- 可实现广播式和请求式两种传输方式。广播式就是一个设备发送数据,其他所有设备都能收到,接收方根据报文ID来决定是否使用数据;请求式就是数据方不会主动广播消息,只有收到接收方发送的请求才发送数据。
- CAN总线还包括应答、CRC校验、位填充、位同步、错误处理等特性
CAN总线硬件电路
CAN总线的硬件电路有两种,分别是高速CAN和低速CAN,电路结构如下,
通过以上接线电路,有以下总结,
- 每个设备通过CAN收发器挂载在CAN总线网络上,CAN收发器就是一个芯片,主要实现电平转换,输出驱动,输入采样等功能
- CAN控制器引出的TX和RX与CAN收发器相连,CAN收发器引出的CAN_H和CAN_L分别与总线的CAN_H和CAN_L相连
- 高速CAN使用闭环网络,CAN_H和CAN_L两端添加120Ω的终端电阻,加入电阻的作用第一是为了防止回波反射,第二是在没有设备操作时,可以让两条线的电压在同一水平,代表的是默认的1的状态。
- 低速CAN使用开环网络,CAN_H和CAN_L其中一端添加2.2kΩ的终端电阻。
CAN电平标准
CAN总线采用的是差分信号,和RS485类似,即两线电压差(VCAN_H-VCAN_L)传输数据位。
高速CAN规定:
电压差为0V时表示逻辑1(隐性电平)
电压差为2V时表示逻辑0(显性电平)
在这里的理解,我们可以看成逻辑1就是总线收紧,逻辑0是总线张开。
低速CAN规定:
电压差为-1.5V时表示逻辑1(隐性电平)
电压差为3V时表示逻辑0(显性电平)
总结以上的物理层特性,如下表
CAN总线帧格式
CAN总线规定以下5种类型的帧,
数据帧
CAN总线的数据帧格式分为两种,标准格式和扩展格式,扩展格式增加了ID位数,可以承载更多种类的ID。
以下是数据帧的格式,
根据上述帧格式分析,
- 发送数据帧之前,总线需处于隐形电平状态,也就是逻辑1
- 数据帧起始位(SOF)必须为显性电平,也就是逻辑0
- 发送报文ID,位数为11位,用于表示后面数据的功能和区分优先级
- RTR在数据帧中必须为显性电平0,意思是远程请求标志位,用来区分数据帧(0)和遥控帧(1)
- IDE叫做扩展标志位,用来区分标准格式(0)和扩展格式(1)
- r0是一位保留位,如果后续需要升级时可能用到
- DLC,位数位4,用来表示数据段的长度,指示数据段有几个字节
- Data表示的是数据段的1~8个字节有效数据
- CRC表示的是校验,根据CRC校验算法检测数据是否准确
- ACK槽是应答位,用来判断数据有没有被接收方接收。基本思想是当发送方发完一帧数据主要内容后,应答这一位时发送方会释放总线,此时总线回归默认状态隐性1,如果此时接收方收到数据的话,就会将ACK槽呈现显性0的状态,最后发送方会读取总线状态,如果读取的是0则表示有接收方对总线进行操作,则表示数据被接收。
- 由上述过程可以知道,在ACK槽前后操作总线的权利是有变化的,CRC界定符和ACK界定符就是用来给这个过程留出时间和界定接收方操作总线的时间
- 在ACK槽处,可以存在多个接收方操作总线总线,也可以知道,整个波形的过程是由发送方和接收方一起完成的
- EOF表示帧结束,为7位,表示数据位已经传输完毕
- SRR是在扩展格式中替代RTR,属于协议升级时留下的无意义位
遥控帧
遥控帧和数据帧类似,只是没有数据段,并且RTR为隐性电平1,其他部分与数据帧相同。
很显然,遥控帧(1)和数据帧(0)通过RTR进行区分,当接受方收到的RTR是1的话就会按照上述遥控帧的格式进行解析,遥控帧是没有数据位的,代表发送方想要请求数据。
根据上述数据帧我们知道,一次完整的请求是需要遥控帧和数据帧的配合完成,遥控帧的ID用于匹配响应请求一方的ID。
当请求数据和反馈数据同时发送时,数据帧拥有更高优先级,原因就是因为RTR位。
错误帧
总线上所有设备都会监督总线的数据,一旦发现“位错误”或“填充错误”或“CRC错误”或“格式错误”或“应答错误” ,这些设备便会发出错误帧来破坏数据,同时终止当前的发送设备
设备默认处于主动错误状态,当设备检测出错误时,会连续发6个显性位(0),用线与的特性破坏总线数据。
处于被动错误状态,当设备检测出错误时,会连续发6个隐性位(1),用线与的特性就无法破坏总线数据。
过载帧
当接收方收到大量数据而无法处理时,其可以发出过载帧,延缓发送方的数据发送,以平衡总线负载,避免数据丢失
过载帧是由接收方产生的,其实就是表示接收方还没有完全做好接收准备,所接收的数据过载了,帧格式和错误帧类似。
帧间隔
帧间隔是负责将数据帧和遥控帧与前面的帧进行分离开来。
备注:错误帧,过载帧和帧间隔等设计的非常繁琐,如果需要了解建议还是观看CAN总线相关手册。
CAN总线位填充
CAN总线的位填充规则为,发送方每发送5个相同电平后,自动追加一个相反电平的填充位,接收方检测到填充位时,会自动移除填充位,恢复原始数据。
比如,当你即将发送的电平为 10000011110 时,实际发送的电平经过位填充是 1000001111100 ,同时实际接收的也是 1000001111100 ,位填充被移除后就恢复原始数据 10000011110
位填充的作用如下,
- 增加波形的定时信息,利于接收方执行“再同步”(后续介绍),防止波形长时间无变化,导致接收方不能精确掌握数据采样时机,比如当我们发送8个字节的FF时,就是接收方需要接收64个1,这时候如果接收方时钟稍有误差的话,就可能产生接收错误,因为没有跳变沿就无法确定采样点是否在中间和采样点位置是否准确,也就无法执行再同步
- 将正常数据流与“错误帧”和“过载帧”区分开,标志“错误帧”和“过载帧”的特异性,因为错误帧和过载帧都为连续的6个相同的电平
- 保持CAN总线在发送正常数据流时的活跃状态,防止被误认为总线空闲
以下给出 波形的示例,大家可以对照一下上述的知识点,
标准数据帧,报文ID为0x555,数据长度1字节,数据内容为0xAA
扩展数据帧,报文ID为0x0789ABCD,数据长度1字节,数据内容为0x56
标准遥控帧,报文ID为0x088,数据长度1字节,无数据内容
接收方数据采样
CAN总线是异步通信,没有时钟线,总线上的所有设备通过约定波特率的方式确定每一个数据位的时长。
发送方以约定的位时长每隔固定时间输出一个数据位
接收方以约定的位时长每隔固定时间采样总线的电平,输入一个数据位
理想状态下,接收方能依次采样到发送方发出的每个数据位,且采样点位于数据位中心附近
但是,现实世界存在一定的区别,比如接收方以约定的位时长进行采样,但是采样点没有对齐数据位中心附近或者接收方刚开始采样正确,但是时钟有误差,随着误差积累,采样点逐渐偏离。
位时序
为了灵活调整每个采样点的位置,使采样点对齐数据位中心附近,CAN总线对每一个数据位的时长进行了更细的划分。
每一个数据位分为同步段(SS)、传播时间段(PTS)、相位缓冲段1(PBS1)和相位缓冲段2(PBS2),每个段又由若干个最小时间单位(Tq)构成。
- 理想化的波形的每个跳变沿都在SS段。
- 由于硬件电路限制,信号输出到总线总会存在延迟(数据输入同理),PTS段就是回来等待这个延迟过去
- PBS1和PBS2段是为了确定采样点的时间,采样点的设定在PBS1和PBS2段的中间。
配置示例如图,
其中SS段为1Tq,PTS段为1-8Tq,PBS1段为1-8Tq,PBS2段为2-8Tq,
硬同步
硬同步是为了解决第一个问题,接收方以约定的位时长进行采样,但是采样点没有对齐数据位中心附近。
每个设备都有一个位时序计时周期,当某个设备(发送方)率先发送报文,其他所有设备(接收方)收到SOF的下降沿时,接收方会将自己的位时序计时周期拨到SS段的位置,与发送方的位时序计时周期保持同步
硬同步只在帧的第一个下降沿(SOF下降沿)有效
经过硬同步后,若发送方和接收方的时钟没有误差,则后续所有数据位的采样点必然都会对齐数据位中心附近
硬同步示例如下,
再同步
再同步是为了解决第二个问题,接收方刚开始采样正确,但是时钟有误差,随着误差积累,采样点逐渐偏离。
若发送方或接收方的时钟有误差,随着误差积累,数据位边沿逐渐偏离SS段,则此时接收方根据再同步补偿宽度值(SJW)通过加长PBS1段,或缩短PBS2段,以调整同步
再同步可以发生在第一个下降沿之后的每个数据位跳变边沿
此处的SJW指的是补偿误差的最大值,可以自己选择,一般选择的范围是1-4Tq
时钟误差导致的采样点偏离存在以下两种结果,
- 接收方时钟相对于发送方时钟快了,这时候就需要将位拉长一点
- 接收方时钟相对于发送方时钟慢了,这时候就需要将位减短一点
波特率计算
波特率表示的是每秒传输码元的大小,在二进制中一个码元等于一个比特位,所以波特率计算为,
波特率 = 1 / 一个数据位的时长 = 1 / (TSS + TPTS + TPBS1 + TPBS2)
CAN总线资源分配
因为CAN总线只有一对差分信号线,同一时间只能有一个设备操作总线发送数据,若多个设备同时有发送需求,就无法合理分配总线资源。
解决该问题的思路是,制定资源分配规则,依次满足多个设备的发送需求,确保同一时间只有一个设备操作总线。
资源分配规则1
资源分配的规则1,简单来说就是先到先得。
适用的场景时,当前已经有设备正在操作总线发送数据帧/遥控帧,则其他任何设备不能再同时发送数据帧/遥控帧(可以发送错误帧/过载帧破坏当前数据)
任何设备检测到连续11个隐性电平(1),即认为总线空闲,只有在总线空闲时,设备才能发送数据帧/遥控帧
一旦有设备正在发送数据帧/遥控帧,总线就会变为活跃状态,必然不会出现连续11个隐性电平,因为有位填充机制,其他设备自然也不会破坏当前发送
若总线活跃状态其他设备有发送需求,则需要等待总线变为空闲,才能执行发送需求
资源分配规则2
资源分配规则2,使用的机制是非破坏性仲裁。
适用场景是,多个设备的发送需求同时到来或因等待而同时到来,则CAN总线协议会根据ID号(仲裁段)进行非破坏性仲裁,ID号小的(优先级高)取到总线控制权,ID号大的(优先级低)仲裁失利后将转入接收状态,等待下一次总线空闲时再尝试发送
实现非破坏性仲裁需要两个要求,
- 线与特性:总线上任何一个设备发送显性电平0时,总线就会呈现显性电平0状态,只有当所有设备都发送隐性电平1时,总线才呈现隐性电平1状态,即:0 & X & X = 0,1 & 1 & 1 = 1
- 回读机制:每个设备发出一个数据位后,都会读回总线当前的电平状态,以确认自己发出的电平是否被真实地发送出去了,根据线与特性,发出0读回必然是0,发出1读回不一定是1
以下是非破坏性仲裁示例图,
数据位从前到后依次比较,出现差异且数据位为1的设备仲裁失利。
可以看到,两个单元的波形是同时开始的,因为不同时开始的波形,规则1就可以解决冲突问题。
经过线与特性,仲裁段的数据为1的设备回读时回读为0(红色部分),此时设备1会意识到数据出错,自动退出,也就是仲裁失利。
ID号小优先级越高,是因为ID号越小的话,也就是数据中的1出现的越晚,仲裁失利的可能性也就越低,就比如假如ID段数据是全0的话,那么无论如何经过线与规则后也不会失利,也就一定能从多个设备的仲裁中胜出,也就是优先级越高。
从仲裁胜利者视角看,由于每一次回读的数据都和自己一样,所以整个过程没有收到任何影响,所以是非破坏性的。
位填充不会导致仲裁出问题。
备注:
- 数据帧和遥控帧ID号一样时,数据帧的优先级高于遥控帧。这是因为遥控帧的RTR值为1而数据帧RTR为0,在仲裁时数据帧会胜出。
- 标准格式11位ID号和扩展格式29位ID号的高11位一样时,标准格式的优先级高于扩展格式。这是因为扩展数据帧的高11位后是一位SRR,该位始终为1,经过仲裁之后还是标准数据帧会胜出。
- 标准遥控帧11位ID号和扩展格式29位ID号的高11位一样时,标准遥控的优先级高于扩展格式。这种情况下,由于标准遥控帧的11位ID后面跟的RTO值为1且仲裁段结束,看起来好像两个格式完全一样会出错,但是由于扩展格式的仲裁段并未结束,而扩展格式后续跟的是IDE且必须为1,而标准遥控帧后续跟的IDE值必须为0,所以最终扩展遥控帧胜出。
CAN总线错误处理
CAN总线规定了五种总线错误类型,位错误、填充错误、CRC错误、格式错误、应答错误。
对于CAN总线通信的错误状态,包括两种,主动错误状态和被动错误状态。
主动错误状态的设备正常参与通信并在检测到错误时发出主动错误帧,可以破坏数据。
被动错误状态的设备正常参与通信但检测到错误时只能发出被动错误帧,不会破坏数据。
当设备在频繁破坏数据时,就会从主动错误状态转向被动错误状态,同时,如果设备还是频繁报错的话,那就会转向总线关闭状态。
总线关闭状态的设备不能参与通信
错误状态评定标准:每个设备内部管理一个TEC和REC,根据TEC和REC的值确定自己的状态。
以下是设备的错误状态转移图,
以下是各种错误的计数值,
这篇关于通信协议学习:CAN总线协议的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!