如何应对CAN总线冲突和数据丢包
1 摘要
设计STM32的CAN总线功能时,如何使用软件策略、协议机制、硬件特性来处理总线冲突和数据丢包。
2 总线冲突
2.1 定义
CAN 总线是一种多主广播通信协议,如图为CAN总线拓扑结构图,所有节点挂载到同一条总线上,单一模块只需开放一路CAN接口即可和所有设备完成通讯。这种总线型拓扑架构,天然支持分布式系统,对于系统维护十分友好。
由上图可知,CAN通信是通过两根线完成的:
- 一条CAN_High
- 一条CAN_Low
两者电平差<0.5V时,为隐性状态,逻辑信号表现为"逻辑1",两者电平差>0.5V时,为显性状态,逻辑信号表现为"逻辑0"。很明显当有个 设备输出显性状态时,会干扰到其他设备输出的隐性状态。
即总线冲突的定义:当两个设备同时在总线上发送信息时,显性电平会吞并阴性电平,使发送的信息与总线上的实际信息不一致,即产生总线冲突。
2.2 应对-协议机制
CAN总线协议本身已经考虑到了总线访问冲突的问题,并通过非破坏性仲裁机制来解决。当多个节点同时尝试发送消息时,具有更高优先级(即ID值更小,显性电平先出现)的消息将赢得仲裁并继续发送,而其他低优先级的消息会自动退出发送,不会造成物理层面上的冲突。例如,如下图所示Node2和Node1同时发送信息,Node2在第7位数据时,竞争失败,于是停止发送消息。
2.3 应对-硬件设置
- 自动重发,STM32中可以设置CAN_MCR寄存器的NART为0,以此启动自动重发功能,当前节点在总线仲裁失败时,在等待总线空闲后,会自动发起数据的重新发送。
- FIFO设置,STM32中可以设置CAN_MCR寄存器的TXFP为0,以此取消FIFO模式,使3个发送邮箱按照ID号优先级进行发送,先发送优先级高的数据。
- 错误管理,当有频繁的冲突时,有可能是总线某个设备发生了异常,导致其频繁干扰总线,就像是群聊里面进了一个疯子,一直疯言疯语。可以借助STM32中错误管理机制,当错误累积一定数量时,使错误设备主动“下线”,变为静默模式,只对总线进行监听,不再发送。
2.4 应对-软件策略
合理的ID分配:
- 对实时性需求不同的消息分配不同的ID,以保证关键信息的传输优先级,这样比较重要的消息,就不会被其他次要的信息所打断。
综合优化消息发送时机: - 传输监测数据的数据包,在满足需求的情况,尽可能降低发送频率,或者被监测数据发生变化时再发送
- 设置通讯主机+从机模式,使用主机在总线上发送同步信号,使用同步信号统一指挥从机,从机监听信号,可以设置从机监听到多少次同步信号后才发送数据,对不同的从机设置差异化的同步机制,使各个子设备错拍发送。
使用成熟CAN协议栈: - 例如,使用CANopen协议栈,里面使用PDO和SDO通讯对象完成周期性传输和可靠性传输,上述“优化消息发送时机”已在协议栈中设计好,调用对应API即可。
设置发送缓存: - 极端阻塞情况下,需要借助发送缓存机制,防止数据包在一段时间内一直发布出去。当然缓存不宜过长,CAN总线本来就是现场总线,可以计算出最大的延时量,设置好缓存长度,当缓存队列溢出后,可以设置对应回调函数,通知上层应用此异常状况。
3 数据丢包
3.1 定义
- 传输过程丢包,尽管CAN总线具有良好的错误检测和自我恢复能力,但在高负载或恶劣电磁环境下,仍可能出现数据丢包的情况。
- 中断延迟过大丢包,导致设备没有响应CAN数据接收中断,导致接收FIFO溢出而数据丢包。
3.2 应对-协议机制
- 重传机制:利用CAN控制器内置的自动重传功能。如果一帧数据成功发送,但在ACK位未被响应,可激发自动重发机制。
3.3 应对-硬件设置
- 优化过滤器设置:合理设置接收过滤器,只接收自己需要的ID,可以减少不必要的中断和服务,从而降低系统负荷,提高响应速度。
- 增强硬件抗干扰能力:选择合适的CAN收发器,并注意PCB布局、信号完整性等硬件设计细节,可以有效地提高系统的稳定性,减少外界干扰导致的数据丢包。
3.4 应对-软件策略
- 设置接收缓存,同上面发送缓存一样,不要设置太长,否则会影响实时性,根据自身实时性设置缓存长度大小。当数据接收中断产生时,在中断中仅将数据搬运到缓冲区,并使用信号量或者任务通知等机制通知应用部分及时进行处理,在中断中不要做复杂的协议处理,以免错误最新数据。
- 中断延迟,测量好系统的中断延迟(CAN RX接收中断产生到处理的时间),有时数据丢包,可能不是ISR运行时间过长,导致错过了数据包,而是中断延迟时间太长,导致数据丢包。中断延迟包含:中断屏蔽+中断嵌套+Sbus压栈(包含总线竞争)+向量表加载 ,注意上述这4个可能导致中断延迟过大的因素,合理设置好中断屏蔽时间,防止中断嵌套过多(使用优先级分配组),对中断向量表加载速度进行内核级优化处理。