数据帧分为标准数据帧和扩展数据帧。它们之间最大的区别在于:标识符(ID)长度不同(标准帧为 11 位,扩展帧为 29 位)。
远程帧没有数据域,数据帧有数据域。
以下均用最常见的标准数据帧来解释。
这是can发送的结构体
typedef struct
{
uint32_t StdId; //标准帧 ID,如果您要发送扩展帧。可以不管它
//StdId 用来设定标准标识符。它的取值范围为 0 到 0x7FF。
uint32_t ExtId; //扩展帧 ID,如果您要发送标准帧。可以不管它
//ExtId 用来设定扩展标识符。它的取值范围为 0 到 0x1FFFFFFF。
uint8_t IDE; //您是想发送标准帧还是扩展帧?
//CAN_Id_Standard 使用标准标识符
//CAN_Id_Extended 使用扩展标识符
uint8_t RTR; //您是想发送数据帧还是远程帧?
//CAN_RTR_Data 数据帧
//CAN_RTR_Remote 远程帧
uint8_t DLC; // 您想发送数据的长度。
// DLC 用来设定待传输消息的帧长度。它的取值范围是 0 到 0x8。
uint8_t Data[8]; //您想要发送的数据。
//Data[8]包含了待传输数据,它的取值范围为 0 到 0xFF。
} CanTxMsg;
接收数据是通过指向 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。就是你调用哪一个过滤器,F1有14个过滤器,F4有28个过滤器。
下面来具体讲讲CAN通信的数据是怎么接收的。
1、一个芯片有14个过滤器组,过滤器组之间可以相互切换(吉老师说一般只用一个过滤器组,比如四个驱动和一个主控,那么驱动只要设置识别主控的ID不要变就行了,然后主控可以识别所有驱动的ID)
2、一个过滤器组有两个寄存器,CAN_FxR1和CAN_FxR2,一个过滤器组也有两种模式,一种是ID和掩码(又称屏蔽或者mask)的组合,一种是ID与ID的组合。
第一种组合:
对于每一个寄存器来说,倒数第二位和倒数第三位设置为00,则是ID,如果是11,则是掩码。掩码为1表示ID的对应的这一位必须相同,掩码为0表示ID对应的这一位没有要求,就相当于我们平常所说的“精准匹配”和“模糊匹配”的要求,我们想精确找一个人,就得把他的眼睛鼻子嘴巴,腿,身高等等一切信息作为寻找的参考,这样才能精准地找到一个人,这个时候就相当于掩码全给1,每一个“参考标准”都起作用。与之对应的,我们不仅仅只想找一个人,我们想找一群人,那么我们就减少标准,只要求他的身高符合,眼睛符合,就行了,其余不做要求,那么这样,就不只一个人会符合我们的匹配要求,就会有很多人。在单片机的通信中,一个芯片就会收到不只一个ID发来的信息,其他符合条件的ID发来的信息也能接收。
第二种组合:
如果两个寄存器的倒数第二位和倒数第三位都是00,那么就只能检测出这两个ID。就是只精确地找两个人。
这是第一种组合:掩码的前11位全为0,对于ID没有产生限制。
CAN_FxR1:xxxx xxxx xxxX XXXX XXXX XXXX XXXX X00X (ID)
CAN_FxR2:0000 0000 0000 0000 0000 0000 0000 0110 (屏蔽)
收到别人发过来的 ID 为 0x000 到 0x7FF 的标准数据帧
这是第二种组合:
CAN_FxR1:0110 0010 1110 0000 0000 0000 0000 0000 (ID)
CAN_FxR2:0000 0001 1110 0000 0000 0000 0000 0000 (ID)
只能识别这两个ID。
这是第一种组合:
CAN_FxR1:0110 0010 xxxX XXXX XXXX XXXX XXXX X00X (ID)
CAN_FxR2:1111 1111 0000 0000 0000 0000 0000 0110 (屏蔽)
能识别别人发过来的 ID 为 0x310 到 0x317 的标准数据帧。
这里的”xxx”表示为0和1没有任何关系。
还有一个容易弄混的是,发送的时候给的ID是自己的ID,过滤器是用来限制你接收到的别人的ID,和自己一毛钱关系都没有。(这句话有待考究,这个ID其实只要弄懂过滤的机制,其实不用去纠结所谓自己和别人的ID,只有发送的时候的ID以及自己设置的过滤器罢了,就这两者)