【HAL库】STM32F407----CAN通信----过滤器配置

【HAL库】STM32F407----CAN通信----基本原理
【HAL库】STM32F407----CAN通信----电路图
【HAL库】STM32F407----CAN通信----中断详解

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验


一、STM32F407----CAN过滤器----简介

在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者以广播的形式把报文发送给所有的接收者。节点在接收报文时,根据标识符(CAN ID)的值决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。

为满足这一需求,bxCAN为应用程序提供了14个位宽可变的、可配置的过滤器组(13~0),以便只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。每个过滤器组x由2个32位寄存器,CAN_FxR0和CAN_FxR1组成。

1. CAN过滤器组

STM32F407有两路CAN,所以有28个过滤器组,具体如下表:

CAN 过滤器组
CAN1 0 ~ 13
CAN2 14 ~ 27

2. CAN过滤器模式

掩码模式

在掩码模式下,标识符寄存器与掩码寄存器关联,用以指示标识符的哪些位必须匹配,哪些位无关

列表模式

传入标识符的所有位都必须与筛选器寄存器中指定的位匹配

3. CAN过滤器位宽

每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供:

  • 1个32位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位。
  • 2个16位过滤器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位。

4. CAN过滤器匹配序号

消息接收到 FIFO 中后,即可供应用程序使用。
通常情况下,报文中的数据被拷贝到SRAM中;为了把数据拷贝到合适的位置,应用程序需要根据报文的标识符来辨别不同的数据。bxCAN提供了过滤器匹配序号,以简化这一辨别过程。
根据过滤器优先级规则,过滤器匹配序号和报文一起,被存入邮箱中。因此每个收到的报文,都有与它相关联的过滤器匹配序号。

过滤器匹配序号的使用方法有两种:

  1. 把过滤器匹配序号跟一系列所期望的值进行比较
  2. 把过滤器匹配序号当作一个索引来访问目标地址

对于列表模式过滤器,软件不再需要比较标识符。
对于掩码模式过滤器,软件只须对需要的那些屏蔽位(必须匹配的位)进行比较即可。

筛选器编号与筛选器组的激活状态无关。此外,还将使用两个独立的编号方案,每个 FIFO 各一个。具体举例如下:
在这里插入图片描述
此图只是举例,具体配置不用按照此图。

5. CAN过滤器优先级规则

根据过滤器的不同配置,有可能一个报文标识符能通过多个过滤器的过滤;在这种情况下,存放在接收邮箱中的过滤器匹配序号,根据下列优先级规则来确定:

  • 位宽为32位的过滤器,优先级高于位宽为16位的过滤器。
  • 对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式。
  • 位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高。

6. CAN过滤器配置

过滤器组可以通过相应的CAN_FMR寄存器(CAN过滤器主控寄存器)配置。但是不是什么时候都可以直接配置,在配置一个过滤器组前,必须通过清除CAN_FAR寄存器(CAN过滤器激活寄存器)的FACT位,把它设置为禁用状态。然后才能设置或设置过滤器组的配置

  • 通过设置CAN_FS1R(CAN过滤器位宽寄存器)的FSCx位,可以配置一个过滤器组的位宽
  • 通过设置CAN_FM1R(CAN过滤器模式寄存器)的FBMx位,可以配置对应的屏蔽/标识符寄存器的标识符列表模式掩码模式

过滤器配置具体如下图所示:
在这里插入图片描述


二、STM32F407----CAN过滤器----配置实验

以下是STM32F407----CAN过滤器----配置的具体实验内容和代码。
前期准备工作,请参考这篇文章:【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验

实验内容: CAN通信波特率为 500K bps,将接收到的CAN_ID发送出来,发送帧ID为0x18888888,前4个字节数据为接收到的CAN_ID。


过滤器配置-----代码模板

在STM32CubeMX生成【HAL库】程序中,没有关于过滤器相关的配置代码,如果不配置过滤器无法接收数据,所以需要我们自己手写代码配置过滤器

以下是 所有CAN帧ID都可以通过的过滤器 配置代码。

具体过滤器配置代码模板如下:

