目录
问题一:两个can设备无法相互间收发数据
板子的两个can总线对接,收发正常,can分析仪的两个can总线对接,收发也正常。偏偏将板子接到分析仪上,收发均有问题。
原因:
波特率不同,分析仪的波特率好设置,在软件界面中选好,主要侦测波特率也要选择正确。
板子的波特率是根据主频和can芯片几个寄存器的值算出来的,计算公式为:BaudRate = APBCLK/BRP*(1+BS1+BS2) APBCLK由sysclk倍频而来,有软件在输入APBCLK之后,可以计算出对应的BRP BS1和BS2的值。
问题二:can接收中断接收不到数据
我遇到过两种情景:
1、有接收过滤filter,去掉过滤条件或者把期待接收的报文id加入过滤条件中便能解决
2、硬件断电重启后无法进入can的接收中断,当硬件reset后接收中断恢复正常:
猜测原因:
(我的硬件环境是mcu外接8M晶振)。硬件上电和硬件reset两种场景下,硬件的初始化时序不一样:系统时钟启动之后,多等待一段时间,等待时钟稳定了,再倍频到APB1,最后再初始化APB1总线上的can资源。
硬件上电时系统时钟还没准备好就初始化can总线,can的接收中断无法触发。上电后,时钟已经ok,硬件reset后can相应的初始化自然能生效。
解决方案:
方案有两个:
(1)方案1
上电后执行NVIC_SystemReset()做软重启,这种方法导致程序反复重启。除非硬件上电有一个独一无二的条件出现,并且软件能感知到。
(2)方案2
在设置系统时钟之后,增加2秒的延时时间。问题成功解决!!!
问题三:GD32的can的过滤功能怎么用呢
列表模式好操作,掩码模式难点:
列表模式就是只接收指定id的报文,掩码模式是接收id在某个段内的报文。
列表模式过滤标准帧的流程(使用can0总线):
1、选选择过滤器,设置模式为列表模式,位宽为32位
can_filter_parameter_struct can_filter;
can_struct_para_init(CAN_FILTER_STRUCT, &can_filter); //初始化为0
can_filter.filter_number = 0; // GD32F4xxx有28个过滤器,这里选择0
can_filter.filter_mode = CAN_FILTERMODE_LIST;
can_filter.filter_bits = CAN_FILTERBITS_32BIT;
2、过滤指定id
can_filter.filter_list_high = 0x5A5 << 5; // 0x5A5可以通过该过滤器;
can_filter.filter_list_low = 0x0000;
can_filter.filter_mask_high和can_filter.filter_mask_low使用初始化值即可
filter_list_high和filter_list_low分别表示过滤器单元有2个寄存器CAN_FxDATA0和CAN_ FxDATA1,而两者加起来共32位,CAN_FxDATA0存放SFID(标准帧的ID)的低11位。
为什么要左移5位呢,0x5A5 << 5之后刚好可以存放在16位的CAN_FxDATA0中。
3、通过过滤器后绑定到FIFO0并使能过滤
can_filter.filter_fifo_number = CAN_FIFO0;
can_filter.filter_enable = ENABLE;
can_filter_init(&can_filter);
关于标准帧的掩码模式,我有一个可用的demo,但是暂时还没搞清楚原理。
can_filter_parameter_struct can_filter;
can_struct_para_init(CAN_FILTER_STRUCT, &can_filter); //初始化为0
can_filter.filter_number=1; // 过滤器序号1
can_filter.filter_mode = CAN_FILTERMODE_MASK; // 掩码模式
can_filter.filter_bits = CAN_FILTERBITS_32BIT; // 使用32位模式
can_filter.filter_list_high = 0x4FF << 5;
can_filter.filter_list_low = 0x0000;
can_filter.filter_mask_high = (0x700 << 5) ; // 0x400-0x4FF可以通过该过滤器;
can_filter.filter_mask_low = (1U << 2); //必须匹配
can_filter.filter_fifo_number = CAN_FIFO0; //通过过滤器后绑定到FIFO0
can_filter.filter_enable = ENABLE;
can_filter_init(&can_filter);