[其他ST产品]

STM32 CAN 发送和接收过滤原理

[复制链接]
459|19
手机看帖
扫描二维码
随时随地手机跟帖
铁血丹心LLLL|  楼主 | 2022-3-30 15:27 | 显示全部楼层 |阅读模式
AN, ST
通过对CANBUS协议的理解,我们知道:CAN总线上的节点接收或发送数据都是以帧为单位的。CAN协议规定了好几种帧的类型,但是对于使用者而言,只有数据帧和远程帧可以通过软件编程来控制。(其他几种帧都是由CAN控制硬件实现的,我们想管也管不了)。而数据帧和远程帧最大的区别在于:远程帧没有数据域。(这也是我没有用过远程帧的原因o(╯□╰)o)数据帧分为标准帧和扩展数据帧,它们之间最大的区别在于:标识符(ID)长度不同(标准帧为11位,而扩展帧为29为)。

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:28 | 显示全部楼层
在这里就不对数据帧的构成作介绍了,主要介绍STM32中MCU是如何接收其他MCU发送过来的数据的。其实原理很简单,就是过滤!只不过过滤遵循的原则比较琐碎,很多人都不太理解这个原则。

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:29 | 显示全部楼层
STM32参考手册中提到:bxCAN控制器为应用程序提供了14个位宽可变的、可变的过滤器组(0~13)(互联型有28个)。每个过滤器组的位宽都可以独立配置。可以配置成16位或者32位。过滤器组还可以配置为屏蔽位模式(也叫标识符屏蔽模式、标识符掩码模式、CAN_FilterMode_IdMask)或者标识符列表模式(CAN_FilterMode_IdList)。

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:30 | 显示全部楼层
先理解一句话,每个过滤器组x由2个32位寄存器,CAN_FxR1和CAN_FxR2组成。我们只要理解了一个过滤器组,其他可以类推。我们先来看一个32位过滤器处于屏蔽位模式的情况。CAN_FxR1作ID,CAN_FxR2作屏蔽,如下图所示。

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:31 | 显示全部楼层
9200362440735d7dbc.png

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:31 | 显示全部楼层
第一行的ID就是CAN_FxR1寄存器中的内容,而第二行掩码就是CAN_FxR2寄存器中的内容。需要注意的是,这里的ID和发送数据帧里面的ID并不是一个东西,它(筛选器中的ID)是接收机中的内容,接收机用它来确定自己要接收的数据。   强调:这里的ID也是根据自己的实际需要设置的!抛开它们所代表的的实际意义,认为它们存在的意义是为了“防守”(过滤其他MCU发送过来的帧 的ID)。     

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:32 | 显示全部楼层
这里的屏蔽(也就是第二行开头的掩码)是什么意思??这里的屏蔽和ID共同配合完成过滤。

这里的映射什么意思??映射的意思就是假定收到的帧的ID信息。     

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:32 | 显示全部楼层
看例子:

1、若我们只想收到其他MCU发过来的ID为 0x317 的标准数据帧:                                 

0x317 的二进制位: 011 0001 0111                                                                           

那么就可以这样设置:

CAN_FxR1 :0110  0010  111X  XXXX  XXXX  XXXX   XXXX  X00X    (ID)                     

CAN_FxR2 :1111   1111   1110   0000   0000   0000     0000   0110   (屏蔽)

CAN_FxR1 (第一行)就是我们设置的想要收到的数据帧的ID。                                    CAN_FxR2 (第二行)中为 1 的位,意味着收到的数据帧中相应的ID位必须和设置的ID位一样(必须匹配)。

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:34 | 显示全部楼层
2、若我们想收到其他MCU发过来的ID位 0x310 到 0x317 的标准数据帧:                     

那么就可以这样设置:

CAN_FxR1 :0110  0010  xxxX  XXXX  XXXX  XXXX   XXXX  X00X    (ID)                      CAN_FxR2 :1111   1111  0000   0000    0000   0000     0000   0110   (屏蔽)

CAN_FxR1中的红色xxx就代表了 000 到 111 的任意组合。                                            

CAN_FxR2中为 0 的位,意味着收到的数据帧中的相应位的ID不一定非要与设置的ID一样(不用关心)。最后两个红色的 1 表明必须是标准数据帧。

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:50 | 显示全部楼层
3、若我们想收到其他MCU发过来的ID为 0x000 到 0x7FF 的标准数据帧:                     

那么就可以这样设置:

CAN_FxR1 :xxxx   xxxx  xxxX  XXXX  XXXX  XXXX   XXXX  X00X    (ID)                     

CAN_FxR2 :0000  0000  0000   0000   0000   0000     0000   0110   (屏蔽)

接下来看2个32位过滤器——标识符列表模式,CAN_FxR1和CAN_FxR2都作为ID。这种情况就比较简单。只有接收到的数据帧的ID和CAN_FxR1或者CAN_FxR2完全一样,这样我们才会接收它。这样的话,就只能接收两种不同的ID。

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:50 | 显示全部楼层
1414862440bd90b525.png

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:51 | 显示全部楼层
也就是说,第一行和第二行的ID都用于过滤接收的数据帧的ID,只有接收到的数据帧的ID与它们俩之中一个,才会被接收。         

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:51 | 显示全部楼层
看例子:

若我们把CAN_FxR1和CAN_FxR2设置成如下的样子。

CAN_FxR1 :0110  0010  111X  XXXX  XXXX  XXXX   XXXX  X00X    (ID)                      CAN_FxR2 :0000  0001  1110   0000    0000   0000     0000   0000    (ID)

这样的话, 就只能过滤出ID为 0x317(与CAN_FxR1必须一样)和 0x00F (与CAN_FxR2必须一样)两种标准数据帧了。   

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-3-30 15:52 | 显示全部楼层
以上就是32位模式下标识符屏蔽模式和标识符列表模式下的设置方法。

在16位模式下,只不过把两个32位寄存器拆成了4个16位的而已,原理和32位模式下是一样的。

使用特权

评论回复
qbwww| | 2022-10-2 16:15 | 显示全部楼层
而数据帧和远程帧最大的区别在于:远程帧没有数据域。(这也是我没有用过远程帧的原因o(╯□╰)o)数据帧分为标准帧和扩展数据帧,它们之间最大的区别在于:标识符(ID)长度不同(标准帧为11位,而扩展帧为29为)

使用特权

评论回复
redone| | 2022-10-3 15:13 | 显示全部楼层
一直以为,能通信就可以了,原来can面这么多门道

使用特权

评论回复
Jacquetry| | 2022-10-5 21:13 | 显示全部楼层
里面还有这么些学问

使用特权

评论回复
Bblythe| | 2022-10-8 08:22 | 显示全部楼层

显然直接调用的话,那么调用线程会被阻塞暂停

使用特权

评论回复
Pulitzer| | 2022-10-8 11:21 | 显示全部楼层

Keil编写程序是默认的时钟为72Mhz

使用特权

评论回复
Uriah| | 2022-10-8 18:22 | 显示全部楼层

TIM4、UART1初始化代码只是些各种相关基本配置,不跟别的外设有关联

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

421

帖子

1

粉丝