STM32之CAN通訊接收過濾器過濾分析


一、前言

學習了CAN通訊,底層的東東CAN控制器已經幫你處理完成,也就是CAN通訊協議已經做好,你按協議格式往對應的位扔數據發送就好,所以使用CAN通訊,我們只需要去關心制定發送的數據間的協議,也就是給每個數據加上有標識符的協議。如下圖所示的CAN通訊發送數據的數據幀,Arbitration Field即是具有優先級的標識ID,Data Field即是要發送的數據,Arbitration FieldData Field就是我們關注的重點,因為CAN通訊協議里邊這些發送出來的標識ID並不代表節點的地址,數據是以廣播形式發送出來,每個節點都是可以接收,至於接收到的數據是不是想要的?就需要對這些標識的ID進行篩選和過濾,再去提取數據。

二、CAN 通訊接收過濾器的分析

首先我們看下要配置發送數據的結構,如下所示。我們發送的Arbitration Field標識即是CanTxMsg.StdId,接收則會先過濾標識ID過濾處理后,再去提取發送的的CanTxMsg.Data。如果不是設定的標識ID,接收則不會去讀取數據,到底接收方是怎樣去過濾處理的。

typedef struct
{
  uint32_t StdId;    //11位 標准幀ID即Arbitration Field
  uint32_t ExtId;    //29位 擴展幀ID
  uint8_t IDE;       //1位  O:標准幀,1:擴展幀
  uint8_t RTR;       //1位  0:數據幀,1:遠程幀
  uint8_t DLC;       //4位  發送的數據的長度
  uint8_t Data[8];   //8位  發送的數據即Data Field
} CanTxMsg;

因為STM32在非互聯網型產品中CAN控制器提供了14個位寬可變、可配置的過濾器組(13~0),每個過濾器組x由2個32位寄存器,CAN_FxR0和CAN_FxR1組成,而1個過濾器組的位寬設置可以分成四種工作模式,工作模式取決於兩個寄存器FBMxFSCx的設置,如下圖所示:

看到過濾器的四種工作模式,工作模式中標識符屏蔽列表模式,如何去理解,舉個例子,假如我們發送的標識IDCanTxMsg.StdId是0x000~0x00f,接收過濾先用標識符屏蔽模式來過濾標識的ID,如下所示:

 ID  :     000 0000 0000 xxxx              
 屏蔽 :     111 1111 1111 0000 
  

x代表0或者1都是可以通過,0000到1111的任意組合,這樣就可以過濾出0x000~0x00f的數據的,所以屏蔽的意思就是讓某個范圍的標識符ID可以通過,目的是過濾出一組標志符。那么如果想過濾出一個數據0x003,用標識符屏蔽模式實現方式如下,

 ID  :     000 0000 0000 0011              
 屏蔽 :     111 1111 1111 1111 
  

如果接收過濾使用標識符列表模式來過濾標識ID,如下所示,

 ID  :    000 0000 0001 
 ID  :    000 0000 0010

這種模式只能過濾出兩個ID,即0x001,0x002,所以列表的意思就是要去羅列想要的標識ID后跟發送過來的CanTxMsg.StdId進行校對,如果是則去接收數據,不是則過濾掉數據,標識符列表模式目的是過濾出一個標志符ID

三、CAN 接收過濾器的四種工作模式的程序配置

1、32位標識符屏蔽模式


假如要發送的標示符IDCanTxMsg.StdId范圍為0x010~0x01f

ID      : 0000 001x xxx0 0000 0000 0000 0000 0000  //分別對應CAN_FxR1高16位、CAN_FxR1低16位
屏蔽    : 1111 1110 0001 1111 1111 1111 1111 1111  //分別對應CAN_FxR2高16位、CAN_FxR2低16位

程序配置如下:

CAN_RxFilerconfig(0,CANRX32IDMASK);                                      //32位標識符屏蔽模式
void CAN_RxFilerconfig(u8 FilterNum,u8 FilterMode)
{
  CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
   
   CAN_FilterInitStructure.CAN_FilterNumber=FilterNum;	               //過濾器號0~13可選
   if(FilterMode==CANRX32IDMASK)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	   //標識符屏蔽模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;    //32位寬 
   }
   else if(FilterMode==CANRX32IDLIST)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 	   //標識符列表模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;    //32位寬 
   }
   else if(FilterMode==CANRX16IDMASK)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	   //標識符屏蔽模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;    //16位寬 
   }
   else if(FilterMode==CANRX16IDLIST)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 	   //標識符列表模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;    //16位寬
   }
    //標識符寄存器FxR1
   CAN_FilterInitStructure.CAN_FilterIdHigh=0x010<<5;                  //32位ID,高16位
   CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;                     //低16位
   //屏蔽寄存器FxR2
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xfe1f;                //32位MASK,高16位
   CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xffff;                 //低16位
	
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;  //過濾器0關聯到FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;                //激活過濾器0

   CAN_FilterInit(&CAN_FilterInitStructure);			               //濾波器初始化
} 

2、32位標識符列表模式


假如要發送的標示符IDCanTxMsg.StdId為0x011和0x012兩個。

ID      : 0000 0010 0010 0000 0000 0000 0000 0000  //分別對應CAN_FxR1高16位、CAN_FxR1低16位  //0x011
屏蔽    : 0000 0010 0100 1111 1111 1111 1111 1111  //分別對應CAN_FxR2高16位、CAN_FxR2低16位  //0x012

