配列と構造体を共用体にしてエンディアンが逆さにならないようにするには?

こんばんは、NAKAといいます。

初心者あるあるで申し訳ないんですが、C言語を教えてください。

8バイト(DATA[0]~DATA[7])の送受信データをやり取りしてます。

配列データのDATA[0]=0x12,DATA[1]=0x34 から変数SPEED=0x1234というデータを作りたく、両者を共用したいので

struct
{
 union                                  
 {
  struct
  {
   unsigned short SPEED;
   unsigned short RPM;
   unsigned short NE;
   unsigned char SIG1;
   unsigned char SIG2;
  }SIG;
  unsigned char DATA[8];
 }BYTE; 
}TXRX;

配列と構造体を共用体として宣言しました。

配列に

    TXRX.BYTE.DATA[0] = 0x12;
    TXRX.BYTE.DATA[1] = 0x34;
    TXRX.BYTE.DATA[2] = 0x56;
    TXRX.BYTE.DATA[3] = 0x78;
    TXRX.BYTE.DATA[4] = 0x9A;
    TXRX.BYTE.DATA[5] = 0xBB;
    TXRX.BYTE.DATA[6] = 0xCC;
    TXRX.BYTE.DATA[7] = 0xDD;

ようにデータをいれたのですが、エンディアンが逆なので

のようにSPEED=0x1234 となってほしいのですが SPEED=0x3412となってしまいます。

当然

TXRX.BYTE.SIG.SPEED = 0x1234;

とするとDATA[0]に0x34、DATA[1]に0x12が入っちゃいます。

 

SPEED=0x1234と入るように作るにはどうすれば良いのでしょうか?

 

あぁ情けない!(T_T)

Parents
  • NAKAさん、こんにちは。NoMaYです。

    何かC言語でやり方があったような気がするけれども???と感じているのは、以下の別の話だったりしないでしょうか?(推測ですけど、、、) コンパイラの種類が書かれていなかったので、とりあえずCC-RXでプロジェクトを作って添付してみました。

    プロジェクトのファイル一式 (RX621 SIM、CS+プロジェクト(rcpeファイル同梱))
    issue_20190309.zip

    データのオフセット位置を構造体定義に任せる & 値を取り出すマクロ & 値を設定するマクロ

    #pragma pack

    struct TXRX_USVAL
    {
        unsigned    char    val_h;
        unsigned    char    val_l;
    };

    union
    {
        struct
        {
            struct      TXRX_USVAL  SPEED;
            struct      TXRX_USVAL  RPM;
            struct      TXRX_USVAL  NE;
            unsigned    char        SIG1;
            unsigned    char        SIG2;
        }SIG;
        /* とりあえず以下は残しておきました */
        struct
        {
            unsigned    char    DATA[8];
        }BYTE;
    }TXRX;

    #pragma packoption

    #define TXRX_GET_SPEED(txrx)\
        ((unsigned short)((txrx.SIG.SPEED.val_h << 8) | txrx.SIG.SPEED.val_l))

    #define TXRX_SET_SPEED(txrx, speed)\
        do{\
            txrx.SIG.SPEED.val_h = (unsigned char)(speed >> 8);\
            txrx.SIG.SPEED.val_l = (unsigned char)speed;\
        }while(0)

     

        debug_val = TXRX_GET_SPEED(TXRX);

        TXRX_SET_SPEED(TXRX, 0xABCD);


    [追記]

    もしRXマイコンだったとしたら、実行時間を1クロックでも削る必要がある場合には、CC-RXの組み込み関数であるrevw()をマクロ内で使う手もあります。(TXRX_USVALの定義も共用体へ変更します。)

    プロジェクトのファイル一式 (RX621 SIM、CS+プロジェクト(rcpeファイル同梱))
    issue_20190309B.zip

    union TXRX_USVAL
    {
        struct
        {
            unsigned    char    val_h;
            unsigned    char    val_l;
        }VAL;
        unsigned short val_ushort_internal_use_only;
    };

    union
    {
        struct
        {
            union       TXRX_USVAL  SPEED;
            union       TXRX_USVAL  RPM;
            union       TXRX_USVAL  NE;
            unsigned    char        SIG1;
            unsigned    char        SIG2;
        }SIG;
        /* とりあえず以下は残しておきました */
        struct
        {
            unsigned    char    DATA[8];
        }BYTE;
    }TXRX;

    #pragma packoption

    #define TXRX_GET_SPEED(txrx)\
        ((unsigned short)revw(txrx.SIG.SPEED.val_ushort_internal_use_only))

    #define TXRX_SET_SPEED(txrx, speed)\
        do{\
            txrx.SIG.SPEED.val_ushort_internal_use_only = ((unsigned short)revw(speed));\
        }while(0)

     

  • 皆さん、おはようございます&ありがとうございます、NAKAです。

    実は、
    通信はCANでch1バスで受けたID100のデータ一部をch2バスのID200の違う位置にビットアサインし
    流すみたいなことを簡単にやりたいと思いました。
    データはIDごと最大8バイトですが、IDごとに固定のバイト単位ではなく、中途半端な12bitが
    バイトをまたいで配置されていたり、スイッチなどは1bitが混じってたりします。
    しかもch1⇒ch2に渡す信号のデータbit数が変わるものもあります。(T_T)

    なので、ch1バス受信はIDごとの配列で受け、送信時IDごとに共用化された構造体の信号を、送信
    する構造体信号に入れ直し(複数)、ch2バスに入れ直した構造体と共用された配列で送信しようと
    考えました。
    今までは、普通にビットシフトしたりマスクかけたりしてやってましたが、NAKAはおっちょこちょい
    で時々凡ミスしちゃうため、信号名になっていたらミスが無くなるかな?と考えました。

    やっぱり結構複雑で構造体を作る時点で間違いを起こしそうですね!(*_*;

    一番、シンプルな方法をもう少し検討したいと思います。

    皆さん!本当にありがとうございました。_(._.)_

Reply
  • 皆さん、おはようございます&ありがとうございます、NAKAです。

    実は、
    通信はCANでch1バスで受けたID100のデータ一部をch2バスのID200の違う位置にビットアサインし
    流すみたいなことを簡単にやりたいと思いました。
    データはIDごと最大8バイトですが、IDごとに固定のバイト単位ではなく、中途半端な12bitが
    バイトをまたいで配置されていたり、スイッチなどは1bitが混じってたりします。
    しかもch1⇒ch2に渡す信号のデータbit数が変わるものもあります。(T_T)

    なので、ch1バス受信はIDごとの配列で受け、送信時IDごとに共用化された構造体の信号を、送信
    する構造体信号に入れ直し(複数)、ch2バスに入れ直した構造体と共用された配列で送信しようと
    考えました。
    今までは、普通にビットシフトしたりマスクかけたりしてやってましたが、NAKAはおっちょこちょい
    で時々凡ミスしちゃうため、信号名になっていたらミスが無くなるかな?と考えました。

    やっぱり結構複雑で構造体を作る時点で間違いを起こしそうですね!(*_*;

    一番、シンプルな方法をもう少し検討したいと思います。

    皆さん!本当にありがとうございました。_(._.)_

Children
No Data