4

我想从 32 位寄存器中读取第 2、第 5 和第 6 位。我决定使用 struct bit fields 来存储它们。下面的数据结构正确吗?

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 声明为什么?

4

3 回答 3

4

通常使用以下联合:

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 // e.g.

 union readData* rd = (union readData*)REG_ADDRESS;

 char bit2 = rd->readBits.reqbit1;
 char bits56 = rd->readBits.reqbit2;
于 2013-07-09T06:43:42.253 回答
2

为什么不使用sizeof()并检查分配给每个结构成员的字节数?结构成员 对齐可以在这里找到

为什么将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

恕我直言,亲吻(保持简单,愚蠢)。

于 2013-07-09T07:03:28.980 回答
2

来自 C 标准:“单元内位域的分配顺序(高位到低位或低位到高位)是实现定义的。”

所以你不应该在顺序重要的地方使用位域。

改用显式掩码和移位:

reqbit1 = (w >> 1) & 1;    
reqbit2 = (w >> 4) & 3;

或者

reqbit1 = (w & 0x00000002) >> 1;    
reqbit2 = (w & 0x00000010) >> 4;

和另一个方向

w = (reqbit1 << 1) | (reqbit2 << 4);

“不需要的”部分通常被命名reserved1,依此类推。

于 2013-07-10T19:42:43.887 回答