CAN通讯难点———验收筛选器

验收筛选器

CAN外设的验收筛选器,一共有28个筛选器组,每个筛选器组有2个寄存器,CAN1和CAN2共用的筛选器的。在 CAN 协议中,消息的标识符与节点地址无关,但与消息内容有关。因此,发送节点将报文广播给所有接收器时,接收节点会根据报文标识符的值来确定软件是否需要该消息,为了简化软件的工作,STM32的CAN外设接收报文前会先使用验收筛选器检查,只接收需要的报文到FIFO中。

筛选器工作的时候,可以调整筛选ID的长度及过滤模式。
根据筛选ID长度来分类有有以下两种:
检查 STDID[10:0]、 EXTID[17:0]、 IDE 和 RTR 位,一共31位。
检查STDID[10:0]、 RTR、 IDE 和 EXTID[17:15],一共16位。

而根据过滤的方法分为以下两种模式:
标识符列表模式:它把要接收报文的ID列成一个表,要求报文ID与列表中的某一个标识符完全相同才可以接收,可以理解为白名单管理。
掩码模式:它把可接收报文ID的某几位作为列表,这几位被称为掩码,可以把它理解成关键字搜索,只要掩码(关键字)相同,就符合要求,报文就会被保存到接收FIFO。
在这里插入图片描述
RTR位(Remote Transmission Request Bit),译作远程传输请求位,它是用于区分数据帧和遥控帧的,当它为显性电平时表示数据帧,隐性电平时表示遥控帧。
IDE位(Identifier Extension Bit),译作标识符扩展位,它是用于区分标准格式与扩展格式,当它为显性电平时表示标准格式,隐性电平时表示扩展格式。
SRR位(Substitute Remote Request Bit),只存在于扩展格式,它用于替代标准格式中的RTR位。由于扩展帧中的SRR位为隐性位,RTR在数据帧为显性位,所以在两个ID相同的标准格式报文与扩展格式报文中,标准格式的优先级较高。

每组筛选器包含2个32位的寄存器,分别为CAN_FxR1和CAN_FxR2,它们用来存储要筛选的ID或掩码,各个寄存器位代表的意义与图中两个寄存器下面“映射”的一栏一致,各个模式的说明如下:
在这里插入图片描述
筛选器设置举例:
在这里插入图片描述
如在掩码模式时,第一个寄存器存储要筛选的ID,第二个寄存器存储掩码,掩码为1的部分表示该位必须与ID中的内容一致,筛选的结果为表中第三行的ID值,它是一组包含多个的ID值,其中x表示该位可以为1可以为0。如工作在标识符模式时,2个寄存器存储的都是要筛选的ID,它只包含2个要筛选的ID值(32位模式时)。如果使能了筛选器,且报文的ID与所有筛选器的配置都不匹配,CAN外设会丢弃该报文,不存入接收FIFO。筛选器结构体:CAN_FilterInitTypeDef。
对于标识符列表模式,只要将掩码模式配置成全部都匹配就是一样的功能。

模式1:32位掩码模式

void CAN_Filter_Config(void)
{
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
	/*CAN筛选器初始化*/
	CAN_FilterInitStructure.CAN_FilterNumber=0;						//筛选器组0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;	//工作在掩码模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;	//筛选器位宽为单个32位。
	/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */
	CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;		//要筛选的ID高位 
	CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要筛选的ID低位 
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0xFFFF;			//筛选器高16位每位必须匹配
	CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF;			//筛选器低16位每位必须匹配
	
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ;				//筛选器被关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;			//使能筛选器
	CAN_FilterInit(&CAN_FilterInitStructure);
	/*CAN通信中断使能*/
	CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}

模式2:32位标识符模式

void CAN_Filter_Config(void)
{
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;

	/*CAN筛选器初始化*/
	CAN_FilterInitStructure.CAN_FilterNumber=0;						//筛选器组0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList;	//工作在标识符模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;	//筛选器位宽为单个32位。
	/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */

	CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x13<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;		
	CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x13<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; 
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh= ((((u32)0x14<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;			
	CAN_FilterInitStructure.CAN_FilterMaskIdLow= (((u32)0x14<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; 
			
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ;				//筛选器被关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;			//使能筛选器
	CAN_FilterInit(&CAN_FilterInitStructure);
	/*CAN通信中断使能*/
	CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}

模式3:16位掩码模式

void CAN_Filter_Config(void)
{
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;

	/*CAN筛选器初始化*/
	CAN_FilterInitStructure.CAN_FilterNumber=0;						//筛选器组0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;	//工作在掩码模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;	//筛选器位宽为单个16位。
	/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */

	CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x13<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF0000)>>16;		
	CAN_FilterInitStructure.CAN_FilterIdLow= 0xFFFF;			
	
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh= ((((u32)0x24<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF0000)>>16; 	
	CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF; 		
	
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ;				//筛选器被关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;			//使能筛选器
	CAN_FilterInit(&CAN_FilterInitStructure);
	/*CAN通信中断使能*/
	CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}

模式4:16位标识符模式

void CAN_Filter_Config(void)
{
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;

	/*CAN筛选器初始化*/
	CAN_FilterInitStructure.CAN_FilterNumber=0;						//筛选器组0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList;	//工作在标识符模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;	//筛选器位宽为单个16位。
	/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */

	CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x13<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF0000)>>16;		
	CAN_FilterInitStructure.CAN_FilterIdLow= ((((u32)0x13<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF0000)>>16;				
	
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh= ((((u32)0x24<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF0000)>>16; 	
	CAN_FilterInitStructure.CAN_FilterMaskIdLow= ((((u32)0x24<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF0000)>>16; 			
	
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ;				//筛选器被关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;			//使能筛选器
	CAN_FilterInit(&CAN_FilterInitStructure);
	/*CAN通信中断使能*/
	CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}

要注意:在主函数(main.c)里和中断函数(stm32f10x_it.c 文件)里也要按相应的要求改。
如果想要修改关联到FIFO0或者FIFO1,中断服务函数名要改。

#define CAN_RX_IRQ								USB_LP_CAN1_RX0_IRQn            //当使用CAN_Filter_FIFO0时
#define CAN_RX_IRQHandler					USB_LP_CAN1_RX0_IRQHandler

#define CAN_RX_IRQ1                CAN1_RX1_IRQn           //当使用CAN_Filter_FIFO1时
#define CAN_RX_IRQHandler1	        CAN1_RX1_IRQHandler

筛选器组修改如下:

void CAN_Filter_Config(void)
{
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
	/*CAN筛选器初始化*/
	CAN_FilterInitStructure.CAN_FilterNumber=1;						//筛选器组1
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;	//工作在掩码模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;	//筛选器位宽为单个16位。
	/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO1。 */

	CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x67<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF0000)>>16;		
	CAN_FilterInitStructure.CAN_FilterIdLow= 0xFFFF;			
	
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh= ((((u32)0x45<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF0000)>>16; 	
	CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF; 		
	
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO1 ;				//筛选器被关联到FIFO1
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;			//使能筛选器
	CAN_FilterInit(&CAN_FilterInitStructure);
	/*CAN通信中断使能*/
	CAN_ITConfig(CANx, CAN_IT_FMP1, ENABLE);
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页