STM32的CAN总线+J1939数据格式说明

更新时间:2023-12-21 18:55:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

在STM32中都是有标准的数据结构和函数供大家使用,那么对于具体的每一部分对应那些数据、每一位代表什么意思都没有具体说明。特别在使用某些协议,需要辨别该部分的具体信息时,就必须对数据结构中的每位的意义清楚才能提取出具体的含义。先来看一下下面的东西吧。 CAN帧结构。

这个就不具体介绍了,不过先提一点疑问:在STM32中直接给结构体中各成员直接赋值或读取,那么其实际的发送或接收的最底层的结构又是怎么样的呢? 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; 接受结构体和发送结构体一样,就只是结构体名不一样而已(CanTxMsg)。

对于上面的问题,在一些协议中进行解析时,如何将这些标识符与协议的具体项对应呢?由于在做J1939协议的编程,所以就以这个为例说明一下。

如上所示,在J1939中CAN帧结构为32位,包含优先级、PDU格式(PF)、PS、SA。而在STM32的结构体中却是32位的ID,8位的IDE、RTR、DLC。如果要单独提取标识符中的某一个有如何提取呢? 这就涉及到STM32的收发邮箱的寄存器存储结构了。来看一下其标识符寄存器结构吧 (接收和发送寄存器结构除0位外都一样)

位 31:21 20:3 2 1 0 名称 STID[10:0] EXID[17:0] IDE RTR TXRQ(发送) / 保留(接受) 说明 标准标识符或扩展标识符的高字节 扩展标识符 扩展帧标识的低字节 0:使用标准标识符 1:使用扩展标识符 0:数据帧 1:远程帧 发送数据请求/保留 对于J1939协议来说,必须对帧数据和优先级、PF、PS、SA进行双向解析。所以我们在发送数据或收到数据时必须做一定的处理。在STM32的固件库函数中该寄存器中的各个部分的值提取出来赋给其结构体中个部分的值。

发送数据时:

u32 Id_Ext = 0x00000000;

Id_Ext = Id_Ext|Priority<<26;

Id_Ext = ((Id_Ext>>16)|Pdu_PF)<<16; Id_Ext = ((Id_Ext>>8)|Pdu_Ps)<<8; Id_Ext = Id_Ext|Pdu_Sa; 接收数据时:

PDU_PF = (RxMessage.ExtId&0x00ff0000)>>16; PDU_PS = (RxMessage.ExtId&0x0000ff00)>>8; PDU_SA = RxMessage.ExtId&0x000000FF;

注意:在帧结构图中我们看到PF被分成了两部分,而在上面的处理中PF却是连在一起的8位。这又是怎么回事呢?

这就要归结为ExtId这个结构体成员的具体形式了。 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 0无效位 15 14 13 优先级3位 12 11 PS 10 R(0) DP(0) 9 8 7 6 5 4 PF 3 SA 2 1 0 我想通过这个ExtId数据位结构的说明,对于如何对帧数据和优先级、PF、PS、SA进行双向解析有了比较清楚的认识了吧。

大家可以结合下面这个STM32中的函数对比着看更容易理解。

void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage) {

/* Check the parameters */

assert_param(IS_CAN_ALL_PERIPH(CANx)); assert_param(IS_CAN_FIFO(FIFONumber)); /* Get the Id */

RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RIR; if (RxMessage->IDE == CAN_ID_STD) {

RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RIR>> 21); } else {

RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 3); }

RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONumber].RIR; /* Get the DLC */

RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONumber].RDTR; /* Get the FMI */

RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDTR >> 8); /* Get the data field */

RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDLR;

RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 8); RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 16); RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 24); RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDHR;

RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 8); RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 16); RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 24); /* Release the FIFO */

CAN_FIFORelease(CANx, FIFONumber); }

本文来源:https://www.bwwdw.com/article/d585.html

Top