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~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;
  1. 列表模式

    绑定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;
  1. 掩码模式

    绑定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通信过滤器的理解

  • 15
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书阁下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值