STM32之关于CAN过滤器配置16位标识符屏蔽模式的纠错

本文讲述了作者在配置CAN通信16位屏蔽模式时遇到的问题,通过对比和实验发现错误在于对标准帧和扩展帧处理的不同。作者分享了正确的配置方法和CAN初始化代码示例,适用于STM32F103平台。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本人在学习CAN通信的过滤器配置的过程中,对位宽为16位的屏蔽码模型的寄存器设置一直产生错误。

1、在网上查找资料,包括CSDN中,参考他们的说明以及代码编写CAN外设的四种,发现除了 位宽为16位的屏蔽码模式一直有错误外,其他三种都可以正常实验。直到我发现了这个资料,按照资料所述,配置CAN过滤器的两个32位寄存器,发现能正常工作,另外将我编写的CAN初始化代码分享如下,里面包含了CAN过滤器的四种配置。

根据上述表中第四行所示,配置两个ID和他们对应的掩码,可以正常运行。

2、以下为CAN过滤器的16位标识符屏蔽模式(相当于两个屏蔽器,只能过滤标准帧,不能过滤扩展帧,因为扩展帧的ID为29位)的代码:

     //选择机器5   筛选ID为:0x52-0x53 ,0x60-x063
     // 机器5 16位标识符屏蔽模式(相当于两个屏蔽器,同上 只能过滤标准帧,不能过滤扩展帧)
    CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
   	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x060<<5;高16位 为ID1   0b0000 1100 0000 0000      
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x52<<5;  //  低16位 为ID2   0b0000 1010 0100 0000
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xff9f;//高16位 为屏蔽1 0b1111 1111 1001 1111
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xffdf;// 低16位 为屏蔽2 0b1111 1111 1101 1111   
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
 	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0 

注:代码中的 ID1对应屏蔽1,ID2对应屏蔽2。 

 3、以下是我所写的CAN初始化代码,基于stm32f103系列芯片。

       使用了宏定义:#define Choice_MCU    5    // 可设置的值为1 2 3..... 分别选择机械1 2 3模式

来选择不同的CAN过滤器工作模式:

u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

	  GPIO_InitTypeDef GPIO_InitStructure; 
	  CAN_InitTypeDef        CAN_InitStructure;
 	  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
#if CAN_RX0_INT_ENABLE 
   	NVIC_InitTypeDef  NVIC_InitStructure;
#endif

	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;   //TX
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽
    GPIO_Init(GPIOA, &GPIO_InitStructure);		//初始化IO
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;   //RX

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化IO
	  
 	//CAN单元设置
 	  CAN_InitStructure.CAN_TTCM=DISABLE;						 //非时间触发通信模式  //
 	  CAN_InitStructure.CAN_ABOM=DISABLE;						 //软件自动离线管理	 //
  	CAN_InitStructure.CAN_AWUM=DISABLE;						 //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//
  	CAN_InitStructure.CAN_NART=ENABLE;						 	//禁止报文自动传送 //
  	CAN_InitStructure.CAN_RFLM=DISABLE;						 //报文不锁定,新的覆盖旧的 // 
  	CAN_InitStructure.CAN_TXFP=DISABLE;						 //优先级由报文标识符决定 //
  	CAN_InitStructure.CAN_Mode= mode;	         //模式设置: mode:0,普通模式;1,回环模式; //
  	//设置波特率
  	CAN_InitStructure.CAN_SJW=tsjw;				//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位  CAN_SJW_1tq	 CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
  	CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
  	CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~	CAN_BS2_8tq
  	CAN_InitStructure.CAN_Prescaler=brp;            //分频系数(Fdiv)为brp+1	//
  	CAN_Init(CAN1, &CAN_InitStructure);            // 初始化CAN1 
#if Choice_MCU==1	            //选择机器1   0x50~0x57
 	CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
   	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x50<<5;32位ID
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xff1f;//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xffff;
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
 	  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0      
#elif Choice_MCU==2            //选择机器2   0x51,0x55,0x59,0x5d    
    CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
   	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x51<<5;32位ID
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xfe7f;//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xffff;
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
 	  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0  
#elif Choice_MCU==3            //选择机器3  0x59 和 0x1800f001
     // 机器3 32位标识符列表模式 2个ID
    u32 ext_id =0x1800f001;
    CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
   	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList;  // 列表模式  
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x059<<5;                      // 第一个ID高八位  标准帧
  	CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_Id_Standard;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=((ext_id<<3)>>16) & 0xffff;// 第二个ID高八位  扩展帧
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=((ext_id<<3)& 0xffff) | CAN_Id_Extended;
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
 	  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0   
#elif Choice_MCU==4            //选择机器4  筛选ID为:0x50 0x53 0x57 0x63
     // 机器4 16位标识符列表模式(16位不能过滤扩展帧,扩展帧必须是32位)
     // 16位列表可以筛选4个ID(只能是标准帧),32为列表可以 筛选2个ID(可以是扩展帧)
    CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
   	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit; //16位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x050<<5;    // 第一个ID  0x050 0b0000 1010 0000 0000
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x053<<5;     // 第二个ID
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x057<<5;// 第三个ID
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x063<<5; // 第四个ID
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
 	  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0   
#elif Choice_MCU==5            //选择机器5   筛选ID为:0x52-0x53 ,0x60-x063
     // 机器3 16位标识符屏蔽模式(相当于两个屏蔽器,同上 只能过滤标准帧,不能过滤扩展帧)
    CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
   	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x060<<5;高16位 为ID1   0b0000 1100 0000 0000      
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x52<<5;  //  低16位 为ID2   0b0000 1010 0100 0000
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xff9f;//高16位 为屏蔽1 0b1111 1111 1001 1111
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xffdf;// 低16位 为屏蔽2 0b1111 1111 1101 1111   
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
 	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0   


#endif  
  	CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
#if CAN_RX0_INT_ENABLE
	
	  CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.		    
  
  	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(&NVIC_InitStructure);
#endif
	return 0;
}   

4、实验效果

硬件资源:4个stm32f03系列单片机,4个SN65HVD230(3.3V)CAN收发器 ,3个基于I2C的OLED和1个基于SPI的OLED,按键若干。

测试了上述代码中的1、2、4、5四种情况(图片中MCU从上到下),效果理想。

上传不了视频

CAN测试1

5、纠错

        以下图片是我之前从CSDN等开源网站上查找到的各种资料,现在经我实验,发现是错误的。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值