Das Dualsystem spielt in der Welt der Steuerungstechnik eine fundamentale Rolle. Daher ist es wichtig zu wissen, wie man mit Binären Zahlen und Logischen Operationen umgehen kann. Hier sollen die wesentlichen Bit-Operationen vorgestellt werden. Im Folgenden werden die Bit-Operatoren der Sprache C vorgestellt.
Logische Operationen
UND Verknüpfung
Die UND-Verknüpfung wird in C mit dem Operator & durchgeführt. Bei der bitweisen UND-Verknüpfung hat das Ergebnis an den Stellen eine 1, an denen beide Vergleichswerte eine 1 besitzen.
ODER Verknüpfung
Bei der bitweisen ODER-Verknüpfung hat das Ergebnis an den Stellen eine 1, an denen mindestens einer der beiden Vergleichswerte eine 1 besitzt. Das Operatorzeichen dafür ist das einfache Pipe-Zeichen |.
Exklusiv-Oder Verknüpfung
Bei der bitweisen XOR Verknüpfung hat das Ergebnis an den Stellen eine 1, an denen entweder der eine oder der andere Vergleichswert eine 1 besitzt. Das Operatorzeichen dafür ist das Dach-Zeichen ^.
NICHT Verknüpfung
Bei der bitweisen Negation wird jedes Bit umgekehrt: aus 0 wird 1 und aus 1 wird 0. Das Operator-Zeichen dafür ist die Tilde ~.
Beispiel-Programm
Im folgenden sollen die oben vorgestellten Verknüpfungen innerhalb eines Beispielprogramms umgesetzt werden:
int x = 5; // binary: 101 int y = x & 1; // now y == 1 x = 4; // binary: 100 y = x & 1; // now y == 0 y = x | 2; // now y == 110 int x = 12; // binary: 1100 int y = 10; // binary: 1010 int z = x ^ y; // binary: 0110, or decimal 6 int a = 103; // binary: 0000000001100111 int b = ~a; // binary: 1111111110011000 = -104
Schiebe-Operationen
Durch Verschieben, nach links mit << und nach rechts mit >>, wird ein Binärwert um eine bestimmte Anzahl von Bits nach links oder rechts verschoben. Die durch die Verschiebung freiwerdenden Stellen werden mit 0 gefüllt.
01101011 << 2 ergibt: 10101100 01101011 >> 4 ergibt: 00000110
Bit-Manipulation
In den folgenden Abschnitten wird gezeigt, wie man in einer Bitfolge gezielt einzelne Bits setzt, löscht oder umkehrt.
Setzen eines Bits
Um ein bestimmtes Bit innerhalb eines Bytes zu setzen kann man entweder eine Kombination aus einer Shift- und einer ODER-Operation verwenden oder den Maskierungsansatz verwenden.
Um das n-te Bit einer Variable A zu setzen wird folgende Formel verwendet:
Setzen von Bit 0: 0100 |= (1 << 0) ergibt: 0100 | 0001 ergibt: 01001 Setzen von Bit 3: 0100 |= (1 << 2) ergibt: 0100 | 0100 ergibt: 0100 (keine Veränderung)
Alternativ lässt sich ein Bit auch direkt über eine Maske setzen. Dazu verknüpft man den zu prüfenden Wert mit einer sogenannten Maske, in der genau das Bit (und nur das Bit) gesetzt ist, nach dem man setzen bzw. das man prüfen möchte. Der einzige Unterschied zur vorherigen Methode ist, dass die Maske manuell erstellt wird und nicht durch eine shift-Operation generiert wird.
Überprüfung ob ein BIT gesetzt ist
// Bit Operationen - Beispiel int Wert = 0b01001111; int Maske = 0b00001000; int Pin = 9; void setup() { Serial.begin(9600); pinMode(Pin,OUTPUT); // wenn Bit gesetzt leuchtet LED digitalWrite(Pin, (Wert & Maske) == Maske); if ( (Wert & Maske) == Maske) { Serial.println("Bit ist gesetzt"); } } void loop(){ }
Löschen eines Bits
Das Löschen eines Bits kann durch die Kombination aus einem Shift, dem Komplement und der UND-Verknüpfung realisiert werden. Auch hier besteht die Möglichkeit anstelle des Verschiebens wieder Manuell eine Bit-Maske zu erzeugen und einzusetzen. Um das n-te Bit in der Variable A zu löschen (von 0 an gezählt, also vom niederwertigsten Bit) wird folgender Ausdruck verwendet:
Beispiel wie das Bit 0 der Variable A gelöscht (auf LOW) gesetzt werden kann:
A = 65 ==> 1000001 A &= ~ (1 << 0) ==> 1001000 // lösche Bit 0
Togeln eines Bits
Das Wechseln eines Bits geschieht durch die Kombination der Shift-Funktion und der Exklusiv-ODER-Verknüpfung. Dabei wird das entsprechende Bit von 0 auf 1 oder von 1 auf 0 gesetzt. Um den Zustand des n-ten Bits in der Variable A zu wechseln (von 0 an gezählt) wird folgender Ausdruck verwendet:
byte A = 65; // ==> 1000001 Serial.println(A); // A=65 // toggle Bit 0 A = (A^=(1 << 0)); // ==> 1001000 Serial.println(A); // A=64
Bestimmung des Low-Bytes und High-Bytes
In verschiedenen Fällen benötigt man von einer 16-Bit-Variable die unteren 8-Bit und die oberen 8 Bit separiert. Hierzu können die oben beschriebenen Mechanismen verwendet werden:
word wert = 27543; byte high_byte = wert >> 8; // oder (wert & 0xff00) >> 8 byte low_byte = wert & 0x00ff;
Arduino Funktionen
Da die oben beschriebenen Bit-Manipulationen relativ häufig vorkommen, und nicht immer jederzeit von weniger geübten programmieren abgerufen werden können, haben sich die Entwickler entschlossen, die häufig benötigten Funktionen in den Sprach-Umfang zu integrieren:
Funktion | Erklärung |
---|---|
bit(n) | Berechnet den Wert des angegebenen Bits (Bit 0 ist 1, Bit 1 ist 2, Bit 2 ist 4, etc.). |
bitClear(var,n) | var : Die Zahlenvariable, deren Wert manipuliert werden soll.n : Bit gelöscht werden soll; Startet bei 0 für das least-significant (rechteste) Bit. |
bitRead(var,n) | Liest n-tes Bit aus der Variable var |
bitSet(var,n) | Setze Bit n in der Variable var |
highByte(var) | Liest das most-significant (linkeste) Bit eines Wortes (oder das zweitkleinste Bit eines größeren Datentypes). |
lowByte(var) | Liest das least-significant (rechteste) Bit eines Wortes oder größeren Datentypes. |
Weitere Details finden sich in der Arduino-Referenz Dokumentation.