用于从H / W寄存器读取的位字段
我想从32位寄存器读取第2,第5和第6位。 我决定使用struct位字段来存储它们。 以下数据结构是否正确?
struct readData { int unwanted:1; int reqbit1:1; int unwanted1:2; int reqbit2:2; int unwanted2:26; };
我不确定如何创建位字段。 我将使用一个API,它将字节从h / w寄存器直接复制到此结构。 在那种情况下,reqbit1会包含第二位吗? 根据我的理解,编译器将第一位分配给一个int变量,第二位分配给另一个int变量,因此reqbit1将不会从寄存器中读取任何数据。 以下联盟不适合这种情况吗?
union readData { struct readBits{ bool unwanted:1; bool reqbit1:1; xxx unwanted1:2; short reqbit2:2; xxx unwanted2:26; }; int regValue; };
如果这是对的,我应该将不想要的2声明为什么?
根据C标准:“单位内的位域分配顺序(从高阶到低阶或从低阶到高阶)是实现定义的。”
所以你不应该使用秩序重要的位域。
使用显式屏蔽和转换:
reqbit1 = (w >> 1) & 1; reqbit2 = (w >> 4) & 3;
要么
reqbit1 = (w & 0x00000002) >> 1; reqbit2 = (w & 0x00000010) >> 4;
而另一个方向
w = (reqbit1 << 1) | (reqbit2 << 4);
“不需要的”部分通常被命名为reserved1
,依此类推。
通常使用以下联合:
union readData { struct { unsigned int unwanted:1; unsigned int reqbit1:1; unsigned int unwanted1:2; unsigned int reqbit2:2; unsigned int unwanted2:26; } readBits; unsigned int regValue; };
编辑:
用法是:
#define REG_ADDRESS 0x12345678 // eg union readData* rd = (union readData*)REG_ADDRESS; char bit2 = rd->readBits.reqbit1; char bits56 = rd->readBits.reqbit2;
为什么不使用sizeof()
并检查分配给每个struct成员的字节数? 结构成员对齐可以在这里找到
为什么要将h / w寄存器复制到结构中然后处理结构位? 可能存在使用新值更新h / w寄存器但结构仍未更新的情况。
如果要读取第2位,第5位和第6位,可以通过以下方式实现:
#define myregister ((unsigned long*)address of register) unsigned long ret=0; ret = myregister & (1<<2); if(ret) { ... } ret = myregister & (1<<5); if(ret) { ... } //... and so on
恕我直言,亲吻(保持简单,愚蠢)。