STM32之CAN ---CAN ID过滤器分析与设置 CAN_FilterInit

主要提醒一下CAN_FilterInitStructure.CAN_FilterIdHigh和CAN_FilterInitStructure.CAN_FilterIdLow的设置:


最终设置是这样滴:
/* Setup the identifier information                                        */
	if (format == STANDARD_FORMAT)
	{       /* Standard ID                     */
		CAN_msgMask  |= (u32)(mask << 21) | CAN_ID_STD;
	}
	else
	{                              /* Extended ID                     */
		CAN_msgMask  |= (u32)(mask <<  3) | CAN_ID_EXT;
	}

	if (format == STANDARD_FORMAT)
	{       /* Standard ID                     */
		CAN_msgId  |= (u32)(id << 21) | CAN_ID_STD;
	}
	else
	{                              /* Extended ID                     */
		CAN_msgId  |= (u32)(id <<  3) | CAN_ID_EXT;
	}
        CAN1->sFilterRegister[CAN_filterIdx].FR1 = CAN_msgId; 	 /*  32-bit identifier */
	CAN1->sFilterRegister[CAN_filterIdx].FR2 = CAN_msgMask; /*  32-bit Mask */

所以用库文件的时候 CAN_FilterInitStructure.CAN_FilterIdHigh和 CAN_FilterInitStructure.CAN_FilterIdLow要或上扩展帧或者标准帧才算是真正的ID。

以下文章来自:http://blog.csdn.net/flydream0/article/details/8148791


4.2 位宽为32位的屏蔽模式

在此种模式下中过滤多个CAN ID,此时,过滤器包含两个寄存器,屏蔽码寄存器和标识符寄存器。此模式下最多只存在一个屏蔽过滤器。

如下图所示:

                                                                                 图10

如上图,上面的ID为标识符寄存器,中间部分的MASK为屏蔽码寄存器。每个寄存器都是32位的。最下边显示的是与CAN ID各位定位的映射关系。由4.1的知识很快可以发现,上图最下边的映射关系恰好等于扩展CAN值左移3位再补上IDE(扩展帧标识),RTR(远程帧标志)。


因此,我们初步得出这样的推论:对于一个扩展CAN ID,不能单纯地将它看到的一个数,而应该将它看成两部分,基本ID和扩展ID(当然标准CAN ID只包含基本ID部分),过滤器屏蔽码寄存器和标识符寄存器也应该看成多个部分,然后问题就变成了如何将CAN ID所表示的各部分如何针对过滤器寄存器各部分对号入座的问题了。

对号入座的方法多种多样,但万变不离其心,主要是掌握其核心思想即可:1:在各种过滤器模式下,CAN ID与寄存器相应位置一定要匹配;2:在屏蔽方式下,屏蔽码寄存器某位为1表示接收到的CAN ID对应的位必须对验证码寄存器对应的位相同。


下面给出一个代码例子,假设我们要接收多个ID:0x7e9,0x1800f001,前面为标准ID,后面为扩展ID,要同时能接收这两个ID,那么该如何设置这个过滤器呢?

[cpp]  view plain copy
  1. CAN_FilterInitTypeDef  CAN_FilterInitStructure;  
  2. U16 std_id =0x7e9;  
  3. U32 ext_id =0x1800f001;  
  4. U32 mask =0;  
  5.   
  6. CAN_FilterInit(&CAN_FilterInitStructure);     //初始化CAN_FilterInitStructrue结构体变量  
  7. CAN_FilterInitStructure.CAN_FilterNumber=0;      //设置过滤器组0,范围为0~13  
  8. CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;    //设置过滤器组0为屏蔽模式  
  9. CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;   //设置过滤器组0位宽为32位  
  10.   
  11. //标识位寄存器的设置  
  12. //ext_id<<3对齐,见上图9,再>>16取高16位  
  13. CAN_FilterInitStructure.CAN_FilterIdHigh=((ext_id<<3) >>16) &0xffff;  //设置标识符寄存器高字节。  
  14. CAN_FilterInitStructure.CAN_FilterIdLow=(U16)(ext_id<<3) | CAN_ID_EXT;   //设置标识符寄存器低字节  
  15. //这里也可以这样设置  
  16. //CAN_FilterInitStructure.CAN_FilterIdHigh=std_id<<5;  //设置标识符寄存器高字节.这里为什么是左移5位呢?从上图可以看出,CAN_FilterIdHigh包含的是STD[0~10]和EXID[13~17],标准CAN ID本身是不包含扩展ID数据,因此为了要将标准CAN ID放入此寄存器,标准CAN ID首先应左移5位后才能对齐.  
  17. //CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_ID_EXT;   //设置标识符寄存器低字节,这里也可以设置为CAN_ID_STD  
  18.   
  19. //屏蔽寄存器的设置  
  20. //这里的思路是先将标准CAN ID和扩展CAN ID对应的ID值先异或后取反,为什么?异或是为了找出两个CAN ID有哪些位是相同的,是相同的位则说明需要关心,需要关心的位对应的屏蔽码位应该设置为1,因此需要取反一下。最后再整体左移3位。  
  21. mask =(std_id<<18);//这里为什么左移18位?因为从ISO11898中可以看出,标准CAN ID占ID18~ID28,为了与CAN_FilterIdHigh对齐,应左移2位,接着为了与扩展CAN对应,还应该再左移16位,因此,总共应左移2+16=18位。也可以用另一个方式来理解:直接看Mapping的内容,发现STDID相对EXID[0]偏移了18位,因此左移18位.  
  22. mask ^=ext_id;//将对齐后的标准CAN与扩展CAN异或后取反  
  23. mask =~mask;  
  24. mask <<=3;//再整体左移3位  
  25. mask |=0x02; //只接收数据帧,不接收远程帧  
  26. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=(mask>>16)&0xffff; //设置屏蔽寄存器高字节  
  27. CAN_FilterInitStructure.CAN_FilterMaskIdLow=mask&0xffff;   //设置屏蔽寄存器低字节  
  28.   
  29. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;  //此过滤器组关联到接收FIFO0  
  30. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活此过滤器组  
  31. CAN_FilterInit(&CAN_FilterInitStructure); //设置过滤器  

