STM CAN filter配置纪要

案例1:某工程师使用STM32F407VG开发产品,在做CAN的调试过程中发现,CAN1接收、CAN2发送,工作正常。但反过来就有问题,即CAN2收,CAN1发就无法正常接收。
后来发现CAN 过滤器配置的地方有问题。他使用STM32Cube固件库,两句关键代码如下:

sFilterConfig.FilterNumber = m; //……【1】
sFilterConfig.BankNumber = n; //……【2】

第【1】句代码就是选择某过滤器组进行初始化并配置接收过滤器。对于双CAN产品,m的值为0到27。对于单CAN产品而言,m的值为0~13。
第【2】句代码针对双CAN的STM32产品,配置CAN2可使用的过滤器组的起始编号,n取值范围为0~28.从编号为n的过滤器组到编号为27的过滤器组分配给CAN2使用。通过配置寄存器CAN2SB[5:0]@CAN_FRM确定。如果第【2】句配置不在代码中明确写出来,默认值就是14. 即硬件默认将编号为14起往后的过滤器组分配给CAN2使用。


void CanBus_Config(void)
{

    CAN_InitTypeDef CAN_InitStructure;
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    /* CAN register init */
    // CAN_DeInit();
    /* CAN1 and CAN2 register init */
    CAN_DeInit(CAN1);
    CAN_DeInit(CAN2);


    /* Struct init*/
    CAN_StructInit(&CAN_InitStructure);


    /*************************************************************

    主机CAN配置

    *************************************************************/


    /* CAN cell init */
    CAN_InitStructure.CAN_TTCM = DISABLE; //禁止时间触发通信模式
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_NART = DISABLE;
    //CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_TXFP = DISABLE;
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
    CAN_InitStructure.CAN_BS1 = CAN_BS1_10tq; //1--16
    CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq; //1--8
    CAN_InitStructure.CAN_Prescaler = 4;//8  波特率=Fpclk1/(sjw+bs1+bs2)/pre
    (pclk1/((1+8+7)*16)) = 36Mhz/16/4 = 500Kbits
    //CAN_Init(&CAN_InitStructure);

    /*Initializes the CAN1  and CAN2 */
    CAN_Init(CAN1, &CAN_InitStructure);


    /* CAN cell init */
    CAN_InitStructure.CAN_TTCM = DISABLE; //禁止时间触发通信模式
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_NART = DISABLE;
    //CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_TXFP = DISABLE;
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
    CAN_InitStructure.CAN_BS1 = CAN_BS1_10tq; //1--16
    CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq; //1--8
    CAN_InitStructure.CAN_Prescaler =4;//4:500k//8 :250K//16:125K  波特率=Fpclk1/(sjw+bs1+bs2)/pre
    (pclk1/((1+8+7)*16)) = 36Mhz/16/4= 500Kbits
    CAN_Init(CAN2, &CAN_InitStructure);
#if 1




    CAN_FilterInitStructure.CAN_FilterNumber = 1; //选择过滤器0~13 for one can register 
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;//IdList mode or IdMask mode
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;//16bits or 32bits
    CAN_FilterInitStructure.CAN_FilterIdHigh = AUD_A4L_CAN_Light_Mode_STD_ID << 5;
    CAN_FilterInitStructure.CAN_FilterIdLow =AUD_A4L_CAN_Lightness_And_CD_ONOFF_STD_ID << 5;  //
    //CAN_FilterInitStructure.CAN_FilterMaskIdHigh = CAN_ID_STD; 
    //CAN_FilterInitStructure.CAN_FilterMaskIdLow = CAN_ID_STD; 

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数



    CAN_FilterInitStructure.CAN_FilterNumber = 2; //选择过滤器0~13 for one can register 
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;//IdList mode or IdMask mode
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//16bits or 32bits
    CAN_FilterInitStructure.CAN_FilterIdHigh = ((AUD_A4L_CAN_Key_Control_Knob_EXT_ID << 3)>>16&0xffff);
    CAN_FilterInitStructure.CAN_FilterIdLow = ((AUD_A4L_CAN_Key_Control_Knob_EXT_ID<<3)&0xffff)|CAN_ID_EXT; //


    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数


 /*************************************************************

    CAN2 接收

 *************************************************************/

     CAN_FilterInitStructure.CAN_FilterNumber = 14; //选择过滤器0~13 for one can register 
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;//IdList mode or IdMask mode
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//16bits or 32bits
    CAN_FilterInitStructure.CAN_FilterIdHigh = ((AUD_A4L_CAN_RADA_EXT_ID << 3)>>16&0xffff);
    CAN_FilterInitStructure.CAN_FilterIdLow = ((AUD_A4L_CAN_RADA_EXT_ID<<3)&0xffff)|CAN_ID_EXT; //

    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ((AUD_A4L_CAN_Media_Statu_EXT_ID<<3)>>16)&0xffff; 
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((AUD_A4L_CAN_Media_Statu_EXT_ID<<3)&0xffff)|CAN_ID_EXT; 

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数


    CAN_FilterInitStructure.CAN_FilterNumber = 15; //选择过滤器7
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = ((AUD_A4L_CAN_Time_EXT_ID << 3)>>16)&0xffff;
    CAN_FilterInitStructure.CAN_FilterIdLow = ((AUD_A4L_CAN_Time_EXT_ID << 3)&0xffff)|CAN_ID_EXT; //

    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ((AUD_A4L_CAN_Audio_Synchronous_EXT_ID << 3)>>16&0xffff);
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((AUD_A4L_CAN_Audio_Synchronous_EXT_ID<<3)&0xffff)|CAN_ID_EXT;

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数




    CAN_FilterInitStructure.CAN_FilterNumber = 16; //选择过滤器0~13 for one can register 
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;//IdList mode or IdMask mode
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//16bits or 32bits
    CAN_FilterInitStructure.CAN_FilterIdHigh = ((AUD_A4L_CAN_Key_Control_Knob_EXT_ID << 3)>>16&0xffff);
    CAN_FilterInitStructure.CAN_FilterIdLow = ((AUD_A4L_CAN_Key_Control_Knob_EXT_ID<<3)&0xffff)|CAN_ID_EXT; //

    //CAN_FilterInitStructure.CAN_FilterMaskIdHigh =CAN_ID_EXT;
    //CAN_FilterInitStructure.CAN_FilterMaskIdLow = CAN_ID_EXT;

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数


    CAN_FilterInitStructure.CAN_FilterNumber = 17; //选择过滤器0~13 for one can register 
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;//IdList mode or IdMask mode
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//16bits or 32bits
    CAN_FilterInitStructure.CAN_FilterIdHigh = ((AUD_A4L_CAN_MUTE_STATUS_EXT_ID << 3)>>16&0xffff);
    CAN_FilterInitStructure.CAN_FilterIdLow = ((AUD_A4L_CAN_MUTE_STATUS_EXT_ID<<3)&0xffff)|CAN_ID_EXT; //

    CAN_FilterInitStructure.CAN_FilterMaskIdHigh =((AUD_A4L_CAN_BL_PHONE_NUM_SHOW_EXT_ID<<3)>>16&0XFFFF);
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((AUD_A4L_CAN_BL_PHONE_NUM_SHOW_EXT_ID<<3)&0XFFFF)|CAN_ID_EXT;

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数

   CAN_FilterInitStructure.CAN_FilterNumber = 18; //选择过滤器7
   CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
   CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;

   CAN_FilterInitStructure.CAN_FilterIdHigh = AUD_A4L_CAN_RADA_ONOFF_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterIdLow = AUD_A4L_CAN_HandBrake_STD_ID << 5; //

   CAN_FilterInitStructure.CAN_FilterMaskIdHigh = AUD_A4L_CAN_STEER_KEY_STD_ID << 5;       
   CAN_FilterInitStructure.CAN_FilterMaskIdLow = AUD_A4L_CAN_Turn_Angle_STD_ID << 5;

   CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
   CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数



   CAN_FilterInitStructure.CAN_FilterNumber = 19; //选择过滤器7
   CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
   CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
   CAN_FilterInitStructure.CAN_FilterIdHigh = AUD_A4L_CAN_Gears_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterIdLow = AUD_A4L_CAN_EngineSpeed_STD_ID << 5; //
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh = AUD_A4L_CAN_Speed_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterMaskIdLow = AUD_A4L_CAN_Car_Front_Hood_STD_ID << 5;

   CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
   CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数




   CAN_FilterInitStructure.CAN_FilterNumber = 20; //选择过滤器7
   CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
   CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
   CAN_FilterInitStructure.CAN_FilterIdHigh = AUD_A4L_CAN_Infrared_Lock_Car_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterIdLow = AUD_A4L_CAN_Door_Rear_L_STD_ID << 5; //

   CAN_FilterInitStructure.CAN_FilterMaskIdHigh = AUD_A4L_CAN_Door_Rear_R_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterMaskIdLow =  AUD_A4L_CAN_Door_Front_L_STD_ID << 5;

   CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
   CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数



   CAN_FilterInitStructure.CAN_FilterNumber = 21; //选择过滤器7
   CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
   CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
   CAN_FilterInitStructure.CAN_FilterIdHigh = AUD_A4L_CAN_Door_Front_R_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterIdLow =  AUD_A4L_CAN_Door_Infor_STD_ID << 5; //
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh = AUD_A4L_CAN_MileageRemain_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterMaskIdLow = AUD_A4L_CAN_Engine_Coolant_Temp_STD_ID << 5; 

   CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
   CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数



   CAN_FilterInitStructure.CAN_FilterNumber = 22; //选择过滤器0~13 for one can register 
   CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;//IdList mode or IdMask mode
   CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;//16bits or 32bits
   CAN_FilterInitStructure.CAN_FilterIdHigh = AUD_A4L_CAN_SafeBelt_Statu_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterIdLow =AUD_A4L_CAN_Turn_Light_LR_Statu_STD_ID << 5;
   //CAN_FilterInitStructure.CAN_FilterMaskIdHigh =CAN_ID_STD; 
   //CAN_FilterInitStructure.CAN_FilterMaskIdLow =CAN_ID_STD;  

   CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
   CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数


   CAN_FilterInitStructure.CAN_FilterNumber = 23; //选择过滤器0~13 for one can register 
   CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;//IdList mode or IdMask mode
   CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//16bits or 32bits
   CAN_FilterInitStructure.CAN_FilterIdHigh = AUD_A4L_CAN_Oil_Mass_Outdoor_Temp_STD_ID << 5;
   CAN_FilterInitStructure.CAN_FilterIdLow = CAN_ID_STD; //

   CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; //选择FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能过滤器
   CAN_FilterInit(&CAN_FilterInitStructure); //进入初始化函数




    #endif
    CAN_SlaveStartBank(13);//Miller
    //-------------------------------------------------------------

    /* CAN FIFO0 message pending interrupt enable */
    CAN_ITConfig(CAN1, CAN_IT_FMP0 | CAN_IT_FF0, ENABLE);
    /* CAN FIFO0 message pending interrupt enable */
    CAN_ITConfig(CAN2, CAN_IT_FMP0 | CAN_IT_FF0, ENABLE);
}

