c - 将各个位分配给字节

标签 c bit-manipulation bitwise-operators unions spi

我需要在微 Controller 和另一个芯片之间进行 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

我尝试创建这个结构/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 而不会出现编译错误?
  • 您对更好的方法有何建议?

最佳答案

这似乎有效:

<小时/>
#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;
}

关于c - 将各个位分配给字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47110886/

相关文章:

使用 C unix 命令或 C 更改文件中的特定单词

c - 如何在 C 中为我的应用程序修复内存大小?

c - 位摆弄 : which bit is set?

c - 按位运算和移位

c - 如何在C中的字符串中为time_t分配内存

c - 夏令时开关问题

algorithm - 一种计算位奇偶校验的简单/按位方式

c++ - 如何在具有 8 位成员的队列中前进并将对组合成 16 位值

scala - 了解 | scala中的运算符

c - Ansi C 中的位设置和位移位