Do. Apr 25th, 2024

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:

FunktionErklä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.
Vordefinierte Bit-Manipulations-Funktionen beim Arduino

Weitere Details finden sich in der Arduino-Referenz Dokumentation.