CAN过滤器:基础知识概览
文章目录
过滤器
过滤器的过滤模式
掩码(不常用掩码模式)
两个单元分别组成匹配ID和掩码(MASK)
被过滤的ID号和匹配ID号会和掩码进行按位与运算后再进行匹配
例如:
可以指定一个ID号的范围,在这个范围内的ID号可以通过我们的过滤器
过滤器一共有4种工作模式:
32位宽的掩码模式, 配置过滤2个不同的ID号
32位宽的列表模式, 配置过滤4个不同的ID号
16位宽的列表模式, 配置过滤2个不同的ID号
16位宽的掩码模式 配置过滤1个不同的ID号
过滤器的位宽:
16位过滤器
32位过滤器
CAN的双接收中断
使用CAN2过滤ID号(实验)
在之前CAN实验的代码上修改
这里我们只需要修改CAN2,把CAN_Configfilter()函数中的sFiterconfig拷贝下来
覆盖掉之前的sFiterconfig.FilterBank
sFiterconfig.FilterActivation = CAN_FILTER_ENABLE;//激活过滤器
sFiterconfig.FilterBank=0;//过滤器编号,CAN1是0~13
sFiterconfig.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~27
sFiterconfig.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~27
sFiterconfig.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通信过滤器的理解