对于双CAN STM32芯片,如果sFilterConfig.BankNumber=0,则所有过滤器组分配给CAN2使用,CAN1没得用。若sFilterConfig.BankNumber=27,则所有过滤器组分配给CAN1使用,CAN2就没得用了。

具体结合到本案例,客户代码里对CAN1、CAN2的过滤器进行配置时,当前过滤器组始终为0,即sFilterConfig.FilterNumber=0,而分配给CAN2的过滤器组又是从BANK 14开始的,即sFilterConfig.BankNumber = 14。

这样配置的话,CAN1接收,CAN2发的确不会有问题。反过来,CAN1发送,CAN2接收就会有问题。因为他一方面只是将Filter BANK 14到27分配给CAN2,同时又选择Filter BANK 0来配置CAN2的接收滤波器。所以要想CAN1发送,CAN2接收正常,其它参数不动的话,为CAN2配置滤波器时选择的过滤器组【Filter BANK】至少为14才可以,即sFilterConfig.FilterNumber=14。
案例2:在STM32双CAN产品中,CAN2不能进行接收,发送没问题。

这个问题经常有人碰到。很多情况是因为用户没有开启CAN1,或者在配置滤波器时,不是使用CAN1作为主体,而选择了CAN2。对于STM32双CAN芯片,CAN专用SRAM的访问以及对外来数据的滤波接收功能统一通过CAN1行使。因此,CAN1被称作为Master,CAN2被称作为Slave.换言之,CAN2对专用SRAM的访问和对信息滤波接收须借助CAN1来实现和管理。

