CAN总线详解

CAN过滤器详解

需要了解的知识:
1.CAN:Controller Area Network,控制器局域网
2.CAN-bus: Controller Area Network-bus,控制器局 域网总线技术

3.运行流程:
CAN总线详解_第1张图片
4.显性隐性:
CAN总线详解_第2张图片

一、 CAN帧结构

CAN-bus通信帧:数据帧、远程帧、错误帧、过载帧和帧间隔

1.数据帧

由7个段组成,其中根据仲裁段ID码长度的不同,分为标准帧(CAN2.0A)和扩展帧(CAN2.0B)。
CAN总线详解_第3张图片
1.1 帧起始、帧结束:
CAN总线详解_第4张图片
1.2 仲裁段

CAN总线详解_第5张图片
1.2.1总线仲裁:

CAN总线详解_第6张图片
CAN总线详解_第7张图片

  • 从该分析过程得出结论是:帧ID值越小,优先级越高
  • 对于同为扩展格式数据帧、标准格式远程帧和扩展格式远程帧的情况同理。

CAN总线详解_第8张图片
CAN总线详解_第9张图片
1.3 控制段
CAN总线详解_第10张图片
1.4 数据段

CAN总线详解_第11张图片

1.5 CRC段

CAN总线详解_第12张图片

1.6 ACK段
CAN总线详解_第13张图片

2. 远程帧

CAN总线详解_第14张图片

3. 数据帧与远程帧的区别

CAN总线详解_第15张图片

4. CAN-bus 错误类型

CAN总线详解_第16张图片
CAN总线详解_第17张图片
CAN总线详解_第18张图片

5. 过载帧

CAN总线详解_第19张图片

6. 帧间隔

CAN总线详解_第20张图片

7.CAN发送和接收

数据帧和远程帧最大的区别在于:远程帧没有数据域。数据帧分为标准数据帧和扩展数据帧,它们之间最大的区别在于:标识符(ID)长度不同(标准帧为11 位,扩展帧为29 位)。
为了能更好地理解下面的内容,让我们先来回忆一下标准数据帧是什么样子的:

CAN总线详解_第21张图片
7.1 发送:

前面已经强调了CAN 总线上的节点接收或者发送数据都是以帧为单位。假如我们要发送一个字节的数据:0x5A,是不是像串口发送数据那样,直接把0x5A 写入发送缓冲寄存器,然后发送就可以了呢?
NO! 刚才已经强调了,CAN 总线上的数据都是以帧为单位的!!!我们必须按照帧的格式填充它!TNND,
这么复杂?没关系,ST 库函数已经提供了一个结构,我们只需要填充该结构就可以了。我们来看一下
这个结构的样子:

typedef struct
{
uint32_t StdId; //标准帧ID,如果您要发送扩展帧。可以不管它
uint32_t ExtId; //扩展帧ID,如果您要发送标准帧。可以不管它
uint8_t IDE; //您是想发送标准帧还是扩展帧?
uint8_t RTR; //您是想发送数据帧还是远程帧?
uint8_t DLC; // 您想发送数据的长度。
uint8_t Data[8]; //您想要发送的数据。
} CanTxMsg;
  • StdId
    StdId 用来设定标准标识符。它的取值范围为0 到0x7FF。
  • ExtId
    ExtId 用来设定扩展标识符。它的取值范围为0 到0x1FFFFFFF。
  • IDE
    IDE 用来设定消息标识符的类型。
  • IDE值
IDE 描述
CAN_Id_Standard 使用标准标识符
CAN_Id_Extended 使用扩展标识符
  • RTR
    RTR 用来设定待传输消息的帧类型。它可以设置为数据帧或者远程帧。
  • RTR值
RTR 描述
CAN_RTR_Data 数据帧
CAN_RTR_Remote 远程帧
  • DLC
    DLC 用来设定待传输消息的帧长度。它的取值范围是0 到0x8。
  • Data[8]
    Data[8]包含了待传输数据,它的取值范围为0 到0xFF。

