以字节数组形式访问结构
Access struct as array of bytes
我目前正在重写程序以使用 RDM protocol 处理通过串行连接接收的数据,每个数据包都由 UART 接收并具有特定的结构,但可能会有所不同length,下面是一个数据包结构示例,假设数据包中的字节数为n(这可能会根据数据包的内容而变化)
我想做的是在我的 C 代码中定义一个结构,它定义了各种参数,但为了能够读取和写入字节 to/from 来自 UART 的结构,就好像该结构只是uint8_t 的数组。我对此的问题是,我读到结构可能并不总是存储在连续的内存部分中,因此采用 &RDMPacket1
并递增结构可能最终导致数据不在正确的位置。
我的另一个问题是,如果我有一个数组来在结构中存储最大可能长度(220 字节)的数据包数据,那么数据包末尾的校验和将被写入错误的位置。可以使用哪些方法接收数据并将其放入结构中?
示例数据包定义(从标准缩短)
Byte | Description
0 | START Code - Constant, can be ignored
1 | Sub-Start Code - Contains command for device to process
2 | Message Length - Points to byte number of Checksum High (up to 255)
3-8 | Destination UID - Unique ID of packet Destination
9-14 | Source UID - Unique ID of packet Source
15 | Transaction Number - ID of transaction between controller and responder
16-(n-2) | Data (up to 220 bytes long)
n-1 | Checksum High
n | Checksum Low
这是一个结构示例,用于保存最大可能长度的数据包:
struct RDMPacket
{
uint8_t subStartCode;
uint8_t messageLength;
uint32_t destinationUID;
uint32_t sourceUID;
uint8_t transactionNumber;
uint8_t portID;
uint8_t messageCount;
uint8_t subDevice;
uint8_t commandClass
uint8_t parameterID;
uint8_t parameterDataLength;
uint8_t parameterData[220];
uint16_t checksum
} RDMPacket1;
当您处理非字节对齐的内存结构时,可能会出现您所描述的问题。在这种情况下,每个结构字段都将具有特定的对齐方式。即,如果对齐为 4 个字节,则每个字段将从可被 4 整除的地址开始。为避免这种情况,您可以使用 GCC 的属性 packed
作为结构,指示编译器将结构打包为最小内存。在其他编译器中有 #pragma pack
或一些其他相应的编译器指令用于此目的。为确保您的结构已打包,您可以使用 sizeof
检查其大小并将其与预期大小进行比较。
我目前正在重写程序以使用 RDM protocol 处理通过串行连接接收的数据,每个数据包都由 UART 接收并具有特定的结构,但可能会有所不同length,下面是一个数据包结构示例,假设数据包中的字节数为n(这可能会根据数据包的内容而变化)
我想做的是在我的 C 代码中定义一个结构,它定义了各种参数,但为了能够读取和写入字节 to/from 来自 UART 的结构,就好像该结构只是uint8_t 的数组。我对此的问题是,我读到结构可能并不总是存储在连续的内存部分中,因此采用 &RDMPacket1
并递增结构可能最终导致数据不在正确的位置。
我的另一个问题是,如果我有一个数组来在结构中存储最大可能长度(220 字节)的数据包数据,那么数据包末尾的校验和将被写入错误的位置。可以使用哪些方法接收数据并将其放入结构中?
示例数据包定义(从标准缩短)
Byte | Description
0 | START Code - Constant, can be ignored
1 | Sub-Start Code - Contains command for device to process
2 | Message Length - Points to byte number of Checksum High (up to 255)
3-8 | Destination UID - Unique ID of packet Destination
9-14 | Source UID - Unique ID of packet Source
15 | Transaction Number - ID of transaction between controller and responder
16-(n-2) | Data (up to 220 bytes long)
n-1 | Checksum High
n | Checksum Low
这是一个结构示例,用于保存最大可能长度的数据包:
struct RDMPacket
{
uint8_t subStartCode;
uint8_t messageLength;
uint32_t destinationUID;
uint32_t sourceUID;
uint8_t transactionNumber;
uint8_t portID;
uint8_t messageCount;
uint8_t subDevice;
uint8_t commandClass
uint8_t parameterID;
uint8_t parameterDataLength;
uint8_t parameterData[220];
uint16_t checksum
} RDMPacket1;
当您处理非字节对齐的内存结构时,可能会出现您所描述的问题。在这种情况下,每个结构字段都将具有特定的对齐方式。即,如果对齐为 4 个字节,则每个字段将从可被 4 整除的地址开始。为避免这种情况,您可以使用 GCC 的属性 packed
作为结构,指示编译器将结构打包为最小内存。在其他编译器中有 #pragma pack
或一些其他相应的编译器指令用于此目的。为确保您的结构已打包,您可以使用 sizeof
检查其大小并将其与预期大小进行比较。