二、CAN链路层 也就是CAN控制器干了啥? 回顾完物理层,咱来看链路层,CAN帧的标准格式。当发送节的MCU将TX由1变0的时候,CAN收发器将CAN-H拉高&CAN-L拉低,接收节点收到了H-L>0.7V的压差后,接收节点的CAN收发器RX输出由1变0。下图是一个节点接收到CAN波形后解码出的RX逻辑。
一帧报文里边有比较关键的几段:仲裁段、控制段 、 数据段、CRC段、ACK段。 仲裁段中的大部分是CAN报文的ID,起名为“仲裁”其实是因为这一段有优先级仲裁的功能:假设A、B两个节点在同一时刻抢发报文,节点A要发二进制ID为001的报文,B要发010。当A、B节点都在发第一位的显性0的时候,总线会同时被两个节点驱动显性,A、B节点回读总线也都是显性,相互之间还意识不到对方的存在。当节点A发到第二位的0,节点B发到第二位的1的时候,总线只有节点A驱动显性0,节点B不驱动 却发现总线被别人驱动了,此时节点B会认为CAN线上有比自己这帧010优先级更高的数据,节点B就会主动停发,让节点A独占总线发完。之后节点B怀揣着这帧数据再次参与总线优先级的仲裁。 反直觉知识点①:CAN作为一个对等网络,没有主从关系,报文全部广播,节点本身也没有优先级概念,只有报文ID的优先级。可以这么理解:CAN节点是“由事件驱动的”,比如刹车制动器,它能发高优先级的“刹车被踩下”的报文,也会发低优先级的“刹车油位正常”的报文,这些报文根据ID的大小在总线上自由竞争优先级,而不是刹车制动器这个节点的话语权一定高。这个特性就要求设计人员提前规划好所有报文优先级和周期(即“通信矩阵”)才能保证整个CAN网络如期运转。如果你的CAN网络有大量雷同节点,节点又只有一帧报文,那么ID数大(优先级低)的节点一定会在总线繁忙或干扰重发的时候"插不上话",可以试试把时间戳融合到ID里边,确保各节点的新数据优先级最高,旧数据自然会被仲裁掉。 反直觉知识点②:在A、B节点同时驱动第一个显性0的时候,总线被两个节点同时驱动,电压会显著高于2V。示波器上会看到在仲裁段的头部有明显的电平凸台,后续节点A抢占总线之后电压会回归正常的2V。 反直觉知识点③:各个节点的时钟同步是把每个bit做16~20份的数字切片来实现的,这个切的份数不建议太多或太少。详细机制请参阅 ZLG致远电子的这篇:CAN同步机制,你真的了解吗? 控制段中有几个控制位,这里拿几个常用的举例。IDE位为扩展ID的指示。如果IDE位为隐性1,就会在后边再续上18位的ID,共11+18=29位长度。比如0x9E就是个11位长度的ID,0x0151就是个29位的ID。R0位是CAN里边的预留位,在CAN-FD里被用作FD帧格式的标志位FDF,这一位为隐性1就会按FD的帧格式解码后续报文。DLC指示了后边的数据段的长度,例如1000表示后续会有8个Byte长度的数据。CAN-FD协议只在数据段会切换成高速率,比如2Mbps/8Mbps,前后其他段的速率保持500kbps不变。 反直觉知识点①:CAN与CAN-FD除了数据段波特率的不同,帧格式也有区别,CAN-FD多了一些控制位。比如FDF(也叫EDL)位用来指示是否按FD帧格式解码,BRS位用来指示是否需要切换高波特率,也就是说,一个FD帧可以全程500kbps不切速率的。 反直觉知识点②:CAN控制器的标准ISO11898-1里要求接收方不解读R0位的显隐性,所以CAN的控制器无法过滤FD帧。标准CAN网络里边一旦出现FD帧会因为多了BRS、ESI等控制位被认为是格式错误。同样的,因为CAN 2.0时代R0/FDF帧无意义,也有一些设备把发送出去的CAN帧的R0位错误地置了隐性1,这样的设备在CAN网络里一切正常,但若进入CAN-FD网络就会被解读成FD帧,进而因为缺少BRS、ESI等控制位被认为是格式错误。所以,CAN-FD并不是真的向下兼容CAN,因为旧时代的CAN设备并没有判别R0/FDF位的能力,一旦它进入FD网络就会疯狂地打断通信。 反直觉知识点③:DLC的长度,在CAN标准里DLC可以是0000~1000之间的二进制值,可以用8421的算法直接计算出数据长度。而在CAN-FD中,1001~1111之间的值则被解读为离散的12,16,20,24,32,48,64byte。 CRC段对于从帧头到Data结束之间的数据,CAN协议使用了CRC15这个比较特别的多项式计算校验,有兴趣的可以手算CRC试试。CAN-FD根据数据长度的不同使用了CRC17和CRC21,这里暂不做展开。 ACK段是由收到该帧的CAN节点回复的确认(Acknowledge)。注意 发送节点在ACK位一定发的是隐性1,由接收节点回应显性0,双方无缝衔接才在总线上呈现出一个完整的CAN报文。 反直觉知识点①:总线上任何节点 只要认为这个帧的结构正确,都会在ACK位回显性0,不管需不需要这一帧的ID和数据。为什么不需要的节点也会回ACK?因为等MCU算完会造成这一位的延迟,搅乱总线时序,不如只保障链路层本身的格式正确,纯芯片数字逻辑实现无延迟。嗯,90年代的总线要求不要太高。 反直觉知识点②:发送节点若发现自己这一帧没有ACK回应,它也会认为总线出错,重发16次后进入Passive error状态,有兴趣的自行研究一下,这里不做展开。
|