STM32 CAN 过滤器、滤波屏蔽器配置总结

本文详细介绍了STM32微控制器中CAN模块的过滤器组及过滤器配置原理,包括标识符列表模式和屏蔽位模式的工作方式。此外,还提供了具体的初始化配置代码示例,帮助读者更好地理解如何实现对不同类型的CAN帧进行过滤。

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

一、过滤组、过滤器编号介绍

    在STM32互联型产品中,CAN1CAN2分享28个过滤器组,其它STM32F103xx系列产品中有14个过滤器组,用以对接收到的帧进行过滤。

1、过滤器组

    每组过滤器包括了2个可配置的32位寄存器:CAN_FxR0CAN_FxR1。这些过滤器相当于关卡,每当收到一条报文时,CAN要先将收到的报文从这些过滤器上""一下,能通过的报文是有效报文,收进相关联FIFOFIFO1FIFO2),不能通过的是无效报文(不是发给""的报文),直接丢弃。 

  (标准CAN的标志位长度是11位。扩展格式CAN的标志位长度是29CAN2.0A协议规定CAN控制器必须有一个11位的标识符。CAN2.0B协议中规定CAN控制器的标示符长度可以是11位或29位。STM32同时支持CAN2.0A/CAN2.0B协议。)    

每组过滤器组有两种工作模式:标识符列表模式标识符屏蔽位模式

标识符屏蔽位模式:

    可过滤出一组标识符。此时,这样CAN_FxR0中保存的就是标识符匹配值,CAN_FxR1中保存的是屏蔽码,即CAN_FxR1中如果某一位为1,则CAN_FxR0中相应的位必须与收到的帧的标志符中的相应位吻合才能通过过滤器;CAN_FxR1中为0的位表示CAN_FxR0中的相应位可不必与收到的帧进行匹配。

标识符列表模式:

    可过滤出一个标识。此时CAN_FxR0CAN_FxR1中的都是要匹配的标识符,收到的帧的标识符必须与其中的一个吻合才能通过过滤。注意:CAN_FilterIdHigh是指高16位CAN_FilterIdLow是低16位应该将需要得到的帧的和过滤器的设置值左对齐起。

    所有的过滤器是并联的,即一个报文只要通过了一个过滤器,就是算是有效的。 

    按工作模式和宽度,一个过滤器组可以变成以下几中形式之一:

        (1) 132位的屏蔽位模式的过滤器。

        (2) 232位的列表模式的过滤器。

        (3) 216位的屏蔽位模式的过滤器。

        (4) 416位的列表模式的过滤器。

    每组过滤器组有两个32位的寄存器用于存储过滤用的"标准值",分别是FxR1FxR2

32位的屏蔽位模式下:    1个过滤器。

    FxR1用于指定这些位的标准值,FxR2用于指定需要关心哪些位。

32位的列表模式下:     2个过滤器。

    FxR1指定过滤器0的标准值,FxR2指定过滤器1的标准值。

16位的屏蔽位模式下:    2个过滤器。

    FxR1配置过滤器0,其中,[31-16]位指定要关心的位,[15-0]位指定这些位的标准值。

    FxR2配置过滤器1,其中,[31-16]位指定要关心的位,[15-0]位指定这些位的标准值。

16位的列表模式下:     4个过滤器。

    FxR1[15-0]位配置过滤器0FxR1[31-16]位配置过滤器1

    FxR2[15-0]位配置过滤器2FxR2[31-16]位配置过滤器3

STM32CAN有两个FIFO,分别是FIFO0FIFO1。为了便于区分,下面FIFO0写作FIFO_0FIFO1写作FIFO_1

每组过滤器组必须关联且只能关联一个FIFO。复位默认都关联到FIFO_0

    所谓关联是指假如收到的报文从某个过滤器通过了,那么该报文会被存到该过滤器相连的FIFO

从另一方面来说,每个FIFO都关联了一串的过滤器组,两个FIFO刚好瓜分了所有的过滤器组。

    每当收到一个报文,CAN就将这个报文先与FIFO_0关联的过滤器比较,如果被匹配,就将此报文放入FIFO_0中。如果不匹配,再将报文与FIFO_1关联的过滤器比较,如果被匹配,该报文就放入FIFO_1中。如果还是不匹配,此报文就被丢弃。

    每个FIFO的所有过滤器都是并联的,只要通过了其中任何一个过滤器,该报文就有效。

