编译附件的工程,并阅读了对应的描述文件之后,初步认为:CAN总线负载率过高,导致设备循环进入bus off状态。可以尝试通过查看总线过载帧,错误帧的发送情况,减少总线节点等方法判断。
下面是详细说明:
现象:
测试条件:CAN总线接入三路不同波特率的设备节点,
一路是1Mbps波特率, 20-30条周期在10ms左右的发送报文,同时存在两三条1ms发送周期的报文。
一路是500kbps波特率,20-30条周期在10ms左右的发送报文,同时存在两三条1ms发送周期的报文。
一路是250kbps波特率,20-30条周期在10ms左右的发送报文,同时存在两三条1ms发送周期的报文。
我们的控制器也会是一个节点,连接到总线上去,波特率为250kbps。
我们程序中,设计了一个状态指示灯功能,周期性的进行闪烁。
1,如果我们程序中,加入了一项功能,就是一旦检测到CAN总线 bus error或者busoff的情况,会重新初始化can模块,进行恢复。
这种情况下,其他三个节点不断电的情况下,我们控制器断电重启,大概率会出现指示灯不再闪烁的情况,像是程序跑飞的情况。
这种状态下,如果拔掉一两个设备节点,指示灯正常周期性的进行闪烁,程序跑飞的情况消失。
2, 我们程序中,也会检测CAN总线 bus error或者busoff的情况,但是不会重新初始化can模块,不进行CAN恢复。
这种情况下,其他三个节点不断电的情况下,我们控制器断电重启,再也不会出现指示灯不再闪烁的情况,功能表现正常。
我们整个测试下来,归根到底,也是模拟CAN总线上出现bus error或者bus off的情况,最终调用CAN初始化函数(包含CAN_Deinit()反初始化函数和CAN_Init()初始化函数),
CAN_Deinit()反初始化函数和CAN_Init()初始化函数,这些都是 RTM SDK 3.0.0 CAN 模块接口函数,这里面会引发程序停在某个地方,不再继续执行的情况。
我们尝试过在包含CAN_Deinit()反初始化函数和CAN_Init()初始化函数中,所有出现while()的地方,都加入计数机制,到达某一个值就退出循环,但依然还会出现程序停在某个地方,不再继续执行的情况。
1. 以250kbps为例,10ms内总线上约有20+2*10=40帧报文,以数据帧平均一帧100bit,粗略计算总线负载率:
10ms总线需传输40*100 = 4000bit数据,250kbps传输1bit所需时间4us, 4us*4000 = 16ms,已经超出10ms周期,
即使是1Mbps波特率,负载率粗略计算也在40%,
另外根据情况的描述,
1)拔掉节点,属于减轻负载率
2)不初始化CAN模块,不进行CAN恢复,属于禁止设备循环进入Bus off中断
所以,根据目前信息,初步判断是总线负载率过高导致。
2. 官方提供的API接口都是经过验证的,一般情况下,不会有所描述的死循环问题,所以建议先尝试从总线负载率方向查找原因。