2016-04-09 6 views
1

Ich habe ein 8-Bit-Register und ich möchte die Bits 4,5 und 6 ändern, ohne die anderen Bits zu ändern. Dieses Bit kann Werte von 000 bis 111 annehmen (unabhängig von ihrem vorherigen Zustand). Gibt es eine Methode, um sie in einem Schritt zu ändern oder muss ich sie einzeln ändern?Ändern von mehr als einem Bit in einem Register

Antwort

1

Sie benötigen eine Maske, die angeforderten Bits in einem Zustand bekannt zu setzen, 0 ist die bequemer als je meine Programmiergewohnheiten, legen Sie dann die Bits, die Sie mit einer oder Betrieb zu 1 und schreiben wollen zurück:

#define mask 0x70 // 01110000b bit 4, 5 & 6 set 
reg = (reg & ~mask) | (newVal & mask); 

Wir haben die invertierte Maske verwenden, um 0 die Bits zu setzen und die unveränderte Maske zu ändern setze auf 0 die Bits, die wir nicht wollen stört den neuen Wert.
Wenn Sie sicher sind, dass die unerwünschten Bits des neuen Wertes 0 sind immer können Sie vereinfachen:

#define mask 0x8f // 10001111b bit 4, 5 & 6 reset 
reg = (reg & mask) | newVal; //newVal must have always bits 7, 3, 2, 1 & 0 reset. 
+0

Ich sehe nicht, wie '0' ist bequemer als' 1' für den bekannten Zustand. Es ist nur eine Frage, ob Sie im nächsten Schritt die gewünschten Bits einschalten (mit einer '|' -Operation), oder die gewünschten Bits ausschalten (mit einer '&' -Operation). –

+0

@ JohnBollinger, halte ich die 0 bequemer, weil, um die gewünschten Bits zu setzen, wie Sie sagten, Sie brauchen nur ein 'oder' zwischen Werten, um sie zurückzusetzen, müssen Sie 'und' den Registerwert mit ** der invertierten ** eingegebener Wert. Sie benötigen 2 Operationen. –

+0

Nein, die Alternative kann genau so komplex sein wie Ihr Beispiel, und es ist nicht notwendig, die Eingabe zu invertieren: 'reg = (reg | mask) & (newVal | ~ mask)'. –

1

Sie können es tun, indem bitweise Operation, dh zuerst die 3 Bits löschen, und dann setzen sie:

unsigned char value = 0x70; 
unsigned char r = 0xFF; 
r = (r & 0x8F) | value; 
+0

Ich denke du meinst bitweise oder '|'? – Unimportant

+0

ah, in der Tat, ja, behoben, danke @ user1320881 – fluter

1

Sie bit-field innerhalb einer Struktur verwenden können:

typedef struct{ 
    unsigned char b0_3 : 4; 
    unsigned char b4_6 : 3; 
    unsigned char b7 : 1; 
}your_reg_type; 

your_reg_type my_register; 

//modify only the bits you need 
my_register.b4_6 = 0x02; 

Überprüfen Sie, wie Ihr Compiler Befehl, die Bits in der Struktur vor dem Versuch und order your bit-field accordingly

+0

Diese Antwort ist nicht (unbedingt) korrekt, da es in C keine Garantie gibt, dass das erste Bit Bit 7 ist. Es kann Bit 0 sein. – user3629249

+0

Deshalb habe ich gesagt "check out the endianess of the target ..." – simpego81

+0

Bei einem einzelnen Byte geht es nicht um Endianess, sondern um Compilerimplementierung. Tatsächlich ist es sogar für Multi-Bytes immer noch nicht eine Frage der Endianess - Endianess ist über die Byte-Reihenfolge nicht Bit-Reihenfolge. Der Compiler kann unabhängig von der Byte-Reihenfolge Bits von MSB oder LSB packen. Überprüfen Sie also die Dokumentation Ihres Compilers und nicht die Endlichkeit des Ziels. Beachten Sie, dass sich dies bei verschiedenen Compilern für dasselbe Ziel ändern kann. – Clifford

0

Eine Reihe von Lösungen und Variationen sind möglich (und wurden bereits vorgeschlagen), aber wenn der Wert der drei aufeinander folgenden Bits Bedeutung an sich hat (dh . es ist ein Wert von 0 bis 7 und nicht einfach eine Sammlung von unabhängigen Flag- oder Steuerbits), es kann nützlich sein, den Wert als einen einfachen numerischen Bereich von 0 bis 7 zu halten, anstatt direkt Details der Bitposition innerhalb des Wertes zu codieren. In diesem Fall:

 assert(val <= 7) ; // During debug (when NDEBUG not defined) the 
          // assert trap will catch out-of-range inputs 

    reg = (reg & mask) | (val << 4) ; 

Natürlich gibt es einige klein Kosten für die Vereinfachung der Schnittstelle auf diese Weise zu zahlen (durch einen Schichtbetrieb Zugabe), aber der Vorteil ist, dass das Wissen über die Einzelheiten der Registerfelds Layout auf einen Ort beschränkt.