2013-07-09 3 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; 
}; 

비트 필드가 어떻게 생성되는지 잘 모르겠습니다. h/w 레지스터의 바이트를이 구조체에 직접 복사하는 API를 사용할 것입니다. 이 경우 reqbit1에는 2 번째 비트가 포함됩니까? 내 이해에 따라 컴파일러는 첫 번째 비트를 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는 무엇으로 선언해야합니까?

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

및 "원치 않는"부분은 일반적으로 등 reserved1 선정되어

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

다른 방향에 대한

.

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 레지스터의 첫 번째 유형은 대개'부호없는 정수 '이므로 비트 필드에이 유형을 사용하는 것을 선호합니다. 두 번째, 편집을 참조하십시오 (답변을 코멘트에 맞지 않습니다) – Alex

+0

내 질문은 내 구조체 readData 잘못된 무엇입니까? – linuxfreak

1

sizeof()를 사용에 alloted 바이트 수를 확인 구조체 멤버 각각? 구조체 부재 alignment can be found out here

왜 구조로 레지스터 W/H 을 복사 한 다음 구조 비트 작업? 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 

IMHO, 키스 (바보, 간단하게).

+0

물론 이것은 가장 간단한 해결책입니다. – Alex

+0

@ D.7 레지스터에서 직접 읽을 수 없습니다. 구조체를 레지스터 데이터로 채우는 API를 호출해야합니다. 내 질문은 내가 선언 한 구조인지 여부이다. struct readData는 비트를 올바르게 포함 할 것인가? – linuxfreak

+1

더 많은 자신감을 얻기 위해 '__attribute __ ((__ packed__))'를 사용할 수 있습니다. 그리고 네 합집합에서 'regValue'는 메모리에 4 바이트가 할당되면 int 유형이 될 수 있습니다. 그렇게하면 적어도 4 바이트 이상의 메모리를 최대로 할당 할 수 있습니다. 그렇지 않으면 오래 사용하십시오. – madD7