微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > STM32之CAN ---CAN ID过滤器分析

STM32之CAN ---CAN ID过滤器分析

时间:11-10 来源:互联网 点击:

帧标识),RTR(远程帧标志)。

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

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

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

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

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

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

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

图11

  1. CAN_FilterInitTypeDefCAN_FilterInitStructure;
  2. U16std_id=0x7e9;
  3. U32ext_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. CAN_FilterInitStructure.CAN_FilterIdHigh=std_id<5);//为什么左移5位?与上面相同道理,这里不再重复解释
  10. CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_ID_STD;//设置标识符寄存器低字节,CAN_FilterIdLow的ID位可以随意设置,在此模式下不会有效。
  11. //设置标识符寄存器
  12. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=((ext_id<3)>>16)&0xffff;//设置屏蔽寄存器高字节
  13. CAN_FilterInitStructure.CAN_FilterMaskIdLow=((ext_id<3)&0xffff)|CAN_ID_EXT;//设置屏蔽寄存器低字节
  14. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;//此过滤器组关联到接收FIFO0
  15. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活此过滤器组
  16. CAN_FilterInit(&CAN_FilterInitStructure);//设置过滤器

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

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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top