STM32系列文章(2):CAN总线过滤器详解

前言

STM32 CAN总线的过滤器的作用主要是通过数据的帧ID,过滤掉一部分数据不做处理节约CPU硬件资源,我们可以设置不同的过滤条件来滤除不需要的数据,本文主要讲ID掩码过滤模式

一、与滤波设置相关的结构体

在HAL库中,跟滤波设置相关的结构体是CAN_FilterTypeDef,下面逐步讲解过滤过程。

二、逐步讲解

1.定义一个滤波器设置结构体

CAN_FilterTypeDef CAN_FilterInitStructure; 

2.设置过滤模式

CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;

3.设置 过滤比例

这里可能不明白什么意思,我用的STM32信号是F407 CAN总线有14个过滤器,每个过滤器有2个32位寄存器可以配置,可以配置成32位也可以配置成两个16位。

CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;

4.设置过滤ID和掩码ID

这是本文重点,两者共同确定了,到底哪些ID接收哪些ID过滤,下面我先把我的代码贴出来作为例子讲解.

	CAN_FilterInitStructure.FilterIdHigh = 0x0020;
	CAN_FilterInitStructure.FilterIdLow = 0x0000;
	CAN_FilterInitStructure.FilterMaskIdHigh = 0xFF80;
	CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;

首先这个ID是真正的帧ID左移21位得到的,也就是说我这里0x00200000,是由0x01左移21位得到的(这里指标准帧,扩展帧是3位)。

ID高16位ID低16位
0x00200x0000
0000 0000 0010 00000000 0000 0000 0000
掩码高16位掩码低16位
0xFF800x0000
1111 1111 1000 00000000 0000 0000 0000

我们把这两个数据的二进制形式放在一起,先看高16位如下:

ID0000000000000000
掩码 1111111110000000

掩码是1的位,意味着通过的数据帧的ID必须与上面一行我们指定的ID的对应位相等,如果掩码位是0,则没有要求,这样看来我们上面的高16位,能够通过的数据帧ID 必须是

ID0000000000/10/100000

然后再右21位得到帧ID,由此看来,我这种过滤方法,只能让0x00,0x01,0x02,0x03通过,别的ID统统过滤掉,经过我的验证,确实是这样,所以暂且认为我理解的是对的.

2.完整代码供大家参考

void CAN_FilterInit(CAN_HandleTypeDef *hcan)
{
	CAN_FilterTypeDef CAN_FilterInitStructure;
	CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
	CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;
	CAN_FilterInitStructure.FilterIdHigh = 0x0020;
	CAN_FilterInitStructure.FilterIdLow = 0x0000;
	CAN_FilterInitStructure.FilterMaskIdHigh = 0xFF80;
	CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
	CAN_FilterInitStructure.FilterBank = 0;
	CAN_FilterInitStructure.FilterFIFOAssignment = CAN_RX_FIFO0;
	CAN_FilterInitStructure.FilterActivation = ENABLE;
	CAN_FilterInitStructure.SlaveStartFilterBank = 14;
	if(HAL_CAN_ConfigFilter(hcan,&CAN_FilterInitStructure) != HAL_OK)
	{
		Error_Handler();
	}
	if(HAL_CAN_ActivateNotification(hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
	{
		Error_Handler();
	}
	if(HAL_CAN_Start(hcan) != HAL_OK)
	{
		Error_Handler();
	}
}

三.扩展说明

我们还可以通过或CAN_ID_EXT和CAN_RTR_DATA等define值来实现只接受扩展数据帧或者扩展遥控帧等等,具体如下例子(其中slave_id为要保留的id号):

1、对扩展数据帧进行过滤:(只接收扩展数据帧)


      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;

2、对扩展远程帧过滤:(只接收扩展远程帧)

      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_REMOTE)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;

3、对标准远程帧过滤:(只接收标准远程帧)

      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;

4、对标准数据帧过滤:(只接收标准数据帧)

      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;

5、对扩展帧进行过滤:(扩展帧不会被过滤掉)

      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<3)|CAN_ID_EXT)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFC;

6、对标准帧进行过滤:(标准帧不会被过滤掉)

      CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)slave_id<<21)|CAN_ID_STD)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFC;

四.总结

通过对以上两种的综合运用,相信可以实现对任意帧种类任意帧ID进行过滤了。累了,拜拜

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注