本帖最后由 lengrudie 于 2024-8-27 16:53 编辑
#申请原创# 机缘巧合下获得了极海G32A1445的开发板,资源挺丰富的,可以说是车规芯片里性价比比较高的一款芯片了。但是在使用CAN的过程中,却遇到了一点问题,之后就是各种怀疑各种分析仿真,经过几天的努力终于是找到问题了,现在分享一下我遇到问题的现象和解决的过程,让大家避坑。 现象: CANFD程序设置500Kbps,用定时器定时50ms周期发送报文,用CANPRO工具尽可能快的周期(这个工具最快的发送周期只能是1ms)发送10个不同的地址报文,即开发板一直50ms周期发送报文,CANPRO上位机也一直发送报文。使用中出现一开始报文能正常发送和接收,过一段时间之后只能接收,不能发送,程序里一直是周期发送的。大部分情况下在4~15分钟后就会出现开发板只能接收不能发送的情况。 先看现象,下图是CANPRO发送的数据,正常是有接收也有它自身发送的报文显示:
异常情况时,就只有CANPRO自己发送的数据,停止发送后,也看不到开发板发来的数据:
一、CAN配置有问题吗?
大脑第一想到的就是CAN配置问题,毕竟波特率没问题不代表采样点的位置是最佳的,同样的波特率配置组合有很多种,如下是我的CAN配置、初始化:
又翻出手册来看,CAN的采样点位置没有问题,配置流程也是按手册来执行的。
二、CAN模块有报错误标志吗? 只能连着JLINK仿真了,如下是出现发送异常后的寄存器值(CAN0 ERR**1寄存器):
CAN正常发送时ERR**1=0x40008(其中OVR**=0),当出现异常情况发不出报文时OVR**=0,ERR**1=0x40008,即寄存器没有报异常。 其实这时候我是比较放心的,毕竟没有出现硬件错误,也就是说CAN总线终端电阻、CAN通信配置也没有问题。但问题依旧在,还需要继续定位问题,必须揪出程序里的BUG。 都已经在仿真了,那就继续仿真吧,当CAN发送异常的时候,发送函数进入了如下的位置:
每次发送数据前会先检查上一次发送是否完成,发送状态是否处于CAN_MB_STATE_IDLE状态,如果不是IDLE状态则不继续发送。继续跟踪这个状态在什么情况下会改写的吧。 跟踪发现除了初始化会置位为IDLE,还在void CAN_IRQHandler(uint8_t index)中断函数里,发送完成进入中断就会置位为IDLE,那就是没有进入中断了? 继续仿真: 果然,发送和进入中断的次数是不一样的,如图发送执行了253次,发送完成中断只有252次。似乎越来越有意思了!!我要成柯南了!!! 那么为什么不进中断?难道中断标志自动清除了,不应该吧?
三、中断标志还在吗? 如下图,在CAN异常的时候,虽然发送状态还是BUSY状态,但发送完成标志已经是被置位了,也就是说标志没有被清掉。
那就更觉得奇怪了,发送完成标志也置位了,为什么不进中断? 四、中断使能成功了吗? 不知道细心的你,是否也发现了,上面的那个图,其实已经说明了一切。I**是发送完成标志,是置位的状态,但是MBiIEN这个寄存器的值是0,这个是中断使能寄存器,也就是说这时候是不使能的,那怎么可能进中断?中断定位到了,但问题又来了,谁清掉了这个寄存器? 五、谁清了中断使能? 通过仿真发现,只要执行了下面接收续订函数就容易出现: status = CAN_ReceiveNonBlocking(CAN0_INSTANCE,RX_MB, &rxFrame);
这个函数里面执行的相关的寄存器操作如下:
然而,发送函数里也有这个函数调用,都操作了同一个寄存器,元凶终于找到了,只要想办法在调用这个函数操作时不要被打断就解决了。 测试两个小时都没有出现。完美如下:
|
很有意思的一篇文章,开篇点明故障现象:上电CAN正常收发,一段时间后只能接受不能发送。随后随着作者的调试推进,以五连问的方式逐步排查出问题所在并给予解决。思路清晰,处理得当。解决问题的方式值得学习。(ps:大佬后续再申请原创时请@21小跑堂,以便您的文章能及时审核~~)