STM32 CAN过滤器详解.docx
《STM32 CAN过滤器详解.docx》由会员分享,可在线阅读,更多相关《STM32 CAN过滤器详解.docx(9页珍藏版)》请在冰豆网上搜索。
STM32CAN过滤器详解
STM32CAN过滤器详解
------SummerRain94
1.前言
bxCAN是STM32系列最稳定的IP核之一,无论有哪个新型号出来,这个IP核基本未变,可见这个IP核的设计是相当成熟的。
本文所讲述的内容属于这个IP核的一部分,掌握了本文所讲内容,就可以很方便地适用于所有STM32系列中包含bxCAN外设的型号。
有关bxCAN的过滤器部分的内容在参考手册中往往看得“不甚明白“,本文就过滤器的4种工作模式进行详细讲解并使用具体的代码进行演示,这些代码都进行过实测验证通过的,希望能给读者对于bxCAN过滤器有一个清晰的理解。
2.准备工作
2.1. 为什么要过滤器?
在这里,我们可以将CAN总线看成一个广播消息通道,上面传输着各种类型的消息,好比报纸,有体育新闻,财经新闻,政治新闻,还有军事新闻,每个人都有自己的喜好,不一定对所有新闻都感兴趣,因此,在看报纸的时候,一般人都是只看自己感兴趣的那类新闻,而过滤掉其他不感兴趣的内容。
那么我们一般是怎么过滤掉那些不感兴趣的内容的呢?
下面有两种方法来实现这个目的:
第一种方法:
每次看报纸时,你都看下每篇文章的标题,如果感兴趣则继续看下去,如果不感兴趣,则忽略掉。
第二种方法:
你告诉邮递员,你只对财经新闻感兴趣,请只将财经类报纸送过来,其他的就不要送过来了,就这样,你看到的内容必定是你感兴趣的财经类新闻。
上面那种方法好呢?
很明显,第二种方法是最好的,因为你不用自己每次判断哪些新闻内容是你感兴趣的,可以免受“垃圾”新闻干扰,从而可以节省时间忙其他事。
bxCAN的过滤器就是采用上述第二种方法,你只需要设置好你感兴趣的那些CAN报文ID,那么MCU就只能收到这些CAN报文,是从硬件上过滤掉,完全不需要软件参与进来,从而节省了大大节省了MCU的时间,可以更加专注于其他事务,这个就是bxCAN过滤器的意义所在。
2.2.两种过滤模式(列表模式与掩码模式)
假设我们是bxCAN这个IP的设计者,现在由我们来设计过滤器,那么我们该如何设计呢?
首先我们是不是很快就会想到只要准备好一张表,把我们需要关注的所有CAN报文ID写上去,开始过滤的时候只要对比这张表,如果接收到的报文ID与表上的相符,则通过,如果表上没有,则不通过,这个就是简单的过滤方案。
恭喜你!
bxCAN过滤器的列表模式采用的就是这种方案。
但是,这种列表方案有点缺陷,即如果我们只关注一个报文ID,则需要往列表中写入这个ID,如果需要关注两个,则需要写入两个报文ID,如果需要关注100个,则需要写入100个,如果需要1万个,那么需要写入1万个,可问题是,有这个大的列表供我们使用吗?
大家都知道,MCU上的资源是有限的,不可能提供1万个或更多,甚至100个都嫌多。
非常明显,这种列表的方式受到列表容量大小的限制,实际上,bxCAN的一个过滤器若工作在列表模式下,scale为32时,每个过滤器的列表只能写入两个报文ID,若scale为16时,每个过滤器的列表最多可写入4个CANID,由此可见,MCU的资源是非常非常有限的,并不能任我们随心所欲。
因此,我们需要考虑另外一种替代方案,这种方案应该不受到数量限制。
下面假设我们是古时候一座城镇的守卫,城主要求只有1156年出生的人才可以进城,我们又该如何执行呢?
假设古时候的人也有类似今天的身份证(...->_<-…),大家都知道,身份份证号码中有4位是表示出生年月,如下图:
如上图,身份证中第7~10这4位数表示的是出生年份,那么,我们可以这么执行:
检查想要进城的所有人的身份证号码的第7~10位数字,如果这个数字依次为1156则可以进入,否则则不可以,至于身份证号码的其他位则完全不关心。
假如过几天城主放宽进城条件为只要是1150年~1160前的人都可以进城,那么,我们就可以只关注身份证号码的第7~9这3位数是否为115就可以了,对不对?
这样一来,我们就可以非常完美地执行城主的要求了。
再变下,假设现在使用机器来当守卫,不再是人来执行这个“筛选”工作。
机器是死的,没有人那么灵活,那么机器又该如何执行呢?
对于机器来说,每一步都得细化到机器可以理解的程度,于是我们可以作如下细化:
第一步:
获取想进城的人的身份证号码
第二步:
只看获取到身份证的第7~9位,其他位忽略
第三步:
将忽略后的结果与1156进行比较
第四步:
比较结果相同则通过,不同则不能通过
这种方式,我们称之为掩码模式。
2.3. 验证码与屏蔽码
仔细查看上面4个步骤,这不就是C代码中的if语句吗?
如下:
对于机器来说,我们要为它准备好两张纸片,一片写上屏蔽码,另一片纸片写上验证码,屏蔽码上相应位为1时,表示此位需要与验证码对应位进行比较,反之,则表示不需要。
机器在执行任务的时候先将获取的身份证号码与屏蔽码进行“与”操作,再将结果与验证码的进行比较,根据判断是否相同来决定是否通过。
整个判别流程如下所示:
从上图可以很容易地理解屏蔽码与验证码的含义,这样一来,能通过的结果数量就完全取决于屏蔽码,设得宽,则可以通过的多(所有位为0,则不过任何过滤操作,则谁都可以通过),设得窄,则通过的少(所有位设为1,则只有一个能通过)。
那么知道这个有什么用呢?
因为bxCAN的过滤器的掩码模式就是采用这种方式,在bxCAN中,分别采用了两个寄存器(CAN_FiR1,CAN_FiR2)来存储屏蔽码与验证码,从而实现掩码模式的工作流程的。
这样,我们就知道了bxCAN过滤器的掩码模式的大概工作原理。
但是,我们得注意到,采用掩码模式的方式并不能精确的对每一个ID进行过滤,打个比方,还是采用之前的守卫的例子,假如城主要求只有1150~1158年出生的人能通过,那么,若我们还是使用刚才的掩码模式,那么掩码就设为第7~9位为”1”,对应的,验证码的7~9位分别为”115”,这样就可以了。
但是,仔细一想,出生于1159的人还是可以通过,是不是?
但总体来说,虽然没有做到精确过滤,但我们还是能做到大体过滤的,而这个就是掩码模式的缺点了。
在实际应用时,取决于需求,有时我们会同时使用到列表模式和掩码模式,这都是可能的。
2.4. 列表模式与掩码模式的对比
综合之前所述,下面我们来对比一下列表模式与掩码模式这两种模式的优缺点。
2.5. 标准CANID与扩展CANID
1986年德国电气商BOSCH公司开发出面向汽车的CAN通信协议,刚开始的时候,CANID定义为11位,我们称之为标准格式,ISO11898-1标准中CAN的基本格式如下图所示:
如上图所示,标准CANID存放在上图ID18~ID28中,共11位。
随着工业发展,后来发现11位的CANID已经不够用,于是就增加了18位,扩展CANID到29位,如下图所示:
从上图对比扩展CAN报文与标准CAN报文,发现在仲裁域部分,扩展CAN报文的CANID包含了baseIdentifier与extensionIdentifier,即基本ID与扩展ID,而标准CAN报文的CANID部分只包含基本ID,扩展ID(ID0~ID17)被放在基本ID的右方,也就是说,属于低位。
知道这些有什么用呢?
至少我们可以得到这两条信息:
∙ 标准ID一般小于或等于<=0x7FF(11位),只包含基本ID。
∙对于扩展CAN的低18位为扩展ID,高11位为基本ID。
例如标准CANID0x7E1,二进制展开为0b0[11111100001] ,只有中括号内的11位才有效,其全部是基本ID。
再例如扩展CANID0x1835f107,二进制展开为0b000[11000001110][011111000100000111],只有红色中括号和绿色中括号内的位才有效,总共29位,左边红色中括号中的11位为基本ID,右边绿色中括号内的18位为扩展ID,请记住这个信息!
知道这个之后,我们可以很方便地将一个CANID拆分成基本ID和扩展ID,这个也将在后续的内容中多次用到,再次留意一下,扩展ID是位于基本ID的右方,在扩展CANID的构成中,扩展ID位于低18位,而基本ID位于高11位,于是要获取一个扩展CANID的基本ID,就只需要将这个CANID右移18位(这种算法后续将多次用到,请务必记住!
)。
3.bxCAN的过滤器的解决方案
终于进入到正题了!
前面已经介绍了过滤器的列表模式与掩码模式,以及掩码模式下的屏蔽码与验证码的含义,还介绍了标准CANID与扩展CANID的组成部分。
现在我们终于要站在bxCAN的角度来分析其过滤方案。
首先过滤模式分列表模式和掩码模式,因此,对于没有过滤器,我们需要这么一个位来标记,用户可以通过设置这个位来标记他到底是想要这个过滤器工作在列表模式下还是掩码模式,于是,这个表示过滤模式的位就定义在CAN_FM1R寄存器中的FBMx位上,如下图:
这里以STM32F407为例,bxCAN共有28个过滤器,于是上图的每一个位对应地表示这28个过滤器的工作模式,供用户设置。
”0”表示掩码模式,”1”表示列表模式。
另外,我们知道了标准CANID位11位,而扩展CANID有29位,对于标准的CANID来说,我们有一个16位的寄存器来处理他足够了,相应地,扩展CANID,我们就必须使用32位的寄存器来处理它,而在实际应用中,根据需求,我们可能自始至终都只需要处理11位的CANID。
对于资源严重紧张的MCU环境来说,本着不浪费的原则,这里最好能有另外一个标志用告诉过滤器是否需要处理32位的CANID。
于是,bxCAN处于这种考虑,也设置了这么一个寄存器CAN_FS1R来表示CANID的位宽,如下图所示:
如上图,每一个位对应着bxCAN中28个过滤器的位宽,这个需要用户来设置。
于是根据模式与位宽的设置,我们共可以得出4中不同的组合:
32位宽的列表模式,16位宽的列表模式,32位宽掩码模式,16位宽的掩码模式。
如下图所示:
在bxCAN中,每个过滤器都存在这么两个寄存器CAN_FxR1和CAN_FxR2,这两个寄存器都是32位的,他的定义并不是固定的,针对不同的工作模式组合他的定义是不一样的,如列表模式-32位宽模式下,这两个寄存器的各位定义都是一样的,都用来存储某个具体的期望通过的CANID,这样就可以存入2个期望通过的CANID(标准CANID和扩展CANID均可);若在掩码模式-32位宽模式下时,则CAN_FxR1用做32位宽的验证码,而CAN_FxR2则用作32位宽的屏蔽码。
在16位宽时,CAN_FxR1和CAN_FxR2都要各自拆分成两个16位宽的寄存器来使用,在列表模式-16位宽模式下,CAN_FxR1和CAN_FxR2定义一样,且各自拆成两个,则总共可以写入4个标准CANID,若在16位宽的掩码模式下,则可以当做2对验证码+屏蔽码组合来用,但它只能对标准CANID进行过滤。
这个就是bxCAN过滤器的解决方案,它采用了这4种工作模式。
5.总结
在实际的应用中,我们需要根据需求的实际情况来决定使用何种过滤配置,STM32F4的bxCAN提供了28个过滤器,在配置之前,我们需要先将那些需要通过的CANID进行整理,若数量少,则使用列表模式,精准,若只有标准CANID,则可以考虑使用16位宽模式,若需求中的CANID过多,则可以考虑使用多个过滤器,部分使用列表模式,部分使用掩码模式,CANID值相近的可以归纳成一组,使用掩码模式进行过滤。
但使用掩码模式的同时,我们也需要意识到,也有可能部分不期望的CANID也会通过过滤器,掩码放得越宽,带进其他CANID的几率就越大,这点我们需要格外注意,视情况进行应用判断和处理。
另外,对于相近的CANID,我们可以提前计算好屏蔽码,直接在代码中填入,而不是在代码中临时计算,这样可以提高软件效率,大家视情况而定。