通过对 CANBUS 协议的理解,我们知道:CAN 总线上的节点接收或发送数据都是以帧为单位的!!!CAN 协议规定了好几种帧类型,但是对于我们应用来说,只有数据帧和远程帧可以通过软件编程来控制。(其他几种帧都是由 CAN 控制器硬件实现的,我们想管也管不了)。而数据帧和远程帧最大的区别在于:远程帧没有数据域。数据帧分为标准数据帧和扩展数据帧,它们之间最大的区别在于:标识符(ID)长度不同(标准帧为 11 位,扩展帧为 29 位)。为了能更好地理解下面的内容,让我们先来回忆一下标准数据帧是什么样子的:
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。
先声明一个 CanTxMsg 类型的变量,然后按照自己具体的需要,填充此结构变量就可以发送了(帧结构中其他没有填充的部分由硬件自动完成)。
强调:这里的 StdId 或者 ExtId 是根据自己的实际需要设置的!我们先抛开它们所代表的实际意义,认为它们存在的目的是为了“进攻”。(发送出去让别人过滤)
接下来,我们来看接收,第一个问题就是它是怎样接收的?------过滤!!!无数的初学者都倒在了这里。
STM32 参考手册中提到:bxCAN 控制器为应用程序提供了 14 个位宽可变的、可配置的过滤器组(13~0)。(互联型有 28 个)。每个过滤器组的位宽都可以独立配置。可以配置成 16 位或者 32 位。过滤器组还可配置为屏蔽位模式或标识符列表模式。TNND,看起来好像很复杂!
先来理解一句话:共有14个过滤器组,每个过滤器组x由2个32位寄存器,CAN_FxR1和CAN_FxR2组成。
这样的话,就只能过滤出 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。