STM32F103的CAN通讯接收过滤器过滤分析

前言
STM32 的标识符过滤是一个比较复杂的东东,它的存在减少了 CPU 处理 CAN 通信的开销。STM32 的过滤器组最多有 28 个(互联型),但是 STM32F103ZET6 只有 14 个(增强型),每个滤波器组 x 由 2 个 32 为寄存器, CAN_FxR1 和 CAN_FxR2 组成。学习了CAN通讯,底层的东东CAN控制器已经帮你处理完成,也就是CAN通讯协议已经做好,你按协议格式往对应的位扔数据发送就好,所以使用CAN通讯,我们只需要去关心制定发送的数据间的协议,也就是给每个数据加上有标识符的协议。
CAN过滤器的分析 因为STM32在非互联网型产品中CAN控制器提供了14个位宽可变、可配置的过滤器组(13~0),每个过滤器组x由2个32位寄存器,CAN_FxR0和CAN_FxR1组成,而1个过滤器组的位宽设置可以分成四种工作模式,工作模式取决于两个寄存器FBMx,FSCx的设置,如下图所示:
看到过滤器的四种工作模式,工作模式中标识符屏蔽和列表模式,如何去理解,举个例子,假如我们发送的标识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

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位

【STM32F103的CAN通讯接收过滤器过滤分析】程序配置如下
CAN_RxFilerconfig(0,CANRX32IDMASK); //32位标识符屏蔽模式 void CAN_RxFilerconfig(u8 FilterNum,u8 FilterMode) { CAN_FilterInitTypeDefCAN_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_FilterInitTypeDefCAN_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_FilterInitTypeDefCAN_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_FilterInitTypeDefCAN_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); //滤波器初始化 }

    推荐阅读