如果一个报文既符合FIFO_0的规定,又符合FIFO_1的规定,显然,根据操作顺序,它只会放到FIFO_0中。

每个FIFO中只有激活了的过滤器才起作用,换句话说,如果一个FIFO20个过滤器,但是只激话了5个,那么比较报文时,只拿这5个过滤器作比较。

    一般要用到某个过滤器时,在初始化阶段就直接将它激活。

    需要注意的是,每个FIFO必须至少激活一个过滤器,它才有可能收到报文。如果一个过滤器都没有激活,那么是所有报文都报废的。

一般的,如果不想用复杂的过滤功能,FIFO可以只激活一组过滤器组,且将它设置成32位的屏蔽位模式,两个标准值寄存器(FxR1FxR2)都设置成0。这样所有报文均能通过。

2、过滤器编号

过滤器编号用于加速CPU对收到报文的处理。

收到一个有效报文时, CAN会将收到的报文 以及它所通过的过滤器编号, 一起存入接收邮箱中。CPU在处理时,可以根据过滤器编号,快速的知道该报文的用途,从而作出相应处理。

不用过滤器编号其实也是可以的, 这时候CPU就要分析所收报文的标识符, 从而知道报文的用途。由于标识符所含的信息较多,处理起来就慢一点了。会消耗CPU资源。

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

(1) FIFO_0FIFO_1的过滤器分别独立编号,均从0开始按顺序编号。

(2) 所有关联同一个FIFO的过滤器,不管有没有被激活,均统一进行编号。

(3) 编号从0开始,按过滤器组的编号从小到大,按顺序排列。

(4) 在同一过滤器组内,按寄存器从小到大编号。FxR1配置的过滤器编号小,FxR2配置的过滤器编号大。

(5) 同一个寄存器内,按位序从小到大编号。[15-0]位配置的过滤器编号小,[31-16]位配置的过滤器编号大。

(6) 过滤器编号是弹性的。 当更改了设置时,每个过滤器的编号都会改变。

 但是在设置不变的情况下,各个过滤器的编号是相对稳定的。

这样,每个过滤器在自己在FIFO中都有编号。

FIFO_0中,编号从0 -- (M-1) 其中M为它的过滤器总数。

FIFO_1中,编号从0 -- (N-1),,其中N为它的过滤器总数。


一个FIFO如果有很多的过滤器,,可能会有一条报文, 在几个过滤器上均能通过,这时候,,这条报文算是从哪儿过来的呢?STM32在使用过滤器时,按以下顺序进行过滤:

(1) 位宽为32位的过滤器,优先级高于位宽为16位的过滤器。

(2) 对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式。

(3) 位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高。

按这样的顺序,报文能通过的第一个过滤器,就是该报文的过滤器编号,被存入接收邮箱中。
二、初始化配置代码
u32  slave_id = 0x11 ;
/*CAN1配置函数*/ 
void CAN_Configuration(void)
{
 CAN_InitTypeDef        CAN_InitStructure;
    CAN_FilterInitTypeDef  CAN_FilterInitStructure;
    // CAN register init 
    CAN_DeInit(CAN1);
    CAN_StructInit(&CAN_InitStructure);
    // CAN cell init 
    CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式
    CAN_InitStructure.CAN_ABOM=DISABLE;
    CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过清除sleep位来唤醒
    CAN_InitStructure.CAN_NART=ENABLE;//ENABLE;报文自动重传
    CAN_InitStructure.CAN_RFLM=DISABLE;//接收溢出时,FIFO未锁定
    CAN_InitStructure.CAN_TXFP=DISABLE;//发送的优先级由标示符的大小决定
    CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;//正常模式下
    //设置can通讯波特率为50Kbps
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
    CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
    CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
    CAN_InitStructure.CAN_Prescaler=45;
    CAN_Init(CAN1,&CAN_InitStructure);
    // CAN filter init 
    CAN_FilterInitStructure.CAN_FilterNumber=0;     //使用0号过滤器组
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;   //屏蔽位标识符模式
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;  // 1个32bit的过滤器:即过滤器编号为0-->RxMessage.FMI = 0
    CAN_FilterInitStructure.CAN_FilterIdHigh   = (((u32)slave_id<<21)&0xffff0000)>>16;
    CAN_FilterInitStructure.CAN_FilterIdLow   = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;   //完全匹配
    CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;   //完全匹配
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;   //使用FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;   //使能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure);
    CAN_ITConfig(CAN1,CAN_IT_FMP0|CAN_IT_EPV, ENABLE);
} 
/*CAN 发送函数*/
unsigned char CAN1_SendData(void)
{
 CanTxMsg TxMessage;
 TxMessage.StdId=0x11;      //标准标识符 
 TxMessage.RTR=CAN_RTR_DATA; //数据帧
 TxMessage.IDE=CAN_ID_STD; //标准帧
 TxMessage.DLC=2;          //数据长度 2
 TxMessage.Data[0]=0xCA;     //发送的数据
 TxMessage.Data[1]=0xFE;
 CAN_Transmit(CAN1,&TxMessage); //发送数据
}
/*中断服务函数*/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
 CanRxMsg RxMessage;
 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);    
 If(RxMessage.FMI == 0){   //过滤器编号为0
       /*接收数据处理*/
 }
}



三、滤波器的详细设置

1、对扩展数据帧进行过滤:(只接收扩展数据帧)

     CAN_FilterInitStructure.CAN_FilterIdHigh   =(((u32)slave_id<<3)&0xFFFF0000)>>16;

     CAN_FilterInitStructure.CAN_FilterIdLo=(((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;

     CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;

     CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;

(注:标准帧数据帧、标准远程帧和扩展远程帧均被过滤)

2、对扩展远程帧过滤:(只接收扩展远程帧)

     CAN_FilterInitStructure.CAN_FilterIdHigh   = (((u32)slave_id<<3)&0xFFFF0000)>>16;

     CAN_FilterInitStructure.CAN_FilterIdLow  = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_REMOTE)&0xFFFF;

     CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;

     CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;

3、对标准远程帧过滤:(只接收标准远程帧)

     CAN_FilterInitStructure.CAN_FilterIdHigh   =(((u32)slave_id<<21)&0xffff0000)>>16;

     CAN_FilterInitStructure.CAN_FilterIdLow  = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xffff;

      CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;

     CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;

4、对标准数据帧过滤:(只接收标准数据帧)

     CAN_FilterInitStructure.CAN_FilterIdHigh   =(((u32)slave_id<<21)&0xffff0000)>>16;

     CAN_FilterInitStructure.CAN_FilterIdLow  = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;

     CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;

     CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;

5、对扩展帧进行过滤:(扩展帧不会被过滤掉)

     CAN_FilterInitStructure.CAN_FilterIdHigh   =(((u32)slave_id<<3)&0xFFFF0000)>>16;

     CAN_FilterInitStructure.CAN_FilterIdLow  = (((u32)slave_id<<3)|CAN_ID_EXT)&0xFFFF;

     CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;

      CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFC;

6、对标准帧进行过滤:(标准帧不会被过滤掉)

     CAN_FilterInitStructure.CAN_FilterIdHigh   =(((u32)slave_id<<21)&0xffff0000)>>16;

     CAN_FilterInitStructure.CAN_FilterIdLow  = (((u32)slave_id<<21)|CAN_ID_STD)&0xffff;

      CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;

     CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFC;

注:slave_id为要过滤的id号。
其中我们可以开启can错误中断,设置响应的标志位,在大循环里面不断的检测是否错误,一旦错误就重新配置can,这样有效地保证了CAN的正常通信。具体操作代码如下:
 /*CAN错误中断服务函数*/、
void CAN1_SCE_IRQHandler(void)
{
 CANWorkFlag &= ~CAN_RESET_COMPLETE;
}
/*CAN错误处理函数*/
/************************************************************************
 *函数名称:  CanErrorProcess
 *功能:      CAN故障,错误处理
 *参数说明:  无
 ************************************************************************/
void CanErrorProcess(void)
{
 if ((CANWorkFlag & CAN_RESET_COMPLETE) == 0)
 {
  CAN1_Configuration();
  CANWorkFlag |= CAN_RESET_COMPLETE;
 }
}
/*错误标志的定义*/
extern uint8 CANWorkFlag;
/************************************************************************
 *  CANWorkFlag 标志位掩码定义
 ************************************************************************/
#define       CAN_INIT_COMPLETE            0x80   //CAN初始化完成标志
//#define       CAN_BUS_ERROR                0x40   //CAN总线错误标志
#define       CAN_RESET_COMPLETE           0x40   //CAN控制器复位完成标志
#define       CAN2_INIT_COMPLETE            0x20   //CAN2初始化完成标志
//#define       CAN_BUS_ERROR                0x40   //CAN总线错误标志
#define       CAN2_RESET_COMPLETE           0x10   //CAN2控制器复位完成标志




内容概要:本文档详细介绍了在三台CentOS 7服务器(IP地址分别为192.168.0.157、192.168.0.158和192.168.0.159)上安装和配置Hadoop、Flink及其他大数据组件(如Hive、MySQL、Sqoop、Kafka、Zookeeper、HBase、Spark、Scala)的具体步骤。首先,文档说明了环境准备,包括配置主机名映射、SSH免密登录、JDK安装等。接着,详细描述了Hadoop集群的安装配置,包括SSH免密登录、JDK配置、Hadoop环境变量设置、HDFS和YARN配置文件修改、集群启动与测试。随后,依次介绍了MySQL、Hive、Sqoop、Kafka、Zookeeper、HBase、Spark、Scala和Flink的安装配置过程,包括解压、环境变量配置、配置文件修改、服务启动等关键步骤。最后,文档提供了每个组件的基本测试方法,确保安装成功。 适合人群:具备一定Linux基础和大数据组件基础知识的运维人员、大数据开发工程师以及系统管理员。 使用场景及目标:①为大数据平台建提供详细的安装指南,确保各组件能够顺利安装和配置;②帮助技术人员快速掌握Hadoop、Flink等大数据组件的安装与配置,提升工作效率;③适用于企业级大数据平台的建与维护,确保集群稳定运行。 其他说明:本文档不仅提供了详细的安装步骤,还涵盖了常见的配置项解释和故障排查建议。建议读者在安装过程中仔细阅读每一步骤,并根据实际情况调整配置参数。此外,文档中的命令和配置文件路径均为示例,实际操作时需根据具体环境进行适当修改。
在无线通信领域,天线阵列设计对于信号传播方向和覆盖范围的优化至关重要。本题要求设计一个广播电台的天线布局,形成特定的水平面波瓣图,即在东北方向实现最大辐射强度,在正东到正北的90°范围内辐射衰减最小且无零点;而在其余270°范围内允许出现零点,且正西和西南方向必须为零。为此,设计了一个由4个铅垂铁塔组成的阵列,各铁塔上的电流幅度相等,相位关系可自由调整,几何布置和间距不受限制。设计过程如下: 第一步:构建初级波瓣图 选取南北方向上的两个点源,间距为0.2λ(λ为电磁波波长),形成一个端射阵。通过调整相位差,使正南方向的辐射为零,计算得到初始相位差δ=252°。为了满足西南方向零辐射的要求,整体相位再偏移45°,得到初级波瓣图的表达式为E1=cos(36°cos(φ+45°)+126°)。 第二步:构建次级波瓣图 再选取一个点源位于正北方向,另一个点源位于西南方向,间距为0.4λ。调整相位差使西南方向的辐射为零,计算得到相位差δ=280°。同样整体偏移45°,得到次级波瓣图的表达式为E2=cos(72°cos(φ+45°)+140°)。 最终组合: 将初级波瓣图E1和次级波瓣图E2相乘,得到总阵的波瓣图E=E1×E2=cos(36°cos(φ+45°)+126°)×cos(72°cos(φ+45°)+140°)。通过编程实现计算并绘制波瓣图,可以看到三个阶段的波瓣图分别对应初级波瓣、次级波瓣和总波瓣,最终得到满足广播电台需求的总波瓣图。实验代码使用MATLAB编写,利用polar函数在极坐标下绘制波瓣图,并通过subplot分块显示不同阶段的波瓣图。这种设计方法体现了天线阵列设计的基本原理,即通过调整天线间的相对位置和相位关系,控制电磁波的辐射方向和强度,以满足特定的覆盖需求。这种设计在雷达、卫星通信和移动通信基站等无线通信系统中得到了广泛应用。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值