void CAN1_Filter_Bank(void)//过滤器
{
    
    
    CAN_FilterTypeDef FilterConfig;

    /*配置CAN过滤器*/
    FilterConfig.FilterBank = 0;                      //过滤器组号
    FilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;  //过滤模式:屏蔽位模式--CAN_FILTERMODE_IDMASK,列表模式--CAN_FILTERMODE_IDLIST
    FilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //过滤器位宽:32位
    FilterConfig.FilterIdHigh = 0x0000;               //32位ID
    FilterConfig.FilterIdLow = 0x0000;
    FilterConfig.FilterMaskIdHigh = 0x0000;           //32位MASK
    FilterConfig.FilterMaskIdLow = 0x0000;
    FilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; //过滤器0关联到FIFO0
    FilterConfig.FilterActivation = ENABLE;           //激活滤波器0
    FilterConfig.SlaveStartFilterBank = 14;           //单CAN此参数无意义
    
    //过滤器配置激活
    if (HAL_CAN_ConfigFilter(&hcan1, &FilterConfig) != HAL_OK)
    {
    
    
        Error_Handler();
    }
}

说明: 过滤器掩码模式:0不验证,1验证。所以屏蔽位都为0,就都不需要验证,所有CAN帧ID都可以接收了。

列表模式

只有列表中存放的CAN_ID才可以被接收到。

1. 列表模式----16位

在16位列表模式下,只能接收处理 标准帧CAN_ID
CAN_FxR1和CAN_FxR2寄存器一共有64位,可以存放4个16位CAN_ID。

具体如下图所示:
在这里插入图片描述

过滤器配置具体说明如下:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
映射 STID[10:0] RTR IDE EXID[17:15]]
说明 11位标准帧CAN_ID 帧类型:
0 数据帧
1 远程帧
标识符类型:
0 标准帧
1 扩展帧
无用数据
置0即可
举例 0x101 0 0 0
0x102 1 0 0
0x103 0. 0 0
0x104 1 0 0

因为在16位列表模式下,只能接收处理 标准帧CAN_ID,所以IDE位都置0

具体代码如下:

void CAN1_Filter_Bank(void)//过滤器、
{
    
    
	//标准帧ID
    uint16_t CanFilterListSTID0 = 0x101;
    uint8_t CanFilterListRTR0 = 0x00;   //帧类型:0x00数据帧,0x01远程帧
    
    uint16_t CanFilterListSTID1 = 0x102;
    uint8_t CanFilterListRTR1 = 0x01;   //帧类型:0x00数据帧,0x01远程帧
    
    uint16_t CanFilterListSTID2 = 0x103;
    uint8_t CanFilterListRTR2 = 0x00;   //帧类型:0x00数据帧,0x01远程帧
    
    uint16_t CanFilterListSTID3 = 0x104;
    uint8_t CanFilterListRTR3 = 0x01;   //帧类型:0x00数据帧,0x01远程帧
    
    CAN_FilterTypeDef FilterConfig;

    /*配置CAN过滤器*/
    FilterConfig.FilterBank = 0;                      //过滤器组号
    FilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;  //过滤模式:列表模式--CAN_FILTERMODE_IDLIST
    FilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; //过滤器位宽:16位
    FilterConfig.FilterIdHigh = (CanFilterListSTID0<<5)|(CanFilterListRTR0<<4);               //ID
    FilterConfig.FilterIdLow =  (CanFilterListSTID1<<5)|(CanFilterListRTR1<<4);
    FilterConfig.FilterMaskIdHigh = (CanFilterListSTID2<<5)|(CanFilterListRTR2<<4);           //MASK
    FilterConfig.FilterMaskIdLow = (CanFilterListSTID3<<5)|(CanFilterListRTR3<<4);
    FilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; //过滤器0关联到FIFO0
    FilterConfig.FilterActivation = ENABLE;           //激活滤波器
    FilterConfig.SlaveStartFilterBank = 14;           //单CAN此参数无意义
    //过滤器配置
    if (HAL_CAN_ConfigFilter(&hcan1, &FilterConfig) != HAL_OK)
    {
    
    
        Error_Handler();
    }
}

实验结果如下:

在这里插入图片描述

2. 列表模式----32位

在32位列表模式下,可以接收处理 标准帧CAN_ID扩展帧CAN_ID
CAN_FxR1和CAN_FxR2寄存器一共有64位,可以存放2个32位CAN_ID。

具体如下图所示:
在这里插入图片描述
过滤器配置具体说明如下:

31 ~ 21 20 ~3 2 1 0
映射 STID[10:0] EXID[17:0] IDE RTR 0
说明 29位扩展帧CAN_ID 标识符类型:
0 标准帧
1 扩展帧
帧类型:
0 数据帧
1 远程帧
0
11位标准帧CAN_ID 0
举例 0x1B010F01 1 0 0
0x701 0 0 1 0

具体代码如下:

