首先,我还是学生。所以我不是很有经验。
我正在使用蓝牙硬件,我正在使用其协议发送命令。该协议要求每个数据包字段首先使用LSB发送数据包。
我收到错误数据包回到我身上,表明我的CRC值是错误的,所以我做了一些调查。我发现了问题,但我在这个过程中感到困惑。
这是一些GDB输出和其他信息,说明我的困惑。
我发送的数据包应该是这样的:
|Start Flag| Packet Num | Command | Payload | CRC | End Flag|
0xfc 0x1 0x0 0x8 0x0 0x5 0x59 0x42 0xfd
这是一些GDB输出:
print /x reqId_ep
$1 = {start_flag = 0xfc, data = {packet_num = 0x1, command = {0x0, 0x8}, payload = {
0x0, 0x5}}, crc = 0x5942, end_flag = 0xfd}
reqId_ep是我正在发送的数据包的变量名。它看起来很好,但是我收到了它的CRC错误代码,所以一定是错的。
这里我从发送包的地址开始检查以十六进制形式的9个字节:
x/9bx 0x7fffffffdee0
0xfc 0x01 0x00 0x08 0x00 0x05 0x42 0x59 0xfd
这里问题变得明显了。 CRC不是LSB优先。 (0x42 0x59)
为了解决我的问题,我删除了我设置CRC值等于。
的htons()以上是没有htons()的相同输出:
p/x reqId_ep
$1 = {start_flag = 0xfc, data = {packet_num = 0x1, command = {0x0, 0x8}, payload = {
0x0, 0x5}}, crc = 0x4259, end_flag = 0xfd}
这里CRC值不是LSB。
但是:
x/9bx 0x7fffffffdee0
0xfc 0x01 0x00 0x08 0x00 0x05 0x59 0x42 0xfd
这里CRC值首先是LSB。
显然,C的存储首先是LSB?对于这种情况,有人可以向我提供一些知识吗?非常感谢你。
答案 0 :(得分:4)
这与计算中的Endianness有关: http://en.wikipedia.org/wiki/Endianness#Endianness_and_operating_systems_on_architectures
例如,值4660(十进制)是十六进制的0x1234。在Big Endian系统上,它将作为1234
存储在内存中,而在Little Endian系统上,它将存储为3412
如果你想在将来避免这类问题,最简单的方法是创建一个大型数组或unsigned char结构,并在其中存储单个值。
例如:
|Start Flag| Packet Num | Command | Payload | CRC | End Flag|
0xfc 0x1 0x0 0x8 0x0 0x5 0x59 0x42 0xfd
typedef struct packet {
unsigned char startFlag;
unsigned char packetNum;
unsigned char commandMSB;
unsigned char commandLSB;
unsigned char payloadMSB;
unsigned char payloadLSB;
unsigned char crcMSB;
unsigned char crcLSB;
unsigned char endFlag;
} packet_t;
然后,您可以创建一个函数,根据您使用预处理器宏构建的系统类型进行不同的编译。
例如:
/* Uncomment the line below if you are using a little endian system;
/* otherwise, leave it commented
*/
//#define LITTLE_ENDIAN_SYSTEM
// Function protocol
void writeCommand(int cmd);
//Function definition
void writeCommand(int cmd, packet_t* pkt)
{
if(!pkt)
{
printf("Error, invalid pointer!");
return;
}
#if LITTLE_ENDIAN_SYSTEM
pkt->commandMSB = (cmd && 0xFF00) >> 8;
pkt->commandLSB = (cmd && 0x00FF);
# else // Big Endian system
pkt->commandMSB = (cmd && 0x00FF);
pkt->commandLSB = (cmd && 0xFF00) >> 8;
#endif
// Done
}
int main void()
{
packet_t myPacket = {0}; //Initialize so it is zeroed out
writeCommand(0x1234,&myPacket);
return 0;
}
最后一点说明:避免将结构作为数据流发送,而是一次一个地发送它的各个元素! ie:不要假设结构在这种情况下是内部存储的,就像一个巨大的无符号字符数组。编译器和系统有些东西就像打包和分配一样,结构实际上可能大于9 x sizeof(unsigned char)
。
答案 1 :(得分:1)
这取决于架构,取决于您要定位的处理器。有一种所谓的“Big Endian”系统,它首先存储一个字的最高有效字节,而“Little Endian”系统首先存储最低有效字节。看起来你正在看那里的Little Endian系统。