2017-11-04 4 views
0

私は、マイクロコントローラと別のチップとの間でSPI通信を行う必要があります。チップは16ビットワードを受け入れます。しかし、抽象ライブラリでは、データを2つの8ビットバイトとして送信する必要があります。今、私は読み書きのリクエストを簡単に作成できるようにラッパーを作っていきたいですが、まだ成功していません。以下のようになります。個々のビットをバイトに割り当てる

以下の表は16ビットを示しています。 MSBは、書き込みの場合は0、読み取りの場合は1になります。アドレスは0x0から0x7までで、データは11ビットです。例えば

R/W |  ADDRESS | DATA 
B15 |  B14-B11 | B10-B0 
0 |  0000 | 00000000000 
W0 | A3, A2, A1, A0 | D10, D9, D8, D7, D6, D5, D4, D3, D2, D1, D0 

私はレジスタ0x1から読みたい場合は、私は、このようなビットを設定することがあると思う:

W0 | A3, A2, A1, A0 | D10, D9, D8, D7, D6, D5, D4, D3, D2, D1, D0 
    1 | 0 0 0 1 | 0 0 0 0 0 0 0 0 0 0 0 

またはレジスタを0x7からの読み取りを:

W0 | A3, A2, A1, A0 | D10, D9, D8, D7, D6, D5, D4, D3, D2, D1, D0 
    1 | 0 1 1 1 | 0 0 0 0 0 0 0 0 0 0 0 

Iこの構造体/共用体を作成して、それが機能するかどうかを確認しようとしました:

typedef struct{ 
    uint8_t acc_mode:1; 
    uint8_t reg_addr:4; 
    uint8_t reg_data:8; //TODO fix me should be 11 
} DRVStruct; 

typedef union { 
    DRVStruct content; 
    uint16_t all; 
} DRVUnion; 

void DRV_PrepareReadMsg(uint8_t reg, uint8_t* msgBuffer) { 
    DRVUnion temp; 
    temp.content.acc_mode = 1; 
    temp.content.reg_addr = reg; 
    temp.content.reg_data = 0; //read mode does not need data! 

    msgBuffer[1] = temp.all & 0xFF; 
    msgBuffer[0] = temp.all >> 8; 
} 

私は奇妙な結果を得ています...時々私はSPIから答えを得ます(私はSPI通信はOKですが、メッセージを準備するための私のコードは問題です)。

だから、質問は以下のとおりです。私は正しいことかなアプローチを

  • やっているだろうか?
  • reg_dataのビット幅を8から11に増やしても、コンパイルエラーが発生することはありませんか?
  • あなたはより良いアプローチについて何をお勧めしますか?
+2

使用uint16_t、あなたは、11ビットにreg_data設定できないのですか? – perreal

+2

ビットフィールドを使用しない* * *をお勧めします。ビットフィールドの表現は*完全に*実装定義です。つまり、ビットの順序と、それらが基本となるデータにマップするものは、あなたの制御の範囲を超えています。また、2つの 'uint8_t'値の間でビットフィールドをオーバーラップさせる必要があります。何があっても、 'uint8_t reg_data:11;'は動作しません。 –

+0

私はあなたがなぜprototype構造体をuint16_tと組合わせるのか理解していません。 2つのuint8_tはマスキングとシフトを排除してより理にかなっています。実際に、これを行う場合、私はmsgBufferと組み合わされ、コンパイラから利用可能な 'pragma packed'を使用し、uint16_tをプロトコル構造体の基本型として使用して、11ビットフィールドを収容できるようにします。それは、ビット/バイトがどこにあるべきかを確認するために多くのデバッグを行い、非常に注意してください。 –

答えて

1

これは動作するようです:


#include <stdio.h> 
#include <stdint.h> 

typedef union { 
    struct{  // no struct tag, since it is not needed... 
     uint16_t acc_mode:1; 
     uint16_t reg_addr:4; 
     uint16_t reg_data:11; //TODO fix me should be 11 
     } bits; 
    uint16_t all; 
    uint8_t bytes[2]; //extra bonus when lit;-) 
     } DRVUnion; 

int main(void) 
{ 
DRVUnion uni,uni13[13]; 

printf("Size=%zu, %zu\n", sizeof uni, sizeof uni13); 
return 0; 
} 
+0

ありがとうこれは動作します...しかし、私は 'bytes'フィールドに1バイトを割り当てるときに、このようにしなければなりません:' instance.bytes [0] = data [1];インスタンス。bytes [1] = data [0] 'もし' all'フィールドに割り当てただけでは、期待通りに動作しません。 – DEKKER

+0

ホストとターゲットのエンディアンが異なるためです。 – wildplasser

関連する問題