void CAN1_Filter_Bank(void)//过滤器
{
    
    
	//扩展帧ID
    uint32_t CanFilterListEXID0 = 0x1B010F01;
    uint8_t CanFilterListIDE0 = 0x01;       //帧类型:0x00标准帧,0x01扩展帧
    uint8_t CanFilterListRTR0 = 0x00;       //帧类型:0x00数据帧,0x01远程帧

    //标准帧ID
    uint16_t CanFilterListSTID1 = 0x701;
    uint8_t CanFilterListIDE1 = 0x00;//帧类型:0x00标准帧,0x01扩展帧
    uint8_t CanFilterListRTR1 = 0x01;//帧类型:0x00数据帧,0x01远程帧

    CAN_FilterTypeDef FilterConfig;

    /*配置CAN过滤器*/
    FilterConfig.FilterBank = 0;                      //过滤器组号
    FilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;  //过滤模式:列表模式--CAN_FILTERMODE_IDLIST
    FilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //过滤器位宽:32位
    FilterConfig.FilterIdHigh = (CanFilterListEXID0<<3)>>16;         //ID
    FilterConfig.FilterIdLow =  (CanFilterListEXID0<<3)|(CanFilterListIDE0<<2)|(CanFilterListRTR0<<1);
    FilterConfig.FilterMaskIdHigh = CanFilterListSTID1<<5;           //MASK
    FilterConfig.FilterMaskIdLow = (CanFilterListIDE1<<2)|(CanFilterListRTR1<<1);
    FilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; //过滤器0关联到FIFO0
    FilterConfig.FilterActivation = ENABLE;           //激活滤波器
    FilterConfig.SlaveStartFilterBank = 14;           //单CAN此参数无意义
    //过滤器配置
    if (HAL_CAN_ConfigFilter(&hcan1, &FilterConfig) != HAL_OK)
    {
    
    
        Error_Handler();
    }
}

实验结果如下:

在这里插入图片描述

掩码模式

由屏蔽码决定是否与验证CAN_ID哪几位做比较,只有与验证CAN_ID一致,才可以接收到。屏蔽码:0不验证,1验证。

掩码模式举例说明:

16进制 7 6 5 4 3 2 1 0
屏蔽码 0xFC 1 1 1 1 1 1 0 0
验证码 0x79 0 1 1 1 1 0 0 1
可通过数据 0x78,0x79,0x7A,0x7B 0 1 1 1 1 0 x x

屏蔽码是1的位,必须与验证码一致才可通过。
屏蔽码是0的位,0和1皆可通过。

1. 掩码模式----16位

在16位掩码模式下,只能接收处理 标准帧CAN_ID
CAN_FxR1和CAN_FxR2寄存器一共有64位,可以存放2个16位验证码和2个16位屏蔽码。

具体如下图所示:
在这里插入图片描述
过滤器配置具体说明如下:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
映射 STID[10:0] RTR IDE EXID[17:15]]
说明 11位标准帧CAN_ID 帧类型:
0 数据帧
1 远程帧
标识符类型:
0 标准帧
1 扩展帧
无用数据
置0即可
举例 屏蔽码0:0x7FC 1 0 0
验证码0:0x201 0 0 0
可接收帧:0x200,0x201,0x202,0x203
只可接收数据帧
屏蔽码1:0x7CF 0 0 0
验证码1:0x301 0 0 0
可接收帧:0x301,0x311,0x321,0x331
可接收数据帧和远程帧

因为在16位列表模式下,只能接收处理 标准帧CAN_ID,所以IDE位都置0

具体代码如下:

void CAN1_Filter_Bank(void)//过滤器
{
    
    
	uint16_t CanFilterMaskSTID0 = 0x7FC;//屏蔽码:0不验证,1验证
    uint8_t  CanFilterMaskRTR0 = 0x01;//屏蔽码:0不验证,1验证
    uint16_t CanFilterSTID0 = 0x201;
    uint8_t  CanFilterRTR0 = 0x00;//帧类型:0x00数据帧,0x01远程帧
    
    uint16_t CanFilterMaskSTID1 = 0x7CF;//屏蔽码:0不验证,1验证
    uint8_t CanFilterMaskRTR1 = 0x00;//屏蔽码:0不验证,1验证
    uint16_t CanFilterSTID1 = 0x301;
    uint8_t CanFilterRTR1 = 0x00;//帧类型:0x00数据帧,0x01远程帧

    CAN_FilterTypeDef FilterConfig;

    /*配置CAN过滤器*/
    FilterConfig.FilterBank = 0;                      //过滤器组号
    FilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;  //过滤模式:掩码模式--CAN_FILTERMODE_IDMASK
    FilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; //过滤器位宽:16位
    FilterConfig.FilterIdHigh = (CanFilterSTID0<<5)|(CanFilterRTR0<<4);               //ID
    FilterConfig.FilterIdLow =  (CanFilterSTID1<<5)|(CanFilterRTR1<<4);
    FilterConfig.FilterMaskIdHigh = (CanFilterMaskSTID0<<5)|(CanFilterMaskRTR0<<4);           //MASK
    FilterConfig.FilterMaskIdLow = (CanFilterMaskSTID1<<5)|(CanFilterMaskRTR1<<4);
    FilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; //过滤器0关联到FIFO0
    FilterConfig.FilterActivation = ENABLE;           //激活滤波器
    FilterConfig.SlaveStartFilterBank = 14;           //单CAN此参数无意义
    //过滤器配置
    if (HAL_CAN_ConfigFilter(&hcan1, &FilterConfig) != HAL_OK)
    {
    
    
        Error_Handler();
    }
}

实验结果1如下:
在这里插入图片描述
可接收帧:0x200,0x201,0x202,0x203,只可接收数据帧。

实验结果2如下:
在这里插入图片描述
可接收帧:0x301,0x311,0x321,0x331,可接收数据帧和远程帧。

2. 掩码模式----32位

在32位列表模式下,可以接收处理 标准帧CAN_ID扩展帧CAN_ID
CAN_FxR1和CAN_FxR2寄存器一共有64位,可以存放1个32位验证码和1个32位屏蔽码。

具体如下图所示:
在这里插入图片描述
过滤器配置具体说明如下:

31 ~ 21 20 ~3 2 1 0
映射 STID[10:0] EXID[17:0] IDE RTR 0
说明 29位扩展帧CAN_ID 标识符类型:
0 标准帧
1 扩展帧
帧类型:
0 数据帧
1 远程帧
0
11位标准帧CAN_ID 0
举例 屏蔽码:0x1FFFFFFC 1 1 0
验证码:0x1B030F01 1 0 0
可接收帧:0x1B030F00,0x1B030F01,0x1B030F02,0x1B030F03
只可接收数据帧扩展帧

具体代码如下:

void CAN1_Filter_Bank(void)//过滤器
{
    
    
    uint32_t CanFilterMaskEXID = 0x1FFFFFFC;//屏蔽码:0不验证,1验证
    uint8_t CanFilterMaskIDE = 0x01;//屏蔽码:0不验证,1验证
    uint8_t CanFilterMaskRTR = 0x01;//屏蔽码:0不验证,1验证

    uint32_t CanFilterEXID = 0x1B030F01;
    uint8_t CanFilterIDE= 0x01;     //帧类型:0x00标准帧,0x01扩展帧
    uint8_t CanFilterRTR= 0x00;     //帧类型:0x00数据帧,0x01远程帧

    CAN_FilterTypeDef FilterConfig;

    /*配置CAN过滤器*/
    FilterConfig.FilterBank = 0;                      //过滤器组号
    FilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;  //过滤模式:掩码模式--CAN_FILTERMODE_IDMASK
    FilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //过滤器位宽:32位
    FilterConfig.FilterIdHigh = (CanFilterEXID<<3)>>16;               //ID
    FilterConfig.FilterIdLow =  (CanFilterEXID<<3)|(CanFilterIDE<<2)|(CanFilterRTR<<1);
    FilterConfig.FilterMaskIdHigh = (CanFilterMaskEXID<<3)>>16;           //MASK
    FilterConfig.FilterMaskIdLow = (CanFilterMaskEXID<<3)|(CanFilterMaskIDE<<2)|(CanFilterMaskRTR<<1);
    FilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; //过滤器0关联到FIFO0
    FilterConfig.FilterActivation = ENABLE;           //激活滤波器
    FilterConfig.SlaveStartFilterBank = 14;           //单CAN此参数无意义
    //过滤器配置
    if (HAL_CAN_ConfigFilter(&hcan1, &FilterConfig) != HAL_OK)
    {
    
    
        Error_Handler();
    }

实验结果如下:
在这里插入图片描述
可接收帧:0x1B030F00,0x1B030F01,0x1B030F02,0x1B030F03,只可接收数据帧扩展帧。


猜你喜欢

转载自blog.csdn.net/MQ0522/article/details/130067130