顺便提下,这里说的MASTER CAN1和 SLAVE CAN2是从芯片内部资源管理职能而言的,并非针对CAN节点通信而言,否则就让人犯迷糊了。毕竟CAN通信并没有主从的说法。打个比方,就像你和某人一组共用一批设备各自做自己的课题,对方为组长。原则上这些设备共用,但由组长管理。你需要使用某些设备时需对方的协助与支持,至于你到底做什么,对方不干涉。反过来,组长需要使用那些设备时就不需要你的支持和协助,它自行使用和管理。

在使用STM32Cube库配置CAN2的过滤器时,早期版本在做CAN2的过滤器配置使用如下函数将CanHandle配置为CAN2时会有问题,须改用CAN1。不过后来的版本将这点做了修正。即使此为CAN2,在具体配置过滤器时的函数里还是会用CAN1去配置,详细可以查看该函数代码。【记得尽量使用最新版本库或手册】

HAL_CAN_ConfigFilter(&CanHandle,&sFilterConfig)

好,回到标题提到的关于STM32 CAN应用中的几个术语,过滤器组、过滤器、过滤器编号、过滤器索引。

过滤器组【filter bank】,是配置过滤器的原始资源,由2个32位寄存器组成。单CAN芯片有14个过滤器组,双CAN芯片有28个过滤器组,过滤器组编号由硬件拟定。一个过滤器组根据不同的过滤器模式【过滤方式和过滤器宽度】可配置1-4个过滤器。显然,过滤器组并不等同于过滤器。就好像说渔网的编制线材不等同于渔网一样的道理。过滤器组经过适当的配置后才能形成对信息具有过滤作用的过滤器。

