用于从H / W寄存器读取的位字段

时间:2013-07-09 06:24:50

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

我想从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;
};

如果这是对的,我应该将不想要的东西声明为什么?

3 个答案:

答案 0 :(得分:2)

通常使用以下联合:

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;

答案 1 :(得分:2)

为什么不使用sizeof()并检查分配给每个struct成员的字节数? 结构成员alignment can be found out here

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

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

答案 2 :(得分:2)

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

所以你不应该使用秩序很重要的位域。

使用显式屏蔽和转换:

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

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

和另一个方向

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

“不受欢迎”的部分通常被命名为reserved1,依此类推。