2013-07-09 85 views
2

我想從32位寄存器中讀取第2,第5和第6位。我決定使用結構位域來存儲它們。以下數據結構是否正確?用於從H/W寄存器中讀取的位域

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; 
}; 

如果這是正確的,我應該聲明unwanted2爲什麼?

+1

使用1位有符號位域通常是一個非常糟糕的主意。你可以存儲的值只有'-1'或'0',這只是令人困惑。使他們'無符號'。 – unwind

+0

@unwind如果我只是在我的結構中將所有int都更改爲unsigned int,是否可以?我不需要使用工會從註冊表中讀取嗎? – linuxfreak

回答

2

從C標準:「一個單元內的位域分配順序(從高階到低階或從低階到高階)是由實現定義的。」

所以你不應該使用位域的順序。

使用明確的掩模和代替移:

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

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

且用於另一方向

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

的 「不想要的」 份通常命名reserved1等。

1

,一般用於下列工會:

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; 
+0

這個聯盟和我已經聲明的結構之間有什麼區別?我可以將我的結構轉換爲一個int指針並從寄存器讀取值,對吧? – linuxfreak

+0

@linuxfreak第一種類型的寄存器通常是'unsigned integer',所以我更喜歡在位域中使用這種類型。第二,請參閱編輯(回答不適合評論) – Alex

+0

我的問題是我的結構struct readData有什麼問題? – linuxfreak

1

爲什麼不使用sizeof(),檢查獲分配到的字節數每個結構成員? 的結構成員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 

恕我直言,吻(保持簡單,愚蠢的)。

+0

當然,這是最簡單的解決方案。 – Alex

+0

@ D.7我無法直接從寄存器讀取數據。我必須調用一個用寄存器數據填充結構的API。我的問題是我是否已經宣佈過的結構。 struct readData將包含正確的位? – linuxfreak

+1

爲了獲得更多信心,可以使用'__attribute __((__ packed__))。 而在你的聯合中,如果在內存中分配了4個字節,'regValue'可以是int類型。這將確保在最大時分配至少4bytes的內存。否則使用long。 – madD7