zero99 发表于 2016-8-30 15:47:16

【实战经验】基于Cube库无法检测CAN2的接收中断

基于 Cube库无法 检测 CAN2的接收中断
1 前言
       本文将针对客户在使用Cube库时CAN2不能产生接收中断进行分析。

2 问题描述
       客户使用的是STM32F105,同时用到了CAN1与CAN2,使用cube库,但有个奇怪的现象,CAN1能正常工作,CAN2却无**常产生接收中断,CAN1与CAN2的代码几乎没有什么差别。


3 重现问题
       实验使用STM3210C-EVAL评估板,这款板子有同时将CAN1和CAN2引出,此板上的MCU为STM32F107VC,与客户所用到的STM32F105只多了个Ethernet外设,其他无差别,正适合用来验证此问题。

3.1 工程制作
       使用cubemx生成工程,cubemx得配置如下图:





       配置波特率为500K,自动离线使能。
       点击生产代码,在main函数内的/* USER CODE BEGIN 2 */与/* USER CODE END 2 */添加:




       在main函数内的/* USER CODE BEGIN 3 */与/* USER CODE END 3 */添加:


3.2 测试重现问题现象
       使用ZLG的USBCAN-2E-U盒子与STM3210C-EVAL评估板以及PC连接进行测试:

       在调试下,在PC端软件CANTest下都能看到CAN1与CAN2发送的数据,这说明连接上是完全没有问题的,但是,在调试CAN接收时,在CAN2的接收中断处设置断点,使用PC端软件CAN_Test向CAN2发送数据发现并不能产生中断,而对比CAN1时,发现CAN1却可以产生接收中断。

4 问题分析
       仔细对比CAN1与CAN2的代码,发现并没有什么不同之处。仔细思考一下,由于CAN接收中断是与CAN过滤器有关,因此,着重对比CAN1与CAN2设置过滤器时的代码差异。
       CAN1设置过滤器代码如下:


       而CAN1设置过滤器代码如下:

      
       看来好像没有什么不妥的地方,基本差不多,只不过调用HAL_CAN_ConfigFilter函数配置过滤器传入的第一个参数一个是&hcan1,一个是&hcan2,
查看参考手册,对比CAN1与CAN2的差别:
       在参考手册的24.4节中对CAN的功能介绍时有下面一段话:

       上面一段话的意思是说,CAN1是作为主,而CAN2做为从,做为从的CAN2不能直接访问这个专用的512bytes的SRAM,而只能通过作为主的CAN1来间接访问,且CAN1与CAN2是共享这个专用的512bytes的SRAM。打开图222,如下所示:

      
      如上图可知,CAN1与CAN2共用过滤器(Acceptance Filters),CAN2是通过CAN1的Memory Access Controler来访问过滤器的。过滤器共有28个,占用512专用字节其中一部分。
       接着在数据手册中查下内存映射,如下图所示:


      可知,CAN1的地址为:

      
      然后查看bxCAN的寄存器,在参考手册的24.9.5节中,发现有这么一段话:

      
      也就是说,从偏移地址0x200开始到0x31C之间的寄存器只存在于CAN1中,在CAN2中并不存在,那么这些都是些什么寄存器呢?
查看参考手册的CAN寄存器映射表,如下内容所示:



      可知这些都是CAN过滤器相关的寄存器,可知离CAN1起始地址0x4000 6400偏移0x200~0x320之间是CAN过滤器寄存器的地址,且这些过滤器由CAN1和CAN2共享,且最重要的一点信息是,离CAN2起始地址0x4000 6800偏移0x200~0x320之间是没有寄存器的,这个非常重要!
      再回过头来看CAN2过滤器的设置代码:


      这几行设置过滤器的代码到底是将参数设置到CAN1偏移0x200~0x320之间还是CAN2偏移的0x200~0x320之间?这个问题要弄清楚,非常重要的!继续看HAL_CAN_ConfigFilter函数内:


      由上代码可知,设置的参数实际上是设置到传入的句柄hcan的示例Instance下的成员FS1R,sFilterRegister[]中去了,查看这些成员的定义:


      
      由以上代码可知,HAL_CAN_ConfigFilter函数实际上就是对传入的CAN起始地址偏移0x200~0x320之间的过滤器相关寄存器进行参数设置,但是,对于CAN2来说,实际并不存在这个这些寄存器,因此不会生效。这个可以在调试过程中查看CAN2寄存器值来验证,如下图:

      
      在运行过HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig)之后,CAN2相关的过滤器还是没有变化,进一步说明此函数对于CAN2来说是无效的。



      那么要解决这个问题,该如何修改呢?很明显,通过CAN1来设置即可。CAN1和CAN2共享过滤器,但设置过滤器时可以通过CAN1的偏移来访问过滤器,这么说来,也可以将这个理解为CAN1作为“主”的确切含义吧。
      修改后如下:



      在CAN2中断设置断点,使用PC端软件CANTest向STM3210C-EVAL评估板的CAN2通道发送数据进行测试验证:
      如上图可见,CAN2的接收中断已经可以正常捕获到了。

5 横向扩展
      此问题是在使用Cube库下时发现的,那么标准库是否也会存在同样的问题?
其实,在使用标准库下,在设置过滤器时,并不需要传入CAN1或CAN2的句柄,因此也就不会这这种问题,如下基于标准库的示例代码:


      在函数CAN_FilterInit中,内部自始至终操作的都是CAN1,如下所示:


      因此,不会出现在Cube库下出现的问题。


6 总结
      此文所描述的问题之会出现在使用Cube库的情况下,且基本覆盖包含双CAN的所有系列,在使用HAL函数HAL_CAN_ConfigFilter配置过滤器时,将第一个参数固定指向CAN1的句柄就可以了。





点击下载文档
查看更多实战经验


stary666 发表于 2016-8-31 09:48:30

:loveliness::loveliness:

zhulikai 发表于 2016-10-27 10:04:55

:lol:lol:lol:lol:lol

makc 发表于 2016-11-27 16:22:50

F4就没有这个问题了,这样不是感觉很坑人啊。左边是 F4 右边是F1 :L



shuichengwen 发表于 2018-7-28 16:20:29

没有使用Cube

qiaoy1988 发表于 2018-11-8 18:32:14

遇到同样的问题太好了

Morpher 发表于 2021-10-13 14:42:24

太感谢了,从昨天晚上开始,CAN1发送接收中断都正常,但是CAN2只能进入发送中断,谢谢大佬。
页: [1]
查看完整版本: 【实战经验】基于Cube库无法检测CAN2的接收中断