10

int、char、および char の配列が混在する構造体のメンバーをバイト配列にコピーして、シリアル回線に送信しようとしています。これまでのところ、

struct msg_on_send
{
    char descriptor_msg[5];
    int  address;
    char space;
    char cmdmsg[5];
    char CR;
    char LF;
};

void switch_output_on()
{
    int member;
    struct msg_on_send SendMsg_on[sizeof member] =
     {

    };
    unsigned char buffer [ sizeof SendMsg_on[0] ];
    showbytes(buffer, serialize(buffer, SendMsg_on));
}

/*************************************************************************** 
*   Function:   ArrayBuild                                                 *
*   Purpose:    Uses memcopy to transfer the struct members sequentially   *
*               into an array of char                                      *
*   Arguments:                                                             *
*   Returns:    size_t i = a count of the number of bytes in the array     *
***************************************************************************/    

size_t ArrayBuild(unsigned char *dst, const struct msg_on_send *object)
{
    size_t i = 0;

    memcpy(&dst[i], &object->descriptor_msg, sizeof object->descriptor_msg);
    i += sizeof object->descriptor_msg;

    memcpy(&dst[i], &object->address, sizeof object->address);
    i += sizeof object->address;

    memcpy(&dst[i], &object->space, sizeof object->space);
    i += sizeof object->space;

    memcpy(&dst[i], &object->cmdmsg, sizeof object->cmdmsg);
    i += sizeof object->cmdmsg;

    memcpy(&dst[i], &object->CR, sizeof object->CR);
    i += sizeof object->CR;

    memcpy(&dst[i], &object->LF, sizeof object->LF);
    i += sizeof object->LF;

    return i;
}

/*********************************************************************** 
*   Function:   USARTWrite                                             *
*   Purpose:    Writes the array data to the USART data register       *
*   Arguments:  void *object = struct member                           *
*               size_t size =  size of array remaining                 *
*   Returns:    None                                                   *
***********************************************************************/

void USARTWrite(const void *object, size_t size)        
{
    const unsigned char *byte;
    for ( byte = object; size--; ++byte )
    {
        printf("%02X", *byte);
    }
    putchar('\n');
}

このコードを入手したので、それがどのように機能するかを完全には理解していません。memcpy が構造体の各要素を取得し、それを「i」変数によってインデックス付けされたシリアル ストリームにすることがわかりますが、USARTWrite 関数がこれをどのように文字列にパケット化するか、または配列を次のようにロードする方法はわかりません私の構造体の初期化。

申し訳ありませんが、この投稿は少し長くなりますが、私はこのプログラミングのひばりを始めたばかりで、この概念を理解しようとしています.

ありがとうデイブ

編集:

うわー、多くの良い答えがすぐに出ます - みんなありがとう。

slaz: それは私には論理的に思えます.私はまだポインタについて頭を悩ませていないので,そのアプローチについてはあまり考えていませんでしたが.見て。

  • このコード行はデータを UART に送信します。メッセージの内容を含む配列を何に置き換えますか? ここでは、構造の開始位置と大きさを示す変数があるが、送信する配列がないという論理的なステップが欠落しているようです

    USART_SendData(USART1, message_on_contents[array_count]);
    

ハーパー・シェルビー: その説明をありがとう。

rgds

デイブ

4

7 に答える 7

9

構造体を実際にバイトの配列にコピーする必要はありません。オプションでこれを行うことができます:

struct msg_on_send myMessage;

// code to set myMessage to whatever values...

// get a byte pointer that points to the beginning of the struct    
uint8_t *bytePtr = (uint8_t*)&myMessage;

// pass that into the write function, and it will write the amount of bytes passed in
USARTWrite(bytePtr, sizeof(myMessage));

ポインターの力!:)

于 2009-01-27T18:13:39.117 に答える
9

申し訳ありませんが、今まであなたのコメントを見ていませんでした。以下のコードは Linux で問題なくコンパイルできるので、うまくいくことを願っています。
printf() は 16 進数で出力します。各バイトに 2 文字が表示されます。

#include <stdio.h>

struct msg_on_send
{
char descriptor_msg[5];
int  address;
char space;
char cmdmsg[5];
char CR; 
char LF; 
};

void USARTWrite(const void *object, size_t size)    
{
    const unsigned char *byte;
      for ( byte = object; size--; ++byte )                                     
      {   
          printf("%02X", *byte);
      }   
      putchar('\n');
}

int main (int argc, char**argv)
{
    struct msg_on_send myMsg;
    unsigned char* ptr= (unsigned char*)&myMsg;

    USARTWrite(ptr, sizeof(myMsg));

    return 0;
}

これが役立つことを願っています。

~
~

于 2009-01-28T22:50:03.037 に答える
1

構造体をバイト配列として扱いたい場合は、通常、共用体を使用して構造体をバイト配列と結合します。例えば:

typedef union
{
    struct
    { 
        char descriptor_msg[5]; 
        int  address; 
        char space; 
        char cmdmsg[5]; 
        char CR; 
        char LF; 
    };
    BYTE bytes[];
} msg_on_send;
于 2010-02-08T18:56:07.820 に答える
1

それはかなり簡単です: 1. ArrayBuild は msg_on_send 構造体へのポインターを取り、そこにある各メンバーに対して memcpy を使用してバイトを char 配列にコピーします。

char byteArray[17]; // This assumes 4-byte ints
                    // be careful though, the length *must* be long enough, or 
                    // Bad Things will happen
size_t msgSize; // Holds the size of the message built by ArrayBuild,
                // passed to USARTWrite
struct msg_on_send myMessage;
// Code to fill up myMessage appropriately

msgSize = ArrayBuild(byteArray, &myMessage); // need the & to pass a pointer as required

USARTWrite(myMessage, msgSize);

USARTWrite には char 配列とサイズが与えられます。各 char を順番に取得し、printf() で 16 進値として画面に出力します。

「魔法」は ArrayBuild にあります - memcpy は変換なしでソースから宛先へのバイトのリテラルコピーを行います。4 バイトの int を想定すると、関数によって構築される配列は次のようになります。

                     1 1 1 1 1 1 1 
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
|   A     |   B   |C|    D    |E|F|

A = descriptor_msg (char[5])
B = address (int)
C = space (char)
D = cmdmsg (char[5])
E = CR (char)
F = LF (char)

「実際の」アプリケーションでは、printf() 呼び出しはシリアル ポート書き込みの呼び出しに置き換えられると思います。

于 2009-01-27T17:50:26.747 に答える
0

あなたのstructここは単なるバイト配列であり、それを指すポインターは含まれていません。

メンバー間のコピーは、アラインメントに対処するために実行さ(char*) &addressれる可能性が高く、 より大きくなる可能性があります((char*) &descriptor_msg) + 5

USARTWriteHEX構造体のバイトのコードを に送信しますが、stdoutアラインメントは破棄します。このコードをさまざまな配置戦略でコンパイルすると、さまざまな出力が得られます。

構造体宣言を囲み、#pragma pack(push, n)アラインメント#pragma pack(pop)を強制し、構造体をバイト単位でコピーするだけです。

于 2009-01-27T17:44:48.740 に答える