OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 19736|回复: 27

CAN总线过滤器学习很好的一点资料

[复制链接]

93

主题

746

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1850
金钱
1850
注册时间
2012-9-16
在线时间
286 小时
发表于 2013-8-28 09:38:31 | 显示全部楼层 |阅读模式
STM32普通型芯片的 CAN 有14组过滤器组(互联型有28组过滤器组) ,用以对接收到的
帧进行过滤。每组过滤器包括了2个可配置的32位寄存器:CAN_FxR0和 CAN_FxR1。
对于过滤器组, 可以将其配置成屏蔽位模式, 这样 CAN_FxR0中保存的就是标识符匹配值,
CAN_FxR1中保存的是屏蔽码,即 CAN_FxR1中如果某一位为1,则 CAN_FxR0中相应
的位必须与收到的帧的标志符中的相应位吻合才能通过过滤器; CAN_FxR1中为0的位表
示 CAN_FxR0中的相应位可不必与收到的帧进行匹配。 过滤器组还可以被配置成标识符列
表模式,此时 CAN_FxR0和 CAN_FxR1中的都是要匹配的标识符,收到的帧的标识符必
须与其中的一个吻合才能通过过滤。
注意:CAN_FilterIdHigh 是指高16位 CAN_FilterIdLow 是低16位应该将需要得到的帧
的和过滤器的设置值左对齐起。
一般我们用的都是普通型的,所以在本文中可以说 STM32有14组过滤器组。
根据配置,每1组过滤器组可以有1个,2个或4个过滤器。
这些过滤器相当于关卡,每当收到一条报文时,CAN 要先将收到的报文从这些过滤器上"
过"一下,能通过的报文是有效报文,收进 FIFO,不能通过的是无效报文(不是发给"我"
的报文),直接丢弃。
所有的过滤器是并联的,即一个报文只要通过了一个过滤器,就是算是有效的。
每组过滤器组有两种工作模式:标识符列表模式和标识符屏蔽位模式。
在标识符列表模式下,收到报文的标识符必须与过滤器的值完全相等才能通过。
在标识符屏蔽位模式下,可以指定标识符的哪些位为何值时就算通过。这其实就是限定了
处于某一范围的标识符能够通过。
在一组过滤器中,整组的过滤器都使用同一种工作模式。
另外,每组过滤器中的过滤器宽度是可变的,可以是32位或16位。
按工作模式和宽度,一个过滤器组可以变成以下几中形式之一:
(1) 1个32位的屏蔽位模式的过滤器。
(2) 2个32位的列表模式的过滤器。
(3) 2个16位的屏蔽位模式的过滤器。
(4) 4个16位的列表模式的过滤器。
所有的过滤器是并联的,即一个报文只要通过了一个过滤器,就是算是有效的。
每组过滤器组有两个32位的寄存器用于存储过滤用的"标准值",分别是 FxR1,FxR2。
在32位的屏蔽位模式下:
有1个过滤器。
FxR2用于指定需要关心哪些位,FxR1用于指定这些位的标准值。
在32位的列表模式下:
有两个过滤器。
FxR1指定过滤器0的标准值,收到报文的标识符只有跟 FxR1完全相同时,才算通过。
FxR2指定过滤器1的标准值。
在16位的屏蔽位模式下:
有2个过滤器。
FxR1配置过滤器0,其中,[31-16]位指定要关心的位,[15-0]位指定这些位的标准值。
FxR2配置过滤器1,其中,[31-16]位指定要关心的位,[15-0]位指定这些位的标准值。
在16位的列表模式下:
有4个过滤器。
FxR1的[15-0]位配置过滤器0,FxR1的[31-16]位配置过滤器1。
FxR2的[15-0]位配置过滤器2,FxR2的[31-16]位配置过滤器3。
STM32的 CAN 有两个 FIFO,分别是 FIFO0和 FIFO1。为了便于区分,下面 FIFO0写作
FIFO_0,FIFO1写作 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 中只有激活了的过滤器才起作用,换句话说,如果一个 FIFO 有20个过滤器,
但是只激话了5个,那么比较报文时,只拿这5个过滤器作比较。
一般要用到某个过滤器时,在初始化阶段就直接将它激活。
需要注意的是,每个 FIFO 必须至少激活一个过滤器,它才有可能收到报文。如果一个过
滤器都没有激活,那么是所有报文都报废的。
一般的,如果不想用复杂的过滤功能, FIFO 可以只激活一组过滤器组,且将它设置成 32
位的屏蔽位模式,两个标准值寄存器(FxR1,FxR2)都设置成0。这样所有报文均能通过。
(STM32提供的例程里就是这么做的! )
STM32 CAN 中,另一个较难理解的就是过滤器编号。
过滤器编号用于加速 CPU 对收到报文的处理。
收到一个有效报文时, CAN 会将收到的报文 以及它所通过的过滤器编号, 一起存入接
收邮箱中。CPU 在处理时,可以根据过滤器编号,快速的知道该报文的用途,从而作出相
应处理。
不用过滤器编号其实也是可以的, 这时候 CPU 就要分析所收报文的标识符, 从而知道报
文的用途。
由于标识符所含的信息较多,处理起来就慢一点了。
STM32使用以下规则对过滤器编号:
(1) FIFO_0和 FIFO_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) 位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高。
按这样的顺序,报文能通过的第一个过滤器,就是该报文的过滤器编号,被存入接收邮箱
中。
纵浪大化中,不喜亦不惧;应尽便须尽,无复独多虑!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

