0

シリアル通信プロトコルにフィードできる uint8_t の配列を生成できるように、比較的複雑なメッセージをユニオン構造にエンコードしようとしています。

ただし、共用体にデータが入力されたときに生成された配列を見ると、コマンド タイプ要素の後に余分な uint8_t 要素が表示されます。以下のユニオン構造を参照してください。

union myint16_t{
        uint16_t ui16;
        int16_t i16;
        uint8_t data[2];
    };

union {
    struct {
        uint8_t commandtype;
        myint16_t UpperLimits[4];
        myint16_t LowerLimits[4];
        myint16_t JointZeros[4];
        int8_t JointPolarity[4];
        myint16_t P[4];
        myint16_t I[4];
        myint16_t D[4];

    };
    uint8_t data[53];
};

ご覧のとおり、2 番目の無名共用体が共用体 myint16_t を参照しています。したがって、無名共用体のすべての値を入力し、基になる data[53] 配列を出力すると、2 番目の値 (data[1]) は 0 で、UpperLimits[4] の最初の要素の一部ではありません。ユニオンを埋めてから要素を出力するコードを見てください。

char q = 'c';



    hmmv4_configmsg msg;

msg.commandtype =(uint8_t) q;
msg.UpperLimits[0].ui16 = 784;
msg.UpperLimits[1].ui16  = 784;
msg.UpperLimits[2].ui16  = 784;
msg.UpperLimits[3].ui16  = 784;
msg.LowerLimits[0].ui16  = 223;
msg.LowerLimits[1].ui16  = 223;
msg.LowerLimits[2].ui16  = 223;
msg.LowerLimits[3].ui16  = 223;
msg.JointZeros[0].ui16  = 512;
msg.JointZeros[1].ui16  = 512;
msg.JointZeros[2].ui16  = 512;
msg.JointZeros[3].ui16  = 512;
msg.JointPolarity[0] = -1;
msg.JointPolarity[1] =-1;
msg.JointPolarity[2] =-1;
msg.JointPolarity[3] =-1;
msg.P[0].i16=4000;
msg.P[1].i16=4000;
msg.P[2].i16=4000;
msg.P[3].i16=4000;
msg.I[0].i16=1;
msg.I[1].i16=1;
msg.I[2].i16=1;
msg.I[3].i16=1;
msg.D[0].i16=24;
msg.D[1].i16=24;
msg.D[2].i16=24;
msg.D[3].i16=24;

//msg.change_endian();

while(1)
{
        for(int i =0; i<54; i++)
        {
            writebuf[i]=msg.data[i];

            printf("D: %d,  %d \n", i, msg.data[i]);
        }

        printf("L0: %d, %d, %d", msg.P[0].i16, msg.P[0].data[0], msg.P[0].data[1]);

        int r =jointencoder.xfer1(writebuf, readbuf, 54);
}

printf の出力は次のとおりです (問題の要素は D:1 です。存在しないはずです)。

D: 0,  99 
D: 1,  0 
D: 2,  16 
D: 3,  3 
D: 4,  16 
D: 5,  3 
D: 6,  16 
D: 7,  3 
D: 8,  16 
D: 9,  3 
D: 10,  223 
D: 11,  0 
D: 12,  223 
D: 13,  0 
D: 14,  223 
D: 15,  0 
D: 16,  223 
D: 17,  0 
D: 18,  0 
D: 19,  2 
D: 20,  0 
D: 21,  2 
D: 22,  0 
D: 23,  2 
D: 24,  0 
D: 25,  2 
D: 26,  255 
D: 27,  255 
D: 28,  255 
D: 29,  255 
D: 30,  160 
D: 31,  15 
D: 32,  160 
D: 33,  15 
D: 34,  160 
D: 35,  15 
D: 36,  160 
D: 37,  15 
D: 38,  1 
D: 39,  0 
D: 40,  1 
D: 41,  0 
D: 42,  1 
D: 43,  0 
D: 44,  1 
D: 45,  0 
D: 46,  24 
D: 47,  0 
D: 48,  24 
D: 49,  0 
D: 50,  24 
D: 51,  0 
D: 52,  24 
D: 53,  0 
L0: 4000, 160, 15joint encoder transferred 

私の質問は、なぜ D:1 があるのですか? ユニオンと構造についての私の理解では、コマンド タイプは uint8_t であるため、1 つのデータ スペースのみを占有する必要があり、したがって、UpperLimits[0] は D:1 で開始する必要がありますが、command_type は uint16_t として機能し、別のビットを投稿しているようです。 . これはなぜですか?

注: インデックスがカウント データ [53] に達していることがわかるかもしれませんが、これは範囲外である必要がありますが、これを読み取って送信し、相手側でデータを分解できるようにする必要があります。

4

2 に答える 2

0

ユニオンまたは構造体の要素を整列する方法をコンパイラに指示する必要があります。定義の前に #pragma pack(push,1) を追加して、隣接する要素を 1 バイト境界に揃えるようコンパイラーに指示し、#pragma pack(pop) を使用してコンパイラーのデフォルトの配置に戻します。パフォーマンス上の理由から、すべての構造体/共用体/クラスに 1 バイト アラインメントを使用したくないため、共用体の定義をプラグマ ペアでラップすることをお勧めします。

例:

#pragma pack(push,1)
union
{
uint_8 first;
uint_8 second;
} two_bytes;
#pragma pack(pop)

assert(sizeof two_bytes == 2);
于 2013-10-07T04:03:13.863 に答える
0

との間にはほぼ確実にパディング バイトがcommandtypeありUpperLimitsます。2 バイトmyint16_tデータ型は、偶数バイト境界に配置されます。

struct {
    uint8_t commandtype;
    myint16_t UpperLimits[4];
    ...

無名構造体と共用体のサイズを出力できれば、少なくとも 54 バイトであることがわかるでしょう (53 である必要があると思われる場所)。共用体の匿名メンバーとして埋め込まれたタグなしの構造体型の欠点の 1 つは、構造体のサイズを出力する簡単な方法がないことです。struct tag { uint8_t commandtype; ...サイズを印刷できるように、構造体にタグ ( ) を付けます。

現在のフレームワークを使用してそれを簡単に修正することはできません。

于 2013-10-07T03:38:45.867 に答える