1

First, I'm a student still. So I am not very experienced.

I'm working with a piece of bluetooth hardware and I am using its protocol to send it commands. The protocol requires packets to be sent with LSB first for each packet field.

I was getting error packets back to me indicating my CRC values were wrong so I did some investigating. I found the problem, but I became confused in the process.

Here is Some GDB output and other information elucidating my confusion.

I'm sending a packet that should look like this:

|Start Flag| Packet Num | Command | Payload |    CRC    | End Flag|
    0xfc        0x1       0x0 0x8   0x0 0x5   0x59 0x42    0xfd

Here is some GDB output:

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 is the variable name of the packet I'm sending. It looks all good there, but I am receiving the CRC error codes from it so something must be wrong.

Here I examine 9 bytes in hex starting from the address of my packet to send:

x/9bx 0x7fffffffdee0
0xfc    0x01    0x00    0x08    0x00    0x05    0x42    0x59    0xfd

And here the problem becomes apparent. The CRC is not LSB first. (0x42 0x59)

To fix my problem I removed the htons() that I set my CRC value equal with.

And here is the same output above without htons():

p/x reqId_ep

$1 = {start_flag = 0xfc, data = {packet_num = 0x1, command = {0x0, 0x8}, payload = {
  0x0, 0x5}}, crc = 0x4259, end_flag = 0xfd}

Here the CRC value is not LSB.

But then:

x/9bx 0x7fffffffdee0
0xfc    0x01    0x00    0x08    0x00    0x05    0x59    0x42    0xfd

Here the CRC value is LSB first.

So apparently the storing of C is LSB first? Can someone please cast a light of knowledge upon me for this situation? Thank you kindly.

4

2 に答える 2

4

これは、コンピューティングにおけるエンディアンと関係があります:http: //en.wikipedia.org/wiki/Endianness#Endianness_and_operating_systems_on_architectures

たとえば、値4660(base-ten)は16進数で0x1234です。ビッグエンディアンシステムでは、メモリに保存されますが1234、リトルエンディアンシステムでは、次のように保存されます。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;
}

最後の注意点:構造体をデータのストリームとして送信するのではなく、個々の要素を一度に1つずつ送信してください。つまり、この場合、構造体が符号なし文字の巨大な配列のように内部に格納されていると想定しないでください。パッキングやアラインメントのようにコンパイラーとシステムが配置するものがあり、構造体は実際にはより大きくなる可能性があり9 x sizeof(unsigned char)ます。

幸運を!

于 2012-05-17T22:45:59.227 に答える
1

これは、ターゲットとするプロセッサに基づいてアーキテクチャに依存します。単語の最上位バイトを最初に格納する「ビッグエンディアン」システムと、最下位バイトを最初に格納する「リトルエンディアン」システムと呼ばれるシステムがあります。そこにあるリトルエンディアンシステムを見ているようです。

于 2012-05-17T22:09:14.793 に答える