最近换了工作,电脑也换了,STM32的自动代码生成工具在官网已经下不到了,估计也是做的太差了,也不想干了~~花了一些时间把环境配置好了,目前用的是Matlab2020b,stm32cube版本5.6.0,stm32target版本5.6.0(这个是最新的了,再没有更新了)
断更很多天了,感觉很颓废。
进入正题,本文记录stm32CAN过滤模式的四种配置及simulink代码生成与测试。之前的文章中只用了32位列表模式(不清楚的可以看STM32基于simulink自动代码生成),下面分别介绍其他三种模式。
对于掩码模式,可以这样理解,有一个屏蔽码和验证码,屏蔽码用来指定需要确定的位,验证码用来指定确定的位的值,两者一起用来过滤部分ID。
对于配置代码来说,
FilterIdLow与CAN_FxR1低16位对应
FilterIdHigh与CAN_FxR1高16位对应
FilterMaskIdLow与CAN_FxR2低16位对应
FilterMaskIdHigh与CAN_FxR2高16位对应
32位的掩码模式,FilterIdHigh与FilterIdLow合在一起表示CAN_FxR1寄存器,用来存放验证码,而FilterMaskIdHigh与FilterMaskIdLow合在一起表示CAN_FxR2寄存器,用来存放屏蔽码。在32位的掩码模式下,若屏蔽码将IDE位置1,而验证码将IDE位置0,则扩展帧ID将会被过滤掉,如下图所示
设置成2592(0x51<<5)后,则ID为0x51的标准帧ID可以被接收,除了0x51(对应二进制为01010001),其他ID如0x53,0x57也可以正常被接收,因为对应的位上没有置1,无法过滤,而比如0x50则无法被接收,因为最后一位的值应该为1.
对应simulink生成的c代码:
sFilterConfig.FilterIdHigh = 0xA20;
sFilterConfig.FilterIdLow = 0x0;
sFilterConfig.FilterMaskIdHigh = 0xA20;
sFilterConfig.FilterMaskIdLow = 0x4;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
测试0x51标准帧发送,通过串口转发发送的数据:
发送0x53,可以进到断点里,表示可以正常接收,但不会解析(CAN Unpack模块会判断接收的ID与设置的一致)
若是过滤扩展帧ID,则ID位占1的越多,能被过滤掉的ID就越多,这里不再测试,感兴趣的可以自己理解后尝试测试一下。
在16位宽的掩码模式下,CAN_FxR1的低16位(也就是FilterIdLow)是作为验证码,对应的16位屏蔽码为CAN_FxR1的高16位(也就是FilterIdHigh),同样的,CAN_FxR2的低16位(也就是FilterMaskIdLow)是作为验证码,对应于CAN_FxR2的高16位(也就是FilterMaskIdHigh)为屏蔽码。这样说明后,不管是对于代码来说,还是对于模型来说,都是比较好理解的了。
实际应用时,需要选择为16bit模式。设置两组验证码与屏蔽码。
这时大家可能会有疑惑,在这两组不同的过滤器中,报文是按什么方式进行过滤的?
如果是报文在第一个过滤器中就通过,则控制器可以接收到该报文,否则进入下一个过滤器,若下一个过滤器无法通过,则报文无法接收。
stm32还对过滤器进行了编号,规则如下:
同一过滤器组内,按寄存器从小到大编号。FxR1配置的过滤器编号小,FxR2配置的过滤器编号大
同一个寄存器内,按位序从小到大编号。[15-0]位配置的过滤器编号小,[31-16]位配置的过滤器编号大
则,CAN_FxR1过滤器编号小,CAN_FxR2过滤器编号大。
STM32在使用过滤器时,按以下顺序进行过滤:
(1) 位宽为32位的过滤器,优先级高于位宽为16位的过滤器。
(2) 对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式。
(3) 位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高。
所以,上述16位宽的掩码模式下,优先会通过CAN_FxR1过滤器。
实际配置如下图,
第一个过滤器验证码FilterIdLow取2592(0x51<<5),屏蔽码FilterIdHigh取2600(0x51<<5|1<<3),表示IDE位需要的值为0,此时,如果接收0x50报文,会被第一个过滤器过滤掉,进入下一个过滤器
第二个过滤器验证码FilterMaskIdLow取2560(0x50<<5),屏蔽码FilterMaskIdHigh取2568(0x50<<5|1<<3),表示IDE位需要的值为0,此时0x50报文将被接收。
对应simulink生成的c代码:
sFilterConfig.FilterIdHigh = 0xA28;
sFilterConfig.FilterIdLow = 0xA20;
sFilterConfig.FilterMaskIdHigh = 0xA08;
sFilterConfig.FilterMaskIdLow = 0xA00;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
测试0x51标准帧,控制器可以接收到。
测试0x50标准帧,控制器可以接收到。
测试0x53标准帧,控制器可以接收到。
测试0x10标准帧,没有进入断点,控制器无法接收到。
若接收0x53报文,则第一个过滤器就可以收到。若是0x10,则控制器无法接收到该报文。大家可以自行理解其他情况。
对于16位宽的列表模式,很好理解,有四个滤波器,可以精确筛选出4个标准帧ID(接收的ID必须和滤波器设置保持一致)。若是过滤扩展帧,只能过滤出高11位(标准帧的位)和扩展帧的高三位,无法精确筛选扩展帧ID。
simulink中过滤模式设置为列表模式,过滤四个标准帧ID,FilterIdLow取2592(0x51<<5|0),FilterIdHigh取2560(0x50<<5|0).,FilterMaskIdLow取9312(0x123<<5|0),FilterMaskIdHigh取64480(0x7DF<<5|0),设置图如下:
对应simulink生成的c代码:
sFilterConfig.FilterIdHigh = 0xA00;
sFilterConfig.FilterIdLow = 0xA20;
sFilterConfig.FilterMaskIdHigh = 0xFBE0;
sFilterConfig.FilterMaskIdLow = 0x2460;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
测试发送0x51标准帧,可以接收到
测试发送0x50,控制器可以接收到。
测试发送0x123标准帧,控制器可以接收到
测试发送0x7DF标准帧,控制器可以接收到。
测试发送0x53,控制器无法接收到。
有问题可以评论区回复或直接联系:QQ/WX:953909472
欢迎点赞分享~
测试工程及代码