一、引言
书接上回https://mp.csdn.net/mp_blog/creation/editor/138501563
二、标识符过滤器——Identifier filtering
2.1 作用
在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者以广播的形式把报文发送给所有的接收者。节点在接收报文时根据标识符的值决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。根据标识符过滤掉我们不需要的can数据帧,节省CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。
2.2 过滤流程
在接收一个报文时,其标识符首先与配置在标识符列表模式下的过滤器相比较;如果匹配上,报文就被存放到相关联的FIFO中,并且所匹配的过滤器的序号被存入过滤器匹配序号中。如同例子中所显示,报文标识符跟#4标识符匹配,因此报文内容和FMI4被存入FIFO。
如果没有匹配,报文标识符接着与配置在屏蔽位模式下的过滤器进行比较。
如果报文标识符没有跟过滤器中的任何标识符相匹配,那么硬件就丢弃该报文,且不会对软件有任何打扰。
2.3 过滤模式
标识符顾虑器由两种模式可以选择,分别是标识符列表模式和掩码模式。我们怎么理解这两种模式呢,这里举个栗子。比如我们要在一所大学的学生信息系统里面查看一些学生的具体信息,如果知道这些学生的具体学号(假设学生学号包含以下信息aabbccddee(aa表示入学年级、bb表示系别序号、cc表示专业序号、dd表示班级序号、ee表示班内序号)),那我们在系统中输入这些学号就能直接筛选出信息,因为学号和学生信息是一一对应的。标识符列表模式就是这样,我知道我想要过滤的can数据帧的标识符,再把这个标识符加入到过滤列表中,过滤器就可以在总线上筛选出我想要的数据帧。而掩码模式可以理解为一个范围晒选,比如我想提取23年入学的计算机专业的全部学生的考试成绩,那可能我在系统中只需要输入学号的前四位就可以达到目的,不需要学号一一对应。从上面描述也可以看出,标识符列表模式更适用于过滤一些特定的单个标识符,掩码模式则适用于过滤一些拥有相同特征但又不完全相同的标识符组。
在互联型产品中,bxCAN控制器为应用程序提供了28个位宽可变的、可配置的过滤器组(27~0);在其它产品中,bxCAN控制器为应用程序提供了14个位宽可变的、可配置的过滤器组(13~0)。每个过滤器组x由2个32位寄存器,CAN_FxR0和CAN_FxR1组成。另外每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供:
● 1个32位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位
● 2个16位过滤器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位
下图展示的是分别在掩码模式(CAN_FM1R寄存器的FBMx位=0)和标识符列表模式(CAN_FM1R寄存器的FBMx位=1)两种模式中同时位宽选择为32位下(CAN_FS1R寄存器的FSCx=1)过滤器组CAN_FxR1和CAN_FxR2两个寄存器中数据的含义。在标识符列表模式中一个过滤器的CAN_FxR1和CAN_FxR2分别表示一个32位过滤标识符。在掩码模式中CAN_FxR1表示过滤ID,CAN_FxR2表示过滤掩码。(另外需要注意的是CAN_FxRi[31:24]、CAN_FxRi[23:16]、CAN_FxRi[15:8]、CAN_FxRi[7:0]对应can2.0B中canID具体含义,标准帧设IDE=0,扩展帧则IDE=1;数据帧设RTR=0,远程帧则RTR=1。)
![](https://img-blog.csdnimg.cn/direct/da58155644e84dad9404822f83bd2258.png)
下图展示的是分别在掩码模式(CAN_FM1R寄存器的FBMx位=0)和标识符列表模式(CAN_FM1R寄存器的FBMx位=1)两种模式中同时位宽选择为16位下(CAN_FS1R寄存器的FSCx=0)过滤器组CAN_FxR1和CAN_FxR2两个寄存器中数据的含义。在标识符列表模式中一个过滤器的CAN_FxR1和CAN_FxR2分别表示两个16位过滤标识符,相当于一个过滤器组最多可以包含4个过滤16位过滤标识符。在掩码模式中CAN_FxR1的低16位表示过滤ID,CAN_FxR1高16位表示过滤掩码;CAN_FxR2的低16位也表示过滤ID,CAN_FxR1高16位也表示过滤掩码,相当于一个过滤器组最多可以包含2个16位掩码过滤设置。
![](https://img-blog.csdnimg.cn/direct/e54351bedd554e27a3ca630e793e5079.png)
2.4 相关寄存器
CAN filter master register (CAN_FMR)——过滤器主寄存器
Bits 31:14 Reserved, must be kept at reset value.
Bits 13:8 CAN2SB[5:0]: CAN2 start bank
These bits are set and cleared by software. They define the start bank for the CAN2
interface (Slave) in the range 0 to 27.
Note: When CAN2SB[5:0] = 28d, all the filters to CAN1 can be used.
When CAN2SB[5:0] is set to 0, no filters are assigned to CAN1.
Bits 7:1 Reserved, must be kept at reset value.
Bit 0 FINIT: Filter init mode
Initialization mode for filter banks
0: Active filters mode.
1: Initialization mode for the filters.
CAN filter mode register (CAN_FM1R)——过滤器模式设置寄存器
Bits 31:28 Reserved, must be kept at reset value.
Bits 27:0 FBMx: Filter mode
Mode of the registers of Filter x.
0: Two 32-bit registers of filter bank x are in Identifier Mask mode.
1: Two 32-bit registers of filter bank x are in Identifier List mode.
Note: Bits 27:14 are available in connectivity line devices only and are reserved otherwise.
CAN filter scale register (CAN_FS1R)——过滤器位宽设置寄存器
Bits 31:28 Reserved, must be kept at reset value.
Bits 27:0 FSCx: Filter scale configuration
These bits define the scale configuration of Filters 13-0.
0: Dual 16-bit scale configuration
1: Single 32-bit scale configuration
Note: Bits 27:14 are available in connectivity line devices only and are reserved otherwise.
CAN filter FIFO assignment register (CAN_FFA1R)——过滤器关联FIFO寄存器
Bits 31:28 Reserved, must be kept at reset value.
Bits 27:0 FFAx: Filter FIFO assignment for filter x
The message passing through this filter will be stored in the specified FIFO.
0: Filter assigned to FIFO 0
1: Filter assigned to FIFO 1
Note: Bits 27:14 are available in connectivity line devices only and are reserved otherwise.
CAN filter activation register(CAN_FA1R)—— 过滤器激活寄存器
Bits 31:28 Reserved, must be kept at reset value.
Bits 27:0 FACTx: Filter active
The software sets this bit to activate Filter x. To modify the Filter x registers (CAN_FxR[0:7]),
the FACTx bit must be cleared or the FINIT bit of the CAN_FMR register must be set.
0: Filter x is not active
1: Filter x is active
Note: Bits 27:14 are available in connectivity line devices only and are reserved otherwise.
Filter bank i register x (CAN_FiRx) (i=0..27, x=1, 2)——过滤器组i的配置寄存器
说明:过滤器组在不同系列产品中有14组或28组两种,i范围为(0~27),而每个一个过滤器组又有两个32位寄存器表示(x=1/2),所以fileter bank是一个最多有58个32位寄存器组成的寄存器集合。
在标识符模式中,寄存器的每一位表示期望接收的can标识符对应的电平;
0: 期望对应为电平为显性位;
1: 期望对应为电平为隐性位;
在屏蔽位模式中,每个过滤器组的第一个寄存器的每位表示是否需要对应位的标识符要与期望的标识符一致
0:表示不关心此位,改位不参与过滤
1:来的标识符位必须与过滤器对应的标识符寄存器位相一致。
2.5 hal库相关代码
①hal库过滤器配置结构体参数说明
/**
* @brief CAN filter configuration structure definition
*/
typedef struct
{
uint32_t FilterIdLow; /*对于32位过滤器,在标识符列表模式中表示第一个过滤ID的低16位,在掩码模式中表示过滤ID的低16位;对于16位过滤器,在标识符列表中表示第一个过滤ID,在掩码模式中表示第一个过滤ID。This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterIdHigh; /*对于32位过滤器,在标识符列表模式中表示第一个过滤ID的高16位,在掩码模式中表示过滤ID的高16位;对于16位过滤器,在标识符列表中表示第二个过滤ID,在掩码模式中表示第二个过滤ID。This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterMaskIdLow; /*对于32位过滤器,在标识符列表模式中表示第二个过滤ID的低16位,在掩码模式中表示过滤掩码的低16位;对于16位过滤器,在标识符列表中表示第三个过滤ID,在掩码模式中表示第一个过滤掩码。,This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterMaskIdHigh; /*对于32位过滤器,在标识符列表模式中表示第二个过滤ID的高16位,在掩码模式中表示过滤掩码的高16位;对于16位过滤器,在标识符列表中表示第四个过滤ID,在掩码模式中表示第二个过滤掩码。This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterFIFOAssignment; /*过滤器关联的FIFO(FIFO0 or FIFO1) */
uint32_t FilterBank; /*过滤器组的选择For single CAN this parameter must be a number between Min_Data = 0 and Max_Data = 13. For dual CAN this parameter must be a number between Min_Data = 0 and Max_Data = 27. */
uint32_t FilterMode; /*过滤器模式设置(标识符列表模式 or 屏蔽位模式)*/
uint32_t FilterScale; /*过滤器位宽设置(16bit or 32bit)*/
uint32_t FilterActivation; /*过滤器激活配置(Enable or disable)*/
uint32_t SlaveStartFilterBank; /*For single CAN instances, this parameter is meaningless.*/
} CAN_FilterTypeDef;
②hal库过滤器配置接口
/**
* @brief Configures the CAN reception filter according to the specified
* parameters in the CAN_FilterInitStruct.
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
* the configuration information for the specified CAN.
* @param sFilterConfig pointer to a CAN_FilterTypeDef structure that
* contains the filter configuration information.
* @retval None
*/
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, const CAN_FilterTypeDef *sFilterConfig)
{
uint32_t filternbrbitpos;
CAN_TypeDef *can_ip = hcan->Instance;
HAL_CAN_StateTypeDef state = hcan->State;
if ((state == HAL_CAN_STATE_READY) ||
(state == HAL_CAN_STATE_LISTENING))
{
/* Check the parameters */
assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterIdHigh));
assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterIdLow));
assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterMaskIdHigh));
assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterMaskIdLow));
assert_param(IS_CAN_FILTER_MODE(sFilterConfig->FilterMode));
assert_param(IS_CAN_FILTER_SCALE(sFilterConfig->FilterScale));
assert_param(IS_CAN_FILTER_FIFO(sFilterConfig->FilterFIFOAssignment));
assert_param(IS_CAN_FILTER_ACTIVATION(sFilterConfig->FilterActivation));
#if defined(CAN2)
/* CAN1 and CAN2 are dual instances with 28 common filters banks */
/* Select master instance to access the filter banks */
can_ip = CAN1;
/* Check the parameters */
assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->FilterBank));
assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->SlaveStartFilterBank));
#else
/* CAN1 is single instance with 14 dedicated filters banks */
/* Check the parameters */
assert_param(IS_CAN_FILTER_BANK_SINGLE(sFilterConfig->FilterBank));
#endif
//设置can过滤器FMR寄存器的INIT位为1进入初始化模式
/* Initialisation mode for the filter */
SET_BIT(can_ip->FMR, CAN_FMR_FINIT);
#if defined(CAN2)
/* Select the start filter number of CAN2 slave instance */
CLEAR_BIT(can_ip->FMR, CAN_FMR_CAN2SB);
SET_BIT(can_ip->FMR, sFilterConfig->SlaveStartFilterBank << CAN_FMR_CAN2SB_Pos);
#endif
/* Convert filter number into bit position */
filternbrbitpos = (uint32_t)1 << (sFilterConfig->FilterBank & 0x1FU);
//根据filterBank选择的过滤器组将can过滤器FA1R寄存器中的对应位置0
/* Filter Deactivation */
CLEAR_BIT(can_ip->FA1R, filternbrbitpos);
/* Filter Scale */
//在16位宽过滤器组设置中,寄存器FxR1和FxR2的数据分别由FilterMaskIdLow、FilterIdLow和FilterMaskIdHigh、FilterIdHigh组成
if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT)
{
/* 16-bit scale for the filter */
CLEAR_BIT(can_ip->FS1R, filternbrbitpos);
/* First 16-bit identifier and First 16-bit mask */
/* Or First 16-bit identifier and Second 16-bit identifier */
can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 =
((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16U) |
(0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);
/* Second 16-bit identifier and Second 16-bit mask */
/* Or Third 16-bit identifier and Fourth 16-bit identifier */
can_ip->sFilterRegister[sFilterConfig->FilterBank].FR2 =
((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |
(0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh);
}
//在32位宽过滤器组设置中,寄存器FxR1和FxR2的数据分别由FilterIdLow、FilterIdHigh和FilterMaskIdHigh、FilterMaskIdLow组成
if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)
{
/* 32-bit scale for the filter */
SET_BIT(can_ip->FS1R, filternbrbitpos);
/* 32-bit identifier or First 32-bit identifier */
can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 =
((0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) |
(0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);
/* 32-bit mask or Second 32-bit identifier */
can_ip->sFilterRegister[sFilterConfig->FilterBank].FR2 =
((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |
(0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow);
}
/* Filter Mode */
if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK)
{
/* Id/Mask mode for the filter*/
CLEAR_BIT(can_ip->FM1R, filternbrbitpos);
}
else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
{
/* Identifier list mode for the filter*/
SET_BIT(can_ip->FM1R, filternbrbitpos);
}
/* Filter FIFO assignment */
if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0)
{
/* FIFO 0 assignation for the filter */
CLEAR_BIT(can_ip->FFA1R, filternbrbitpos);
}
else
{
/* FIFO 1 assignation for the filter */
SET_BIT(can_ip->FFA1R, filternbrbitpos);
}
/* Filter activation */
if (sFilterConfig->FilterActivation == CAN_FILTER_ENABLE)
{
SET_BIT(can_ip->FA1R, filternbrbitpos);
}
/* Leave the initialisation mode for the filter */
CLEAR_BIT(can_ip->FMR, CAN_FMR_FINIT);
/* Return function status */
return HAL_OK;
}
else
{
/* Update error code */
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
return HAL_ERROR;
}
}
2.6 例程
①过滤器标识符列表模式(hal库)
//标准数据帧
uint16_t canFilterListStdId1 = 0x20;
uint8_t canFilterListRTR1 = 0; //数据帧
uint8_t canFilterListIDE1 = 0;//标准帧
//标准远程帧
uint16_t canFilterListStdId2 = 0x21;
uint8_t canFilterListRTR2 = 1; //远程帧
uint8_t canFilterListIDE2 = 0;//标准帧
hCAN_Filter.FilterBank = 0; //选择过滤器组0
hCAN_Filter.FilterMode = CAN_FILTERMODE_IDLIST; //标识符列表模式
hCAN_Filter.FilterScale = CAN_FILTERSCALE_16BIT; //16位宽
hCAN_Filter.FilterIdHigh = ((canFilterListStdId1 << 5) | (canFilterListRTR1 << 4) | (canFilterListIDE1 << 3)); //移位操作原理见16位宽寄存器组说明
hCAN_Filter.FilterIdLow = ((canFilterListStdId2 << 5) | (canFilterListRTR2 << 4) | (canFilterListIDE2 << 3)); //移位操作原理见16位宽寄存器组说明
hCAN_Filter.FilterMaskIdHigh = 0;//掩码区可以继续添加两个16位标识符,这里没用给0
hCAN_Filter.FilterMaskIdLow = 0;
hCAN_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
hCAN_Filter.FilterActivation = ENABLE;
hCAN_Filter.SlaveStartFilterBank = 0; //只用了can1,这个参数可以不关心
HAL_Status |= HAL_CAN_ConfigFilter(&hcan, &hCAN_Filter);
//扩展远程帧
uint32_t canFilterListStdId3 = 0x2000;
uint8_t canFilterListRTR3 = 1; //远程帧
uint8_t canFilterListIDE3 = 1;//扩展帧
//扩展数据帧
uint32_t canFilterListStdId4 = 0x2001;
uint8_t canFilterListRTR4 = 0; //数据帧
uint8_t canFilterListIDE4 = 1;//扩展帧
hCAN_Filter.FilterBank = 1; //选择过滤器组0
hCAN_Filter.FilterMode = CAN_FILTERMODE_IDLIST; //标识符列表模式
hCAN_Filter.FilterScale = CAN_FILTERSCALE_32BIT; //32位宽
hCAN_Filter.FilterIdHigh = (((canFilterListStdId3 << 3) >> 16) & 0xFFFF) | (canFilterListRTR3 << 1) | (canFilterListIDE3 << 2);
hCAN_Filter.FilterIdLow = ((canFilterListStdId3 << 3) & 0xFFFF) | (canFilterListRTR3 << 1) | (canFilterListIDE3 << 2);
hCAN_Filter.FilterMaskIdHigh = (((canFilterListStdId4 << 3) >> 16) & 0xFFFF) | (canFilterListRTR4 << 1) | (canFilterListIDE4 << 2);
hCAN_Filter.FilterMaskIdLow = ((canFilterListStdId4 << 3) & 0xFFFF) | (canFilterListRTR4 << 1) | (canFilterListIDE4 << 2);
hCAN_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
hCAN_Filter.FilterActivation = ENABLE;
hCAN_Filter.SlaveStartFilterBank = 0; //只用了can1,这个参数可以不关心
HAL_Status |= HAL_CAN_ConfigFilter(&hcan, &hCAN_Filter);
②过滤器掩码模式(hal库)
//16位宽掩码模式,只接收标准帧ID最高3位为1的标识符(即0x7xx),其它位不关心
uint8_t canFilterListIDE1 = 0;//标准帧
hCAN_Filter.FilterBank = 0; //选择过滤器组0
hCAN_Filter.FilterMode = CAN_FILTERMODE_IDMASK; //掩码模式
hCAN_Filter.FilterScale = CAN_FILTERSCALE_16BIT; //16位宽
hCAN_Filter.FilterIdHigh = 0;//这里没用,给0
hCAN_Filter.FilterIdLow = (0x700 << 5) | (0x01 << 3); //ID
hCAN_Filter.FilterMaskIdHigh = 0;//这里没用,给0
hCAN_Filter.FilterMaskIdLow = (0x700 << 5) | (canFilterListIDE1 << 3); //掩码
hCAN_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
hCAN_Filter.FilterActivation = ENABLE;
hCAN_Filter.SlaveStartFilterBank = 0; //只用了can1,这个参数可以不关心
HAL_Status |= HAL_CAN_ConfigFilter(&hcan, &hCAN_Filter);
//32位宽掩码模式,只接收标准帧ID最高2位为1的标识符(即0x6xx),其它位不关心
uint8_t canFilterListIDE2 = 0;//标准帧
hCAN_Filter.FilterBank = 1; //选择过滤器组1
hCAN_Filter.FilterMode = CAN_FILTERMODE_IDMASK; //掩码模式
hCAN_Filter.FilterScale = CAN_FILTERSCALE_32BIT; //32位宽
hCAN_Filter.FilterIdHigh = 0x600 << 5;
hCAN_Filter.FilterIdLow = canFilterListIDE2 << 2;
hCAN_Filter.FilterMaskIdHigh = 0x600 << 5;
hCAN_Filter.FilterMaskIdLow = 0x01 << 2;
hCAN_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
hCAN_Filter.FilterActivation = ENABLE;
hCAN_Filter.SlaveStartFilterBank = 0; //只用了can1,这个参数可以不关心
HAL_Status |= HAL_CAN_ConfigFilter(&hcan, &hCAN_Filter);