做过滤器配置时,首先要选择过滤器组,然后配置过滤器的模式及宽度、并将配置的过滤器组与接收FIFO关联、激活当前的过滤器组。
在对过滤器组进行配置生成过滤器时,各个过滤器都被硬件自动编号,使得每个过滤器都有个编号【Filter Number】。CAN有两个FIFO,即FIFO0/FIFO1.这里有两套过滤器编号,即关联到FIFO0的过滤器与关联到FIFO1的过滤器分别各自从0开始依次编号。

表一、关联到FIFO0/FIFO1的过滤器编号示例
关联到FIFO里的过滤器组的过滤器的编号原则:
先依据过滤器组的编号大小做基本排序,再按照组内过滤模式及过滤器数量排序编号,可以参照表一、表二协助理解。

表二、过滤器组的配置及内部过滤器编号顺序

简单点讲,过滤器编号就是关联到各FIFO里的过滤器的序号,而且过滤器的编号跟过滤器组是否激活无关,只要配置且关联到FIFO就行。那过滤器匹配索引又是什么呢?

我们知道,一旦外来信息通过过滤器就会存放到相应的FIFO里,然后通过应用程序从FIFO中读取信息数据到SRAM。为了读取FIFO里的数据及进行存储,往往先要识别信息标识符,然后根据不同标识符将信息数据放到相应位置。不过,以信息标识符为标准来进行判别以及相应的存储访问,这个过程效率就不高。为此,CAN控制器就提供了过滤器匹配索引值【Filter Match Index】这个东西。

当外来信息通过过滤器后存储信息到FIFO的邮箱时,硬件自动将相应的过滤器编号写入FIFO邮箱内相关寄存器的过滤器匹配索引值【FMI】。所以,本质上讲过滤器匹配索引值跟过滤器编号是同一个数据,但代表的意义不一样。FMI表示本信息是经过哪个编号的过滤器匹配过滤而来。通过FMI可以快速找到相应的报文信息。

有了FMI,我们可以利用它作为数组序列直接访问相应的目的信息数据,或者拿收到的报文邮箱里的FMI跟所期望的数值比较来对信息筛选分类等。比如,考生除了名字外,一般都有准考证号。当考完试后,准考证可作为查分索引。如果没有这个准考证号,可能就得敲入考点、学生名字等多个身份信息,但效率就差了很多。

根据过滤器的配置与过滤规则,可能会出现一个外来信息可以通过多个过滤器的情况。这时FMI的值到底取哪一个过滤器的编号呢?这里就根据过滤器优先级原则来定。有如下三条规则:

1、32位过滤器优先于16位过滤器。
2、当过滤器同等宽度时,标识符列表模式优先于标识符屏蔽模式。
3、当过滤器模式及宽度一样时,低过滤器编号优先于高过滤器编号。

假设我们要接收多个ID:0x7e9,0x1800f001,前面为标准ID,后面为扩展ID,要同时能接收这两个ID,那么该如何设置这个过滤器呢?