93

主题

746

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1850
金钱
1850
注册时间
2012-9-16
在线时间
286 小时
 楼主| 发表于 2013-8-28 09:43:59 | 显示全部楼层
原子代码可以直接换成下列代码,测试没问题:
CAN_FilterInitStructure.CAN_FilterNumber=0;   //过滤器0(个人理解应为过滤组0)
 CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; //列表模式
 CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
 
使用过滤器0 (列表模式或回环模式)
//    CAN_FilterInitStructure.CAN_FilterIdHigh=((0x12<<21)&0xffff0000)>>16;//使用过滤器0
//    CAN_FilterInitStructure.CAN_FilterIdLow=((0x12<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
//    CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0xFFFF;
//    CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF;

使用过滤器1 (只能用于列表模式
  CAN_FilterInitStructure.CAN_FilterIdHigh=0xffff;
  CAN_FilterInitStructure.CAN_FilterIdLow=0xffff;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh= ((0x12<<21)&0xffff0000)>>16;//使用过滤器1     
  CAN_FilterInitStructure.CAN_FilterMaskIdLow= ((0x12<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
纵浪大化中,不喜亦不惧;应尽便须尽,无复独多虑!
回复 支持 1 反对 0

使用道具 举报

15

主题

204

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
287
金钱
287
注册时间
2013-7-17
在线时间
0 小时
发表于 2013-8-28 09:59:09 | 显示全部楼层
顶!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2013-8-28 10:35:52 | 显示全部楼层
顶楼主。
回复 支持 反对

使用道具 举报

96

主题

762

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1228
金钱
1228
注册时间
2012-10-19
在线时间
15 小时
发表于 2015-3-17 09:25:52 | 显示全部楼层
很不错~把过滤器解释的很清晰~
回复 支持 反对

使用道具 举报

4

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2013-6-10
在线时间
4 小时
发表于 2015-5-5 15:01:22 | 显示全部楼层
我需要10多个16位列表模式过滤器,不知如何设置,求教了
回复 支持 反对

使用道具 举报

4

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2013-6-10
在线时间
4 小时
发表于 2015-5-5 15:09:34 | 显示全部楼层
我需要10多个16位列表模式过滤器,不知如何设置,下面代码只过滤了4个ID,再多怎么写?求教了.
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit; //16位 
   CAN_FilterInitStructure.CAN_FilterIdHigh=(0x504<<5);//16位ID
   CAN_FilterInitStructure.CAN_FilterIdLow=(0x2c1<<5);
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh=(0x11<<5);//16位MASK
   CAN_FilterInitStructure.CAN_FilterMaskIdLow=(0x12<<5);
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
回复 支持 反对

使用道具 举报

9

主题

121

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1581
金钱
1581
注册时间
2014-7-8
在线时间
171 小时
发表于 2015-10-16 09:34:23 | 显示全部楼层
谢谢分享!正在学习怎么设置滤波器!
回复 支持 反对

使用道具 举报

8

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2015-3-9
在线时间
27 小时
发表于 2015-11-20 21:45:30 | 显示全部楼层
谢谢楼主,通俗易懂,顶!
回复 支持 反对

使用道具 举报

3

主题

261

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2075
金钱
2075
注册时间
2014-2-20
在线时间
284 小时
发表于 2015-12-25 09:41:29 | 显示全部楼层
顶!感谢楼主,昨天还在纠结这个问题
回复 支持 反对

使用道具 举报

18

主题

54

帖子

0

精华

初级会员

Rank: 2

积分
136
金钱
136
注册时间
2015-6-21
在线时间
34 小时
发表于 2016-3-31 18:55:27 | 显示全部楼层
象牙塔 发表于 2013-8-28 09:43
原子代码可以直接换成下列代码,测试没问题:
CAN_FilterInitStructure.CAN_FilterNumber=0; &nbsp;&nbsp ...

兄弟你这个(0x12<<21)是什么意思?求指导 谢谢
努力吧,骚年
回复 支持 反对

使用道具 举报

3

主题

37

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
304
金钱
304
注册时间
2015-4-11
在线时间
24 小时
发表于 2016-7-24 20:41:02 | 显示全部楼层
虽然帖子很久了,还是不错。我想问下,楼主有没有设计过过滤多个ID,比如32位屏蔽位模式,发送ID为0x10200和0x10202,那么接收端的ID初始化多少,已经屏蔽位怎么设置呢
回复 支持 反对

使用道具 举报

2

主题

90

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1107
金钱
1107
注册时间
2014-8-9
在线时间
192 小时
发表于 2016-8-19 17:28:15 | 显示全部楼层
我的设置在列表模式下:
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0/
// CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;  //屏蔽位模式
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList;  //列表模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;  //32位宽
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0100; //32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0200;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);   //滤波器初始化

CAN分析仪的ID设置为:0x0100 0000或者0x0200 0000发送报文,战舰开发板的CAN都收不到报文,战舰开发板发送的报文,CAN分析仪可以接收到(通信正常)!帮忙解答一下!
http://www.openedv.com/thread-82057-1-1.html

回复 支持 反对

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
发表于 2017-2-23 17:00:38 | 显示全部楼层
学习一下
回复 支持 反对

使用道具 举报

10

主题

147

帖子

0

精华

高级会员

Rank: 4

积分
602
金钱
602
注册时间
2015-7-11
在线时间
94 小时
发表于 2017-3-20 15:59:32 | 显示全部楼层
学习了,谢谢!!!
回复 支持 反对

使用道具 举报

3

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
93
金钱
93
注册时间
2015-5-27
在线时间
11 小时
发表于 2017-4-13 10:53:56 | 显示全部楼层
eaglelab 发表于 2015-5-5 15:09
我需要10多个16位列表模式过滤器,不知如何设置,下面代码只过滤了4个ID,再多怎么写?求教了.
CAN_FilterI ...

你好,你这个代码好使吗?我试了不好使啊
回复 支持 反对

使用道具 举报

2

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2017-3-28
在线时间
19 小时
发表于 2017-4-13 17:26:01 | 显示全部楼层
顶 顶 顶
回复 支持 反对

使用道具 举报

4

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
201
金钱
201
注册时间
2017-4-5
在线时间
24 小时
发表于 2017-6-24 10:10:48 | 显示全部楼层
号里的样子
回复 支持 反对

使用道具 举报

4

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
201
金钱
201
注册时间
2017-4-5
在线时间
24 小时
发表于 2017-6-29 08:05:19 | 显示全部楼层
不错啊
回复 支持 反对

使用道具 举报

4

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
201
金钱
201
注册时间
2017-4-5
在线时间
24 小时
发表于 2017-6-29 08:05:33 | 显示全部楼层
挺好的
回复 支持 反对

使用道具 举报

94

主题

369

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
发表于 2018-1-18 21:16:31 | 显示全部楼层
被CAN视频绕的云里雾里的,终于知道过滤器是什么了,谢谢楼主!
回复 支持 反对

使用道具 举报

6

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
126
金钱
126
注册时间
2018-1-18
在线时间
18 小时
发表于 2018-1-25 16:39:46 | 显示全部楼层
讲的比较透彻,前段时间自己调试CAN,调了一天才把过滤器弄明白了。要是早点看到这个贴子估计很快就搞定了。
不意人夸声色好,愿留心音在乾坤!
回复 支持 反对

使用道具 举报

26

主题

355

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1770
金钱
1770
注册时间
2017-4-1
在线时间
432 小时
发表于 2018-5-16 12:02:03 | 显示全部楼层
刚接触CAN的时候来看这篇帖子一头雾水,自己搭建做了试验后再来看终于看懂了,楼主写的很好。谢谢分享
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2018-11-30
在线时间
20 小时
发表于 2018-11-30 14:53:57 | 显示全部楼层
wx389390063 发表于 2016-8-19 17:28
我的设置在列表模式下:
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0/
// CAN_FilterInitS ...

你这个设置不对的,看手册CANID得像左移5位。
微信图片_20181130145235.png
回复 支持 反对

使用道具 举报

2

主题

90

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1107
金钱
1107
注册时间
2014-8-9
在线时间
192 小时
发表于 2018-12-1 23:12:00 | 显示全部楼层
Jxhe 发表于 2018-11-30 14:53
你这个设置不对的,看手册CANID得像左移5位。

你上面的截图只是使能设置过滤器0的。
与CAN_ID挂钩的配置是:
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0100; //32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0200;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
以上参数才会与CANID左移5位挂钩。
截图中的代码确实未体现CAN_ID左移5位的思想。将过滤ID固化,只能当Demo查看。
回复 支持 反对

使用道具 举报

4

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2015-4-6
在线时间
9 小时
发表于 2018-12-8 14:47:41 | 显示全部楼层
wx389390063 发表于 2018-12-1 23:12
你上面的截图只是使能设置过滤器0的。
与CAN_ID挂钩的配置是:
CAN_FilterInitStructure.CAN_FilterIdH ...

请问您的 id 问题有解了吗?
回复 支持 反对

使用道具 举报

349

主题

519

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1623
金钱
1623
注册时间
2014-7-11
在线时间
285 小时
发表于 2020-6-4 13:24:10 | 显示全部楼层
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0200;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;

这是屏蔽过滤器吧
回复 支持 反对

使用道具 举报

32

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2012-9-12
在线时间
18 小时
发表于 2020-12-21 14:38:38 | 显示全部楼层
通俗易懂,很好的文章
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-14 18:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表