一、前言

学习了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

STM32之CAN通讯接收过滤器过滤分析的更多相关文章

  1. STM32之CAN ---CAN ID过滤器分析

      1 前言 在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的.因此,发送者以广播的形式把报文发送给所有的接收者.节点在接收报文时,根据标识符(CAN ID)的值决定软件是否需要该 ...

  2. STM32之串口DMA接收不定长数据

    STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...

  3. stm32学习笔记之GPIO功能框图分析

    GPIO 是通用输入输出端口的简称,简单来说就是STM32 可控制的引脚,STM32 芯片的GPIO 引脚与外部设备连接起来,从而实现与外部通讯.控制以及数据采集的功能.STM32 芯片的GPIO被分 ...

  4. STM32使用以下规则对过滤器编号:

    STM32使用以下规则对过滤器编号:(1) FIFO_0和 FIFO_1的过滤器分别独立编号,均从0开始按顺序编号.(2) 所有关联同一个 FIFO 的过滤器,不管有没有被激活,均统一进行编号.(3) ...

  5. STM32和STR71X移植uCos-II操作系统比较分析

    STM32和STR71X移植uCos-II操作系统比较分析 ——ARM7 TDMI和ARMv7-M Cortex-M3 的异同 STM32F103ZE,大容量,ARMv7-M,Cortex-M3系列, ...

  6. SuperSocket接收过滤器工厂(ReceiveFilterFactory)

    接收过滤器工厂(ReceiveFilterFactory)用于为每个会话创建接收过滤器. 定义一个过滤器工厂(ReceiveFilterFactory)类型, 你必须实现接口 IReceiveFilt ...

  7. supersockets接收过滤器(ReceiveFilter)

    接收过滤器(ReceiveFilter)用于将接收到的二进制数据转化成请求实例(RequestInfo). 实现一个接收过滤器(ReceiveFilter), 你需要实现接口 IReceiveFilt ...

  8. SpringBoot过滤器过滤get及post请求中的XSS和SQL注入

    1.创建XssAndSqlHttpServletRequestWrapper包装器,这是实现XSS过滤的关键,在其内重写了getParameter,getParameterValues,getHead ...

  9. Java 远程通讯技术及原理分析

    在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在Java领域中有很多可实现远程通讯的技术,例如:RMI.MINA.ESB.Burlap.Hessian.SOAP.EJB和JMS等,这些 ...

随机推荐

  1. java引用被设置为null的疑惑

    a=null; public class C { protected A webDigester = new A(" first one "); public void test( ...

  2. Sub Thread to update main Thread (UI) 2

    Sub Thread to update main Thread (UI)  2 Handler.post(somethread); Handler.sendMessage("Msg&quo ...

  3. vue中剖析中的一些方法

    1 判断属性 71 -81 var hasOwnProperty = Object.prototype.hasOwnProperty; /** * Check whether the object h ...

  4. css历史

    CSS目前最新版本为CSS3,是能够真正做到网页表现与内容分离的一种样式设计语言.相对于传统HTML的表现而言,CSS能够对网页中的对象的位置排版进行像素级的精确控制,支持几乎所有的字体字号样式,拥有 ...

  5. Codefroces B. Hamming Distance Sum

    Genos needs your help. He was asked to solve the following programming problem by Saitama: The lengt ...

  6. codefroces 650A. Watchmen

    A. Watchmen time limit per test 3 seconds memory limit per test 256 megabytes input standard input o ...

  7. DataTable中Compute计算函数

    DataTable dt = new DataTable(); //嵌套的三元运算 牛叉到五体投地 object obj = dt.Compute("iif(1000=5,1000,iif( ...

  8. How Javascript works (Javascript工作原理) (十三) CSS 和 JS 动画底层原理及如何优化其性能

    个人总结:读完这篇文章需要20分钟. 这是 JavaScript 工作原理的第十三章. 概述 正如你所知,动画在创建令人叹服的网络应用中扮演着一个关键角色.由于用户越来越注重用户体验,商户开始意识到完 ...

  9. 便捷编程-Xcode常用第三方插件 (随时更新)

    Xcode工具插件 1.XAlign 让Xcode编辑器中的代码以多种方式瞬间对齐 地址:https://github.com/qfish/XAlign 2.VVDocumenter-Xcode 在X ...

  10. Vijos——T1626 爱在心中

    https://vijos.org/p/1626 描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our H ...