1.  CAN_FilterInitTypeDef  CAN_FilterInitStructure;  
2.  U16 std_id =0x7e9;  
3.  U32 ext_id =0x1800f001;  
4.  U32 mask =0;  
5.    
6.  CAN_FilterInit(&CAN_FilterInitStructure);     //初始化CAN_FilterInitStructrue结构体变量  
7.  CAN_FilterInitStructure.CAN_FilterNumber=0;      //设置过滤器组0,范围为0~13  
8.  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;    //设置过滤器组0为屏蔽模式  
9.  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;   //设置过滤器组0位宽为32位  
10.   
11. //标识位寄存器的设置  
12. //ext_id<<3对齐,见上图9,再>>16取高16位  
13. CAN_FilterInitStructure.CAN_FilterIdHigh=((ext_id<<3) >>16) &0xffff;  //设置标识符寄存器高字节。  
14. CAN_FilterInitStructure.CAN_FilterIdLow=(U16)(ext_id<<3) | CAN_ID_EXT;   //设置标识符寄存器低字节  
15. //这里也可以这样设置  
16. //CAN_FilterInitStructure.CAN_FilterIdHigh=std_id<<5;  //设置标识符寄存器高字节.这里为什么是左移5位呢?从上图可以看出,CAN_FilterIdHigh包含的是STD[0~10]和EXID[13~17],标准CAN ID本身是不包含扩展ID数据,因此为了要将标准CAN ID放入此寄存器,标准CAN ID首先应左移5位后才能对齐.  
17. //CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_ID_EXT;   //设置标识符寄存器低字节,这里也可以设置为CAN_ID_STD  
18.   
19. //屏蔽寄存器的设置  
20. //这里的思路是先将标准CAN ID和扩展CAN ID对应的ID值先异或后取反,为什么?异或是为了找出两个CAN ID有哪些位是相同的,是相同的位则说明需要关心,需要关心的位对应的屏蔽码位应该设置为1,因此需要取反一下。最后再整体左移3位。  
21. mask =(std_id<<18);//这里为什么左移18位?因为从ISO11898中可以看出,标准CAN ID占ID18~ID28,为了与CAN_FilterIdHigh对齐,应左移2位,接着为了与扩展CAN对应,还应该再左移16位,因此,总共应左移2+16=18位。也可以用另一个方式来理解:直接看Mapping的内容,发现STDID相对EXID[0]偏移了18位,因此左移18位.  
22. mask ^=ext_id;//将对齐后的标准CAN与扩展CAN异或后取反  
23. mask =~mask;  
24. mask <<=3;//再整体左移325. mask |=0x02; //只接收数据帧,不接收远程帧  
26. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=(mask>>16)&0xffff; //设置屏蔽寄存器高字节  
27. CAN_FilterInitStructure.CAN_FilterMaskIdLow=mask&0xffff;   //设置屏蔽寄存器低字节  
28.   
29. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;  //此过滤器组关联到接收FIFO0  
30. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活此过滤器组  
31. CAN_FilterInit(&CAN_FilterInitStructure); //设置过滤器  

can:filter总结:1.两组can,can1与can2有0~27组过滤器;
2.配置成32位掩码过滤器有28组,配置成16位掩码过滤器有56组;
3.配置成32位列表过滤器有56组,配置成16位列表过滤器有112组过滤器。

  • 10
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
STM32配置CAN可以按照以下步骤进行: 1. 初始化CAN寄存器:使用CAN_DeInit函数对CAN寄存器进行初始化。然后使用CAN_StructInit函数初始化CAN_InitStructure结构体。 2. 配置CAN单元:通过设置CAN_InitStructure结构体中的各个参数来配置CAN单元的工作模式和时序。例如,可以设置CAN_InitStructure.CAN_Mode为CAN_Mode_Normal以选择正常模式,设置CAN_InitStructure.CAN_SJW、CAN_InitStructure.CAN_BS1和CAN_InitStructure.CAN_BS2来定义时间段1和时间段2的长度,设置CAN_InitStructure.CAN_Prescaler来定义波特率分频器的值。 3. 初始化CAN:使用CAN_Init函数将配置好的CAN_InitStructure结构体传递给CAN_Init函数进行初始化。如果初始化失败,可以返回错误。 4. 打开中断:使用CAN_ITConfig函数打开所需的中断,例如CAN_IT_FMP0表示打开FIFO0的中断。这样可以在接收到消息时触发中断。 总体配置中需要注意的是保持tBS1 >= tBS2、tBS2 >= 1个CAN时钟周期和tBS2 >= 2tSJW。 以上是在代码中进行STM32CAN的配置的步骤。具体的代码示例可以参考引用中的代码。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [STM32F40x CAN控制器](https://blog.csdn.net/weixin_44502943/article/details/120514818)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [STM32之CAN---配置波特率](https://blog.csdn.net/piperzero/article/details/84355059)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值