总结可知,当过滤器为屏蔽模式时,标识符寄存器对应的ID内容可为任意一需求接收的ID值,当同时要接收标准帧和扩展帧时,标识符寄存器对应IDE位也随意设置,屏蔽寄存器的IDE位设置为0,表示不关心标准帧还是扩展帧。而屏蔽寄存器对应的ID内容为各需求接收的ID值依次异或的结果再取反。

4.3 位宽为32位的标识符列表模式

在此种模式下,过滤器组包含的两个寄存器含义一样,此模式下只多存在两个标识符列表过滤器如下图:

                                                                                                   图11

[cpp]  view plain copy
  1. CAN_FilterInitTypeDef  CAN_FilterInitStructure;  
  2. U16 std_id =0x7e9;  
  3. U32 ext_id =0x1800f001;  
  4. CAN_FilterInit(&CAN_FilterInitStructure); //初始化CAN_FilterInitStructrue结构体变量  
  5. CAN_FilterInitStructure.CAN_FilterNumber=0;     //设置过滤器组0,范围为0~13  
  6. CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList;    //设置过滤器组0为标识符列表模式  
  7. CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;   //设置过滤器组0位宽为32位  
  8.   
  9. //设置屏蔽寄存器,这里当标识符寄存器用  
  10. CAN_FilterInitStructure.CAN_FilterIdHigh=std_id<<5) ;  //为什么左移5位?与上面相同道理,这里不再重复解释  
  11. CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_ID_STD; //设置标识符寄存器低字节,CAN_FilterIdLow的ID位可以随意设置,在此模式下不会有效。  
  12.   
  13. //设置标识符寄存器  
  14. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=((ext_id<<3)>>16) & 0xffff; //设置屏蔽寄存器高字节  
  15. CAN_FilterInitStructure.CAN_FilterMaskIdLow=((ext_id<<3)& 0xffff) | CAN_ID_EXT;   //设置屏蔽寄存器低字节  
  16.   
  17. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;  //此过滤器组关联到接收FIFO0  
  18. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活此过滤器组  
  19. CAN_FilterInit(&CAN_FilterInitStructure); //设置过滤器  

4.4 位宽为16位的屏蔽码模式

在此模式下,最多存在两个屏蔽码过滤器,如下图:

                                                                                                          图12

由上图映射可知,最下面的映射只包含STDID0~ID10,因此,此模式下的两个屏蔽过滤器只能实现对标准ID的过滤。具体代码就不介绍了,参见上图的映射即可。

4.5 位宽为16位的标识符列表模式

                                                                                              图13

在此模式下,由于标识符寄存器的高16位和低16位,屏蔽寄存器的高16位和低16位都用来做标识符寄存器,因此,最多可存在4个标识符过滤器。同样,只能实现对标准帧的过滤。具体代码就不介绍了,参见上图的映射即可。

  • 6
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32的CAN过滤器可以通过配置相应的CAN_FMR寄存器来实现。在配置一个过滤器组之前,需要先将CAN_FAR寄存器的FACT位清除,将其设置为禁用状态,然后才能进行过滤器组的设置或配置。\[1\] 根据芯片的不同,STM32可以具有不同数量的CAN控制器。如果STM32只有一个CAN控制器,则可以配置14个过滤器组,对应的编号为0~13。如果STM32拥有两个CAN控制器,则可以配置28个过滤器组,其中CAN1对应的过滤器组编号为0~13,CAN2对应的过滤器组编号为14~27。\[2\] 如果需要让CAN2只接收CAN ID为0x713的报文,可以使用以下代码进行配置: CAN_FilterInitTypeDef CAN_FilterInitStructure; CAN_FilterInitStructure.CAN_FilterNumber = 14; CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh = (uint16_t)((0x713 << 5) & 0xFFFF); CAN_FilterInitStructure.CAN_FilterIdLow = (uint16_t)(0x0000 | CAN_ID_STD); CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFF0; CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0006; CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0; CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; CAN_FilterInit(&CAN_FilterInitStructure);\[3\] 这样配置后,CAN2只会接收CAN ID为0x713的报文。 #### 引用[.reference_title] - *1* [STM32 CAN通讯过滤器使用总结及代码分析](https://blog.csdn.net/qq_27747359/article/details/89682407)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [STM32的CAN过滤](https://blog.csdn.net/fukangwei_lite/article/details/127207198)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值