1

首先,我还是个学生。所以我不是很有经验。

我正在使用一个蓝牙硬件,我正在使用它的协议向它发送命令。该协议要求每个数据包字段首先发送具有 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?对于这种情况,有人可以向我投射知识吗?非常感谢你。

4

2 回答 2

4

这与计算中的字节序有关: 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;
}

最后一点:避免将结构作为数据流发送,而是一次发送一个单独的元素!即:不要假设结构在这种情况下是内部存储的,就像一个巨大的无符号字符数组。有些东西是编译器和系统放置的,比如打包和对齐,结构实际上可能大于9 x sizeof(unsigned char).

祝你好运!

于 2012-05-17T22:45:59.227 回答
1

这取决于您所针对的处理器的架构。有所谓的“Big Endian”系统,它首先存储一个字的最高有效字节,以及“Little Endian”系统,它首先存储最低有效字节。看起来您正在那里查看 Little Endian 系统。

于 2012-05-17T22:09:14.793 回答