将单个位分配给字节
Assigning individual bits to bytes
我需要在微控制器和另一个芯片之间进行 SPI 通信。该芯片接受 16 位字。但是抽象库要求数据以两个 8 位字节的形式发送。现在我想做一个包装器,这样我就可以轻松地创建读写请求……但我还没有取得任何成功。它应该是这样的:
下面的table表示16bits。写入时 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
我已经尝试创建这个 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?
- 对于更好的方法,您有什么建议?
这似乎有效:
#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;
}
我需要在微控制器和另一个芯片之间进行 SPI 通信。该芯片接受 16 位字。但是抽象库要求数据以两个 8 位字节的形式发送。现在我想做一个包装器,这样我就可以轻松地创建读写请求……但我还没有取得任何成功。它应该是这样的:
下面的table表示16bits。写入时 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
我已经尝试创建这个 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? - 对于更好的方法,您有什么建议?
这似乎有效:
#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;
}