1. 先声明一个CanTxMsg 类型的变量,然后按照自己具体的需要,填充此结构变量就可
以发送了(帧结构中其他没有填充的部分由硬件自动完成)。
2. 强调:这里的StdId 或者 ExtId 是根据自己的实际需要设置的!我们先抛开它们所
代表的实际意义,认为它们存在的目的是为了“进攻”。(发送出去让别人过滤)

7.2 接收
STM32 参考手册中提到:bxCAN 控制器为应用程序提供了14 个位宽可变的、可配置的过滤器组(13~0)。(互联型有28 个)。每个过滤器组的位宽都可以独立配置。可以配置成16
位或者32 位。过滤器组还可配置为屏蔽位模式或标识符列表模式。TNND,看起来好像很复杂!

先来理解一句话:共有14个过滤器组,每个过滤器组x由2个32位寄存器,CAN_FxR1和CAN_FxR2组成。搞定一个过滤器组,其他的都可以以此类推。
我们先来看1个32位过滤器-标示符屏蔽的情况CAN_FxR1作ID,CAN_FxR2作屏蔽:
先看图:
CAN总线详解_第22张图片

这里的ID 是什么意思?难道就是前面所说的发送数据帧里面的ID?NO!这里的ID 和自己发送的帧里面的ID 没有一点关系。完全是两个东西,在硬件上属于不同的寄存器。强调:这里的ID也是根据自己的实际需要设置的!我们先抛开它们所代表的实际意义,认为它们存在的目的是为了“防守”。(过滤别人发送过来的帧的 ID)
这里的屏蔽是什么意思?这里的屏蔽和ID 共同配合完成过滤。
这里的映像是什么意思?映像的意思就是假定收到的帧的ID 信息。
下面举个例子,一切都会一目了然:
1.: 假如我们只想收到别人发过来的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 (屏蔽)

这里是我们设置的想要收到的数据帧的ID。
这里为1 的位,意味着收到的数据帧中相应的ID 位必须和设置的ID 位一样(必须匹
配)。
2.: 假如我们想收到别人发过来的ID 为0x310 到0x317 的标准数据帧:
那么可以这样设置:

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

这里的红色xxx 就代表000 到111 的任意组合。
这里为0 的位,意味着收到的数据帧中的相应位的ID 不一定非要与设置的ID 一样(不用关心)。
这里红色部分表明必须是标准数据帧。
3.: 假如我们想收到别人发过来的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。
在这里插入图片描述
举个例子:
如果我们把CAN_FxR1 和CAN_FxR2 设置为下面的样子。
CAN_FxR1:0110 0010 1110 0000 0000 0000 0000 0000 (ID)
CAN_FxR2:0000 0001 1110 0000 0000 0000 0000 0000 (ID)
这样的话,就只能过滤出ID 为0x317(与CAN_FxR1 必须一样)和0x00F(与CAN_FxR2 必须一样)两种标准数据帧了。
以上是32 位模式下标识符屏蔽模式和标识符列表模式下的设置方法。
在16 位模式下,只不过把两个32 位寄存器拆成了4 个16 位的而已,原理和32 位模式下是一样的。就不赘述了。
接收数据是通过指向CanRxMsg 结构体变量的指针传递的。直接调用 CAN_Receive 即可轻松完成。

typedef struct
{
uint32_t StdId;
uint32_t ExtId;
uint8_t IDE;
uint8_t RTR;
uint8_t DLC;
uint8_t Data[8];
uint8_t FMI;
} CanRxMsg;

CanRxMsg 结构与CanTxMsg 差不多。只是多了一个FMI 域。

  • FMI
    FMI 设定为消息将要通过的过滤器索引,这些消息存储于邮箱中。该参数取值范围0 到
    0xFF。

8.

9.

10.

11.

12.

你可能感兴趣的:(STM32F4)