过滤器基础知识"/>
CAN过滤器基础知识
文章目录
- 过滤器
- 过滤器的过滤模式
- 掩码(不常用掩码模式)
- CAN的双接收中断
- 使用CAN2过滤ID号(实验)
- 参考资料
过滤器
- STM32的bxCAN接收时必须使用过滤器接收
- 根据CAN外设数量的不同有以下情况:
- 只有CAN1:CAN1有14个过滤器
- 有CAN1和CAN2:CAN1和CAN2共享28个过滤器
- 有CAN1~3:CAN1和CAN2共享28个过滤器,CAN3有独立的14个过滤器
- 过滤器可以过滤CAN总线上帧的ID号
- 可以不处理不想接收的ID号,只接收想要的ID号
过滤器的过滤模式
- 过滤器总长度64位,可以分为2个32位单元或4个16位单元
- 两种过滤模式:掩码和列表
- 掩码模式:由两个单元组成通过掩码匹配
- 列表模式:由一个单元组成,ID号完全匹配即通过
- ID号对齐最高位(MSB)
- 仅32位单元可以过滤拓展ID
- 在列表模式下,scale为32时,每个过滤器的列表只能写入两个报文ID,若scale为16时,每个过滤器的列表最多可写入4个CAN ID
掩码(不常用掩码模式)
-
两个单元分别组成匹配ID和掩码(MASK)
-
被过滤的ID号和匹配ID号会和掩码进行按位与运算后再进行匹配
- 也就是只有对应的掩码为1的位才会被匹配
-
例如:
- 匹配ID为0x200,掩码为0x000,则所有ID号都能通过
- 匹配ID为0x200,掩码为0x700,则ID为0x200~0x2FF均可通过
- 匹配ID为0x200,掩码为0x7FF,则只有0x200能通过
-
可以指定一个ID号的范围,在这个范围内的ID号可以通过我们的过滤器
过滤器一共有4种工作模式:
32位宽的掩码模式, 配置过滤2个不同的ID号 32位宽的列表模式, 配置过滤4个不同的ID号 16位宽的列表模式, 配置过滤2个不同的ID号 16位宽的掩码模式 配置过滤1个不同的ID号
过滤器的位宽:
16位过滤器 32位过滤器
CAN的双接收中断
- 每个CAN有两个接收中断,对应两组接收邮箱(FIFO)
- 每个过滤器可以绑定一个CAN接收中断
- 经过过滤器过滤的帧会进入该过滤器绑定的接收中断对应的邮箱
- 匹配时,列表模式的优先级高于掩码模式,其次过滤器编号更小的优先级更高
使用CAN2过滤ID号(实验)
- CAN1给CAN2发送不同ID号的数据帧
- CAN2使用过滤器进行过滤
- RX0和RX1分别对应不同过滤器,接收到不同数组中
在之前CAN实验的代码上修改
这里我们只需要修改CAN2,把CAN_Configfilter()函数中的sFiterconfig拷贝下来
覆盖掉之前的sFiterconfig.FilterBank
sFiterconfig.FilterActivation = CAN_FILTER_ENABLE;//激活过滤器sFiterconfig.FilterBank=0;//过滤器编号,CAN1是0~13sFiterconfig.FilterFIFOAssignment=CAN_FILTER_FIFO0;sFiterconfig.FilterMode=CAN_FILTERMODE_IDMASK;//设置为掩码模式sFiterconfig.FilterScale=CAN_FILTERSCALE_32BIT;//设置为32位宽sFiterconfig.FilterIdHigh=0x0000;//设置验证码sFiterconfig.FilterIdLow=0x0000;sFiterconfig.FilterMaskIdHigh=0x0000;sFiterconfig.FilterMaskIdLow=0x0000;sFiterconfig.SlaveStartFilterBank=14;
-
列表模式
绑定FIFO0
把下面的FilterBank设置为14,FilterMode改为CAN_FILTERMODE_IDLIST,FilterScale改为CAN_FILTERSCALE_16BIT,下面的ID号改为我们需要的ID号,这里我们可以设为0x200左移5位(左移5是为了对齐msb)
sFiterconfig.FilterActivation = CAN_FILTER_ENABLE;sFiterconfig.FilterBank=14;//过滤器编号,CAN2是14~27sFiterconfig.FilterFIFOAssignment=CAN_FILTER_FIFO0;//接收到的报文放入到FIFO0中sFiterconfig.FilterMode=CAN_FILTERMODE_IDLIST;//列表模式sFiterconfig.FilterScale=CAN_FILTERSCALE_32BIT;//设置32位宽sFiterconfig.FilterIdHigh=0x200<<5;//基本ID放入到STID中 sFiterconfig.FilterIdLow=0x201<<5;sFiterconfig.FilterMaskIdHigh=0x202<<5;//设置为0时,表示不过滤,可以接收任意的CANID数据,sFiterconfig.FilterMaskIdLow=0x203<<5;//不为0时,则表示过滤 对应MaskID为1的bit必须与FilterID中的bit位相同的CANID才能接收过来。sFiterconfig.SlaveStartFilterBank=14;
-
掩码模式
绑定FIFO1
在HAL库中FilterIdHigh,FilterIdLow,FilterMaskIdHigh,FilterMaskIdLow
FilterBank是过滤器编号,为了避免重复,这里设置为15,FilterMode选择CAN_FILTERMODE_IDMASK,因为我们这里过滤标准帧,没必要使用32位,所以FilterScale选择16位,FilterIdHigh,FilterIdLow在16位模式下指代两个不同的掩码组,FilterIdHigh对应FilterMaskIdHigh,FilterIdLow对应FilterMaskIdLow,一共是两组;如果是32位,就要把他们整个拼成一段整体,因此这里我们需要把它们拼成两组
sFiterconfig.FilterActivation = CAN_FILTER_ENABLE;sFiterconfig.FilterBank=15;//过滤器编号,CAN2是14~27sFiterconfig.FilterFIFOAssignment=CAN_FILTER_FIFO1;sFiterconfig.FilterMode=CAN_FILTERMODE_IDLIST;sFiterconfig.FilterScale=CAN_FILTERSCALE_16BIT;sFiterconfig.FilterIdHigh=0x200<<5;//ID和掩码都要移5位sFiterconfig.FilterMaskIdHigh=0x202<<5;sFiterconfig.FilterIdLow=0x201<<5;sFiterconfig.FilterMaskIdLow=0x203<<5;sFiterconfig.SlaveStartFilterBank=14;
把FilterMaskIdHigh设置为0x700,这样就表示过滤0x200到0x2FF的ID号
把FilterMaskIdHigh设置为0x7F0,这样就表示过滤0x200到0x20F的ID号
这里我们设置为0x7F0,更方便我们观察现象
然后把FilterFIFOAssignment改为CAN_FILTER_FIFO1,即绑定FIFO1,对应RX1的中断,这样就完成了掩码模式的配置
最终CAN_Configfilter()代码如下:
/* USER CODE BEGIN 4 */
void CAN_Configfilter()
{CAN_FilterTypeDef sFiterconfig;sFiterconfig.FilterActivation = CAN_FILTER_ENABLE;sFiterconfig.FilterBank=0;sFiterconfig.FilterFIFOAssignment=CAN_FILTER_FIFO0;sFiterconfig.FilterMode=CAN_FILTERMODE_IDMASK;sFiterconfig.FilterScale=CAN_FILTERSCALE_32BIT;sFiterconfig.FilterIdHigh=0x0000;sFiterconfig.FilterIdLow=0x0000;sFiterconfig.FilterMaskIdHigh=0x0000;sFiterconfig.FilterMaskIdLow=0x0000;sFiterconfig.SlaveStartFilterBank=14;if( HAL_CAN_ConfigFilter(&hcan1,&sFiterconfig)!=HAL_OK){Error_Handler();}
//列表模式sFiterconfig.FilterActivation = CAN_FILTER_ENABLE;sFiterconfig.FilterBank=14;sFiterconfig.FilterFIFOAssignment=CAN_FILTER_FIFO0;sFiterconfig.FilterMode=CAN_FILTERMODE_IDLIST;sFiterconfig.FilterScale=CAN_FILTERSCALE_16BIT;sFiterconfig.FilterIdHigh=0x200<<5;sFiterconfig.FilterIdLow=0x201<<5;sFiterconfig.FilterMaskIdHigh=0x202<<5;sFiterconfig.FilterMaskIdLow=0x203<<5;sFiterconfig.SlaveStartFilterBank=14;if( HAL_CAN_ConfigFilter(&hcan2,&sFiterconfig)!=HAL_OK){Error_Handler();}//掩码模式sFiterconfig.FilterActivation = CAN_FILTER_ENABLE;sFiterconfig.FilterBank=15;sFiterconfig.FilterFIFOAssignment=CAN_FILTER_FIFO0;sFiterconfig.FilterMode=CAN_FILTERMODE_IDMASK;sFiterconfig.FilterScale=CAN_FILTERSCALE_16BIT;sFiterconfig.FilterIdHigh=0x200<<5;sFiterconfig.FilterIdLow=0x201<<5;sFiterconfig.FilterMaskIdHigh=0x202<<5;sFiterconfig.FilterMaskIdLow=0x203<<5;sFiterconfig.SlaveStartFilterBank=14;if(HAL_CAN_Start(&hcan1)!=HAL_OK){Error_Handler();}if(HAL_CAN_Start(&hcan2)!=HAL_OK){Error_Handler();}if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING)!=HAL_OK){Error_Handler();}if(HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING)!=HAL_OK){Error_Handler();}}
void HAL_can_RxFifo0MsgPendingCallback(CAN_HandleTypeDef*hcan)//接收数据的回调函数
{if(hcan==&hcan2){HAL_CAN_GetRxMessage(&hcan2,CAN_RX_FIFO0,&rxHeader0,rxDateBuffer0);}
}//RX0
void HAL_can_RxFifo1MsgPendingCallback(CAN_HandleTypeDef*hcan)//接收数据的回调函数
{if(hcan==&hcan2){HAL_CAN_GetRxMessage(&hcan2,CAN_RX_FIFO1,&rxHeader1,rxDateBuffer1);}
}//RX1
/* USER CODE END 4 */
然后就可以编译烧录。
参考资料
CH4.2 CAN 第2讲 过滤器【南工骁鹰嵌入式软件培训】
STM32 CAN过滤器配置详解
对于can通信过滤器的理解
更多推荐
CAN过滤器基础知识
发布评论