将各个位分配给字节

时间:2017-11-04 12:45:10

标签: c bit-manipulation bitwise-operators unions spi

我要在微控制器和另一个芯片之间进行SPI通信。该芯片接受16位字。但是抽象库要求将数据作为两个8位字节发送。现在我想制作一个包装器,这样我就可以轻松创建读写请求......但我还没有取得任何成功。这是它应该如何:

下表显示了16位。 MSB可以0用于写入,或1用于读取。地址可以是0x00x7,数据是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

我试图创建这个struct / union以查看它是否可以工作:

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通信没问题,但是我准备消息的代码是问题所在。)

所以问题是:

  • 我做得对吗?
  • 如何在不出现编译错误的情况下将reg_data的位宽从8增加到11?
  • 您对更好的方法有什么建议?

1 个答案:

答案 0 :(得分: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;
}