程序配置如下:

CAN_RxFilerconfig(0,CANRX32IDLIST);                                      //32位標識符列表模式
void CAN_RxFilerconfig(u8 FilterNum,u8 FilterMode)
{
  CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
   
   CAN_FilterInitStructure.CAN_FilterNumber=FilterNum;	               //過濾器號0~13可選
   if(FilterMode==CANRX32IDMASK)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	   //標識符屏蔽模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;    //32位寬 
   }
   else if(FilterMode==CANRX32IDLIST)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 	   //標識符列表模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;    //32位寬 
   }
   else if(FilterMode==CANRX16IDMASK)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	   //標識符屏蔽模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;    //16位寬 
   }
   else if(FilterMode==CANRX16IDLIST)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 	   //標識符列表模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;    //16位寬
   }
    //標識符寄存器FxR1
   CAN_FilterInitStructure.CAN_FilterIdHigh=0x011<<5;                  //32位ID,高16位
   CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;                     //低16位
   //屏蔽寄存器FxR2
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x012<<5;              //32位MASK,高16位
   CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xffff;                 //低16位
	
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;  //過濾器0關聯到FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;                //激活過濾器0

   CAN_FilterInit(&CAN_FilterInitStructure);			               //濾波器初始化
} 

3、16位標識符屏蔽模式


假如要發送的標示符IDCanTxMsg.StdId范圍為0x0100x01f,0x0000x00f。

ID      : 0000 001x xxx0 0000  //分別對應CAN_FxR1低16位  CAN_FilterIdLow
屏蔽    : 1111 1110 0001 1111  //分別對應CAN_FxR1高16位  CAN_FilterIdHigh

ID      : 0000 000x xxx0 0000  //分別對應CAN_FxR2低16位  CAN_FilterMaskIdLow
屏蔽    : 1111 1110 0001 1111  //分別對應CAN_FxR2高16位  CAN_FilterMaskIdHigh

程序配置如下:

CAN_RxFilerconfig(0,CANRX16IDMASK);                                      //16位標識符屏蔽模式
void CAN_RxFilerconfig(u8 FilterNum,u8 FilterMode)
{
  CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
   
   CAN_FilterInitStructure.CAN_FilterNumber=FilterNum;	               //過濾器號0~13可選
   if(FilterMode==CANRX32IDMASK)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	   //標識符屏蔽模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;    //32位寬 
   }
   else if(FilterMode==CANRX32IDLIST)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 	   //標識符列表模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;    //32位寬 
   }
   else if(FilterMode==CANRX16IDMASK)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	   //標識符屏蔽模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;    //16位寬 
   }
   else if(FilterMode==CANRX16IDLIST)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 	   //標識符列表模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;    //16位寬
   }
    //標識符寄存器FxR1
   CAN_FilterInitStructure.CAN_FilterIdHigh=0xfe1f;                    //32位ID,高16位
   CAN_FilterInitStructure.CAN_FilterIdLow=0x010<<5;                   //低16位
   //屏蔽寄存器FxR2
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xfe1f;                //32位MASK,高16位
   CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x000<<5;               //低16位
	
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;  //過濾器0關聯到FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;                //激活過濾器0

   CAN_FilterInit(&CAN_FilterInitStructure);			               //濾波器初始化
} 

4、16位標識符列表模式


假如要發送的標示符IDCanTxMsg.StdId 有0x010,0x01f,0x001,0x00f四個。

ID      : 0000 0010 0000 0000  //分別對應CAN_FxR1低16位  CAN_FilterIdLow  //0x010
ID      : 0000 0011 1110 0000  //分別對應CAN_FxR1高16位  CAN_FilterIdHigh //0x01f

ID      : 0000 0000 0010 0000  //分別對應CAN_FxR2低16位  CAN_FilterMaskIdLow //0x001
ID      : 0000 0001 1110 0000  //分別對應CAN_FxR2高16位  CAN_FilterMaskIdHigh //0x00f

程序配置如下:

CAN_RxFilerconfig(0,CANRX16IDLIST);                                      //16位標識符列表模式
void CAN_RxFilerconfig(u8 FilterNum,u8 FilterMode)
{
  CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
   
   CAN_FilterInitStructure.CAN_FilterNumber=FilterNum;	               //過濾器號0~13可選
   if(FilterMode==CANRX32IDMASK)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	   //標識符屏蔽模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;    //32位寬 
   }
   else if(FilterMode==CANRX32IDLIST)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 	   //標識符列表模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;    //32位寬 
   }
   else if(FilterMode==CANRX16IDMASK)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	   //標識符屏蔽模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;    //16位寬 
   }
   else if(FilterMode==CANRX16IDLIST)
   {
     CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; 	   //標識符列表模式
     CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;    //16位寬
   }
    //標識符寄存器FxR1
   CAN_FilterInitStructure.CAN_FilterIdHigh=0x01f<<5;                  //32位ID,高16位
   CAN_FilterInitStructure.CAN_FilterIdLow=0x010<<5;                   //低16位
   //屏蔽寄存器FxR2
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x00f<<5;              //32位MASK,高16位
   CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x001<<5;               //低16位
	
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;  //過濾器0關聯到FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;                //激活過濾器0

   CAN_FilterInit(&CAN_FilterInitStructure);			               //濾波器初始化
} 

by 羊羊得億
2017-02-24 ShenZhen


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM