eric2013 发表于 2015-9-27 11:17:34

STM32的CAN总线的标识符过滤器组使用注意事项------->重要

CAN总线的标识符过滤器很重要。
1.标识符过滤器是用于接收的,发送的时候无需设置过滤器,这点一定要整明白。
   根据发送端发送来的帧数据,通过标识符过滤器就可以设置仅接收需要接收的帧数据
   有效降低CPU多余的处理时间。

2什么是标识符?
    标识符主要包括如下,也可以简单的理解仅包含ID号,但是在这里下面这些都是要包含的。


比如:数据帧和遥控帧,标识符就包含在其中,所以发送端发帧数据给接收端后,接收端就可以通过
硬件标识符过滤器进行筛选,节省了CPU时间:




3.下面就是最重要的,STM32的CAN总线标识符滤波器组包含两种实现方法:
屏蔽位模式和标识符列表模式,这两种方式怎么理解呢,重点看下面的截图:


书面上解释屏蔽位模式和标识符列表模式的区别
屏蔽位模式
在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照
“必须匹配”或“不用关心”处理。
标识符列表模式
在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一
个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符
相同。
=========================================================
标识符的列表模式比较好理解,就是指的所有的过滤器寄存器位全部用于过滤,简单的说就是
发送端发送的标识符所有的位必须跟接收端的滤波器寄存器定义一样。有一个位定义不一样,拒收此消息。


比STM32F103有14个过滤器组,如果采用两个16位的过滤器形式,那么就可以固定识别出
14 * 4 = 56个不同的标识符,实际使用中也够用了。为什么是乘以4,注意看上面的截图,
4个16位过滤器--标识符列表
=========================================================
屏蔽位模式要稍麻烦一些,我们以2个16位过滤器---标识符屏蔽为例进行说明:


将过滤器寄存器分成两个部分,标识符寄存器和屏蔽位寄存器。
上面截图中ID部分就是标识符寄存器,屏蔽部分就是屏蔽位寄存器。
比如
ID    : 0xFED0;
屏蔽:0xFFE0;
那就是表示,接收端接受帧数据时,前11位的数值必须跟ID中定义的前11位一致,后面的5位数据忽略。
不管是什么值都可以。也即是说屏蔽位中的数值:
0: 不关心,该位不用于比较;
1: 必须匹配,到来的标识符位必须与滤波器对应的标识符寄存器位相一致。
基于此原因:
为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。
为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。

eric2013 发表于 2015-9-27 11:29:27

通过上面的说明可以发现,官方F103固件库中对于过滤器组中的ID和屏蔽位定义使用起来还是
要特别的注意,他不仅仅只是一个ID,这里的ID就是标识符,千万不要理解成仅包含ID号,而没有
IDE和RTR位。
=========================================================

/* 设置CAN滤波器0 */
    CAN_FilterInitStructure.CAN_FilterNumber = 0;                                       /* 滤波器序号,0-13,共14个滤波器 */
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;      /* 滤波器模式,设置ID掩码模式 */
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;               /* 32位滤波 */
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;                  
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;                  
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;               
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;               
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;      /* 滤波器绑定FIFO 0 */
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;                /* 使能滤波器 */
    CAN_FilterInit(&CAN_FilterInitStructure);

==============================================================================
CAN_FilterInit的源代码,重点看过滤器寄存器的设置:
/**
* @briefInitializes the CAN peripheral according to the specified
*         parameters in the CAN_FilterInitStruct.
* @paramCAN_FilterInitStruct: pointer to a CAN_FilterInitTypeDef
*                               structure that contains the configuration
*                               information.
* @retval None.
*/
void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct)
{
uint32_t filter_number_bit_pos = 0;
/* Check the parameters */
assert_param(IS_CAN_FILTER_NUMBER(CAN_FilterInitStruct->CAN_FilterNumber));
assert_param(IS_CAN_FILTER_MODE(CAN_FilterInitStruct->CAN_FilterMode));
assert_param(IS_CAN_FILTER_SCALE(CAN_FilterInitStruct->CAN_FilterScale));
assert_param(IS_CAN_FILTER_FIFO(CAN_FilterInitStruct->CAN_FilterFIFOAssignment));
assert_param(IS_FUNCTIONAL_STATE(CAN_FilterInitStruct->CAN_FilterActivation));

filter_number_bit_pos = ((uint32_t)1) << CAN_FilterInitStruct->CAN_FilterNumber;

/* Initialisation mode for the filter */
CAN1->FMR |= FMR_FINIT;

/* Filter Deactivation */
CAN1->FA1R &= ~(uint32_t)filter_number_bit_pos;

/* Filter Scale */
if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_16bit)
{
    /* 16-bit scale for the filter */
    CAN1->FS1R &= ~(uint32_t)filter_number_bit_pos;

    /* First 16-bit identifier and First 16-bit mask */
    /* Or First 16-bit identifier and Second 16-bit identifier */
    CAN1->sFilterRegister.FR1 =
    ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow) << 16) |
      (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow);

    /* Second 16-bit identifier and Second 16-bit mask */
    /* Or Third 16-bit identifier and Fourth 16-bit identifier */
    CAN1->sFilterRegister.FR2 =
    ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) |
      (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh);
}

if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit)
{
    /* 32-bit scale for the filter */
    CAN1->FS1R |= filter_number_bit_pos;
    /* 32-bit identifier or First 32-bit identifier */
    CAN1->sFilterRegister.FR1 =
    ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) << 16) |
      (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow);
    /* 32-bit mask or Second 32-bit identifier */
    CAN1->sFilterRegister.FR2 =
    ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) |
      (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow);
}

/* Filter Mode */
if (CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdMask)
{
    /*Id/Mask mode for the filter*/
    CAN1->FM1R &= ~(uint32_t)filter_number_bit_pos;
}
else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
{
    /*Identifier list mode for the filter*/
    CAN1->FM1R |= (uint32_t)filter_number_bit_pos;
}

/* Filter FIFO assignment */
if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO0)
{
    /* FIFO 0 assignation for the filter */
    CAN1->FFA1R &= ~(uint32_t)filter_number_bit_pos;
}

if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO1)
{
    /* FIFO 1 assignation for the filter */
    CAN1->FFA1R |= (uint32_t)filter_number_bit_pos;
}

/* Filter activation */
if (CAN_FilterInitStruct->CAN_FilterActivation == ENABLE)
{
    CAN1->FA1R |= filter_number_bit_pos;
}

/* Leave the initialisation mode for the filter */
CAN1->FMR &= ~FMR_FINIT;
}

eric2013 发表于 2015-9-27 11:32:08

过滤器寄存器的定义如下:

zhangjie2014 发表于 2016-10-28 10:40:28

Re:STM32的CAN总线的标识符过滤器组使用注意事项------->重要

有没有写好的,can过滤的函数,我想过滤任意多个can id,但总是写不好

伊森亨特 发表于 2021-4-29 13:44:08

有两个问题,初始化结构体里的过滤器号uint8_t CAN_FilterNumber;          /*!< Specifies the filter which will be initialized. It ranges from 0 to 13. */
指的是过滤器组,还是过滤器编号?看手册里的图有两个不一样的号
如果用can2的话,can2的过滤器组14相当于can1的 第0个过滤器组吗?
过滤器组号是固定的吗?,比如我用CAN1,32位掩码模式,按照图所示,就只能选择过滤器组1、13、12?还是可以任意选?谢谢。
http://tiebapic.baidu.com/forum/w%3D580/sign=52bb637d4dafa40f3cc6ced59b65038c/75fbb2fb43166d226e01c1db512309f79052d20f.jpg

eric2013 发表于 2021-4-30 09:35:50

伊森亨特 发表于 2021-4-29 13:44
有两个问题,初始化结构体里的过滤器号uint8_t CAN_FilterNumber;          /*!< Specifies the filter whi ...
1、使用的那个过滤器
2、正常情况下,CAN1和CAN2可以任意使用其中的过滤器。

伊森亨特 发表于 2021-4-30 12:10:19

eric2013 发表于 2021-4-30 09:35
1、使用的那个过滤器
2、正常情况下,CAN1和CAN2可以任意使用其中的过滤器。

回复的时候不能插入图片,手册里有一张图,没看明白。

eric2013 发表于 2021-5-1 08:12:00

伊森亨特 发表于 2021-4-30 12:10
回复的时候不能插入图片,手册里有一张图,没看明白。

进入高级编辑,点击那个图片按钮加载。

2522428130 发表于 2021-12-18 11:24:58

can怎么发送浮点数呀,比如125.3362

eric2013 发表于 2021-12-18 11:29:42

2522428130 发表于 2021-12-18 11:24
can怎么发送浮点数呀,比如125.3362

实战技能分享,各种数据类型的SPI, UART, I2C,FDCAN等方式的通信传输以及存储到EEPROM, Flash等设备的简易实现方法
https://www.armbbs.cn/forum.php?mod=viewthread&tid=109659&fromuid=58
(出处: 硬汉嵌入式论坛)
页: [1]
查看完整版本: STM32的CAN总线的标识符过滤器组使用注意事项------->重要