前言
在做智能驾驶的公司实习,有些协议是必会的。好记性不如烂笔头,所以笔者开了一篇文章来记录学习的过程,方便大家交流,也方便我自己复习。这篇文章总结一下我在公司学的第一个协议,CAN。CAN协议使用差分信号,通讯稳定,而且错误诊断十分完备,安全性很高,因此广泛应用于汽车电子。这是我的第一篇文章,排版和叙述可能有些问题,大家将就看看。文末列了一些参考资料,写得都比我好。
CAN的背景
CAN-Controller Area Network,是德国公司Bosch在20世纪80年代初为了解决汽车中众多控制单元和仪器之间的实时数据交换而开发的一种串行通信协议。
在使用CAN协议之前,汽车的各种器件之间连线杂乱,这种情况下也想要保持同步以及高效地传输数据比较困难和麻烦。如图1:
CAN协议采用总线型拓扑方式的网络。各单元作为总线上的节点分布,有序高效地读取总线上的信息。我们都知道,总线型拓扑有一个问题需要解决——如何确保端用户使用媒体发送数据时不能出现冲突?
此外,节点是怎么筛选信息的?重要的信息如何保证优先级?以及如何保证信息不出错,正确的传达呢?我将在下面的内容中,慢慢解答这些问题。
CAN的通信机制
我们在这一节中,详细介绍CAN的各种性质,并且回答上面我们提出的问题。大家也可以想一想,与我的总结相互印证。
双线差分信号
首先,CAN的一个特性是采用双线差分信号。其实,我不知道采用这种信号到底有什么好处,所以我去百度了。
一般情况下,我们把电压1和0作为传输信号的手段。但实际上,这也是一种差分信号,只不过我们把“地”(GND)作为基准信号。这种情况下,系统的精确度就依赖于“地”的一致性。信号源和信号接收器的“地”的电压可能不同,所以在精度上无法得到保证。所以,采用双线差分信号的一大优点就显现出来了。因为基准电压也可以得到控制,信号源和信号接收器的基准电压就一定是相同的,而且精度也可以得到保证。
第二个优点就是抗干扰能力强。传统的电压传输,“地”是不受干扰的,但是传输中的信号就会得到干扰,所以会出现错误。但是采用双线差分信号,要干扰大家一起干扰,反正我们看的是差值,差值始终不受影响。
传统传输网络中只有0、1。但是,现在如果需要用到双极信号。我们就要把电压区间的一个任意值(一般是中点)看做是一个虚地(虚假的“地GND”)。高于这个值的是1,低于这个值的是-1。我们对地的要求就是要很稳定。无形中就是要求整个电路很稳定。但是双线差分信号就完全没有这样的顾虑。这就是第三个优点。不用电压稳定也能很稳定地传输信号。要求降低了但是质量不会降低。
理解了双线差分信号之后,我们就可以把它抛开了。我们就把它当成是0 1就行了。(只是当成是,实际上我们还是需要有双线差分信号这个概念的。)我在后面的叙述中也用1,0 来代替双线差分信号的隐性信号(1)和显性信号(0)。
为什么显性位是0,隐性位是1?
因为协议的制定者规定,ID越小,优先级越高。所以小的要显示出来。所以0是显性位。
不限制节点数量,并可以动态改变节点数量
广播发送报文
其实广播发送报文是报文机制的基石。因为是广播发送的,所以我们 他们才这么设计了CAN协议的报文结构。而且各节点在发送报文的时候,不能有干扰。在CAN协议中使用的是载波侦听多路访问/冲突避免(CSMA/CA)的方法。节点在发送报文之前,先侦听一下。如果有数据传输就不发送了,等着。否则,就立刻发送准备好的数据。
多路访问:各节点人人平等,并无高下(但是报文有啊),所以大家共用总线(而且都是广播)。
冲突避免:一边发着数据,一边要检测,看看是不是别人也在发,防止发生冲突,大家都白干活。
“回读”机制:节点一边发,一边还要检查发的是不是对的。
如果总线控制器发现ABC在同一时间发送报文。那到底是允许谁传输成功?优先级怎么判断呢?这里就必须提到报文的结构了。如图3、4:
报文的第一个结构是帧起始。只占1位,显性电平,标志着数据帧和远程帧(远程帧的作用是向其他节点请求发送相同ID的数据帧)的起始。真正决定报文优先级的是第二个结构仲裁段。标准的报文,在仲裁段有12位,11位ID以及一位RTR(远程发送请求)。(RTR是区别数据帧和远程帧的标志:显性为数据帧,隐性为远程帧)上面提到,ABC都在发,当他们发了第一位,控制器开始仲裁(所以ID放在前面,根据ID进行对比),如果一致就继续;如果不同的话,根据ID越小的优先级越高,所以就把发出隐性信号的节点设置为【只听】,禁止它继续发出消息,然后发出显性信号的节点继续。这就是“线与”机制。不过等到总线再次空闲的时候,节点会再次尝试进行重发。
接收过滤器:各个节点都有,也是根据ID进行判断,比较ID与选择器中和接收过滤相关位是否相同。存在一个掩码,掩码设置为1的位必须相同;为0则不用。
除此以外,CAN协议使用NRZ编码。NRZ编码确保报文紧凑,在相同带宽下,NRZ编码方式的信息量更大。但是NRZ有缺点,如果一长串的0或1会导致基线漂移,因为接收方会保持一个它所看到的信号的均值,通过均值区分高低电平。连续的0或1会导致均值改变,使检测信号中很难出现明显的变化。还有一个问题是,为了确保发送方和接收方同步需要有足够的跳变沿。因此CAN协议还使用了位填充的方法。即在连续5个1或连续5个0后插入一个反位。那不仅减少了连续的1或0而且还增加了跳变沿的数量。保证了同步性。
帧的结构
上面介绍了一部分的帧的结构。下面完整地介绍一下。以下内容参考文章:https://blog.csdn.net/sheweiwan/article/details/90413214
1.帧起始SOF
显性位一位,表明帧的开始
2.仲裁段
标准帧的仲裁段有12位,11位ID(序号是28-18)和1位的RTR。RTR是区别数据帧和远程帧的标志:显性为数据帧,隐性为远程帧。因此远程帧的优先级是不如数据帧的。
扩展帧的仲裁段有32位,前11位是ID,用SRR代替了RTR(所以SRR叫做代替远程请求位,隐性)因此,标准帧的优先级比扩展帧高。然后是IDE标识符扩展(区分标准帧和扩展帧,标准帧的IDE=0,隐性)再次表明标准帧的优先级,然后是扩展ID有18位(序号是0-17),最后是RTR。
3.控制段
标准帧的控制段包含6位,前两位为IDE、r位,IDE位不再赘述,r位是保留位,当前置0,后面 是DLC位占4位,表示数据段的长度,单位是字节。DLC位有4bit,所以DLC的值是0-15,数据段的最大长度是0-8,但是9-15也不算错误,而是默认为8。
扩展帧的控制段也是6位,前两位是r1、r0位,置0,后面是DLC位。
4.数据段
正如DLC位所表示的那样,数据段的长度不定,共有0-64位。但是远程帧是没有数据段的。
5.CRC段
共有16位,前15位是CRC位,然后 加一位DEL位。CRC位顾名思义,使用的是CRC循环校验。发送节点根据发送的序列计算一个CRC,接收节点也根据接收的序列计算一个CRC,两个比对一下,判断数据帧是否有效。DEL位是界定符,固定为隐性位,在界定符之前使用位填充。
6.ACK段
ACK段用于确认报文被至少一个节点正确接收。共有两位,第一位ACK位,接收节点正确接收之后用显性覆盖隐性,发送节点在回读的时候读到显性证明报文被正确接收。第二位是DEL位同上。
7.帧结束
最后是帧结束EOF共有7位,连续七个隐性位表示数据帧结束。
结束之后是ITM:三位,表示帧间空格,然后就可以继续发送下一帧了。
以上就是帧的结构,接下来就是帧的类型。
帧的类型
根据帧的长度不同分为标准帧和扩展帧。区别我们上面说过了,而且标准帧的优先级是高于扩展帧的。
根据帧的用处不同还分为数据帧、远程帧、错误帧、超载帧和帧间空间。
数据帧:数据帧携带从发送节点到接受节点的数据。格式就是上面说过的格式。
远程帧:向其他节点申请具有同一ID的数据帧。和数据帧的区别就是没有数据段。
错误帧:节点检测到错误之后发送错误帧。因为CAN协议的错误侦测比较完备,安全性高,所以这个要详细讲。
超载帧:6个显性位的超载标志和8个隐性位的超载定界符。在先行的和后续的数据帧(或远程帧)之间附加一段延时,表示满了,装不下更多数据了,不要再发送了。
帧间空间:一个3位的ITM+任意位个隐性位,表示总线正处于空闲状态,如果是错误帧之后还可能有别的变化,我们在错误帧的详细解释中给出介绍。
错误检测
CAN协议有十分详细的错误检测手段。一共有5种错误,位错误、位填充错误、CRC错误、ACK错误和格式错误。
位错误:节点回读的时候发现和自身发出的数值不同的位。不过仲裁或者ACK回读时送出隐性位,而检测到显性位则不导致位错误。正如上文所言,仲裁时有线与机制,而ACK回读时没读到显性位才是有问题的。
位填充错误:在使用位填充的段(CRC界定符之前),不允许出现连续6个相同的电平位。例如:111111、000000。
CRC错误:发送节点的CRC序列和接收节点计算的CRC序列不同。
格式错误:固定格式位含有一个或更多非法位。例如:r0、r1固定置0,DEL固定为0,但被置为1,就产生错误了
ACK错误:位错误中提及,ACK回读时没读到显性位就是有错。
位错误、填充错误、格式错误或者ACK错误,错误产生之后,在下一位发送错误标志。而CRC错误的错误标志在ACK界定符后发送,也就是EOF之前了。错误标志分为主动错误标志和被动错误标志。那么,什么时候应该发什么标志?
错误界定
每个节点有两个计数器,一个是REC接受错误计数器,一个是TEC发送错误计数器。发送错误是位错误、格式错误、ACK错误;接收错误是填充错误、格式错误、CRC错误。接收错误产生的时候,REC增加;反之,REC减少。TEC类似。REC和TEC的数值会引发节点状态改变。
节点的三种状态
1.主动错误
REC和TEC都在0-127。这种状态下,节点可以进行正常的总线通信,错误产生时发送主动错误标志(6个连续的显性位)
2.被动错误
REC或TEC≥128。这种状态下,进行受限制的总线通信,错误发生时发送被动错误标志(6个连续的隐性位)
3.总线关闭(Bus Off)
节点禁止参与总线通信。可以由用户申请恢复通信(发送128个11位隐性位)。
主动错误状态下和被动错误状态根据成功传输和失败传输改变REC和TEC进行状态的转化。两种状态下发出的错误帧的格式也不一样,主动错误标志是6个显性位,而被动错误标志是6个隐性位。然后是错误标志叠加,占据0-6个位,由于错误标志违背了位填充的规则,所以别的节点会发送错误标志,从而产生过了错误标志叠加。最后一段是错误界定符,8位连续隐性位。节点发送错误标志之后,监听总线,总线上出现隐性位后,节点发送剩下7个隐性位。
先写这么多吧,后面还有时序系统过于复杂。我暂时也没有理清楚。有缘再更新~