Arduino Mikrocontroller Tutorials - Softwaretechnik

Arbeiten mit einzelnen Bits

Die wichtigsten Themen um mit Bit und Bytes zu arbeiten sind hier zusammengefasst. Arbeiten auf Bit-Ebene ist notwendig um mit Registern zur arbeiten oder um Datenströme zu senden oder zu empfangen.

Bitvergleiche

UND (&) - Selektives Abfragen von Bits (maskieren) / Selektives Löschen von Bits

Der Bitoperator UND prüft, ob die beiden Operanden '1' sind. Ist das der Fall, dann ist das Ergebnis '1', sonst '0'.

0 & 0 = 0 1 & 0 = 0 0 & 1 = 0 1 & 1 = 1

Der Bitoperator UND wird oft benutzt um Bitwerte zu maskieren. Im Folgenden Beispiel soll nur die Stelle 2, 4, 6 und 8 übernommen werden. Der anderen Stellen bleiben unabhängig der vorherigen Werte auf '0'.

10011100 & 01010101 ---------- = 00010100

ODER (|)- Selektives Setzen von Bits

Der Bitoperator ODER prüft, ob mindestens einer der beiden Operanden '1' ist. Wenn ja, dann ist das Ergebnis '1', sonst '0'.

0 | 0 = 0 1 | 0 = 1 0 | 1 = 1 1 | 1 = 1

OR wird oft verwendet, wenn man sicher gehen will, dass ein bestimmtes Bit unabhängig vom aktuellen Status auf '1' gesetzt wird. Hier sollen die Stellen 0 und 1 auf '1' gesetzt werden.

10011000 & 01000011 ---------- = 01011011

XOR (^) - Selektives invertieren von Bits (toggeln)

Der Bitoperator XOR prüft, ob genau einer der beiden Operanden '1' ist. Wenn ja, ist das Ergebnis '1', sonst '0'. Im Gegensatz zum ODER liefert dieser Operator also auch dann '0', wenn beide Operanden '1' sind.

0 ^ 0 = 0 1 ^ 0 = 1 0 ^ 1 = 1 1 ^ 1 = 0

Der XOR Operator wird benutzt um bestimmte Stellen zu "toggeln" während andere so wie sie sind belassen werden. Hier im Beispiel werden die Stellen 0 und 1 getoggelt.

10011110 ^ 00000011 ---------- = 10011101

NICHT (~)

Der Bitoperator NICHT hat nur einen Operanden. NICHT kehrt den Wert um, aus '1' wird also '0' und umgekehrt.

~0 = 1 ~1 = 0

Beispiel:

~ 10011100 ---------- = 00100011

Bitschiebeoperator (Shiftoperator)

Beim Arduino bzw. in C++ gibt es zwei Schiebeoperatoren. LeftShift (<<) und RightShift (>>). Diese Operatoren bewirken, dass die Bits im linken Parameter um die Anzahl der Bits im rechten Parameter nach rechts oder links geschoben werden. (Gedanklich wird die Anzahl Nullen von links oder rechts eingeschoben).

byte a = 5; // binary: 00000101 byte b = a << 5; // binary: 10100000 byte c = b >> 3; // binary: 00010100

Fallen durch das Einschieben von Nullen auf der Gegenüberliegenden Seite die Daten heraus, sind diese unwiederbringlich verloren. Aufpassen muss man auch bei "signed Int" oder "signed long" Variablen. Diese Daten werden speziell gespeichert. Beispiel 4 = 00000100 und -4 = 11111100. (Negative Zahlen werden als Zweierkomplement gespeichert. Die positive Zahl wird invertiert und anschließend um 1 erhöht). Sobald dabei die erste Stelle eine '1' ist funktioniert das schieben nicht mehr wie erwartet. Daher am Besten für Bit Operationen zunächst in einen unsigned Wert umwandeln.

int a = -5; // binary: 1111111111111011 int b = x >> 2; // binary: 1111111111111110 int c = (unsigned int)x >> 4; // binary: 000011111111111110

Hinweis: Eine Verschiebung um x Stellen nach links entspricht dabei einer Multiplikation mit 2x. Eine Verschiebung um x Stellen nach rechts entspricht einer Division durch 2x (Bsp. 1 << 8 = 28 = 256 ).

Funktionen um Bits und Bytes

Ein Byte besteht aus 8 Bit. Die Position eines Bit innerhalb eines Bytes wird von rechts nach links gezählt und beginnt mit der Position 0 ganz rechts.
Zwei Bytes zusammen ergeben ein Word. Das Highbyte steht dabei links, das Lowbyte rechts.

lowByte(vonZahl)

Ermittelt das niederwertige Byte einer längeren Variablen

int a = 0b111111110000000; byte b = lowByte(a); // binary: 0000000

highByte(vonZahl)

Ermittelt den höherwertigen Byte eines Word, oder den zweitniedrigsten eines noch größeren Datentyps.

int a = 0b111111110000000; byte b = highByte(a); // binary: 11111111

word (highByte, lowByte)

Setzt 2 einzelne Bytes zu einem gemeinsamen Word mit 16 Bits zusammen.

byte hb = 0b11111111; byte lb = 0b11000011; word = word(hb,lb); // binary: 1111111111000011

bitRead(vonZahl, stelleVonRechts)

Liest ein bestimmtes Bit einer Zahl an einer bestimmten Stelle. Beginnend ganz rechts mit der Stelle 0. Der Rückgabewert ist entweder 0 oder 1.

byte a = 0b00011110; bool b = bitRead(a,2); // 1

bitWrite(inZahl, stelleVonRechts, Wert)

Schreibt ein bestimmtes Bit (Wert 0 oder 1) an eine bestimmten Stelle in einer numerischen Variable (also keine Strings). Die zu ändernden Stelle wird von rechts beginnend mit 0 gezählt.

byte a = 0b00011110; bitWrite(a,2,0); // binary: 00011010

bitSet(inZahl,stelleVonRechts) und bitClear(inZahl,stelleVonRechts)

bitSet() setzt an eine bestimmte Stelle einer Zahl eine 1.
bitClear() löscht eine bestimmten Stelle einer Zahl (schreibt eine 0)
Die zu ändernden Stelle wird von rechts beginnend mit 0 gezählt.

byte a = 0b01000110; b = bitClear(a,1); // binary: 01000100 c = bitSet(a,4); // binary: 01000110

bit(stelleVonRechts)

Ermittelt den Wert eines bestimmten Bits. Die entsprechende Stelle wird von rechts beginnend mit 0 gezählt.

a = bit(0); // 1 b = bit(4); // 16 b = bit(7); // 128

Binärzahlen Aus- und Eingeben

Eingabe von Binärwerten

Mit dem Prefix 0b kann man Zahlen binär eingeben (z.B. 0b0011110001010100).
Mit dem Prefix 0x werden sie hexadezimal angegeben(z.B. FF).
Binäre Werte bis zu der Größe von einem Byte lassen sich auch als Konstanten in Großbuchstaben eingen (z.B. B00000101)

Ausgabe als String() oder auf dem seriellen Monitor

Zahlen sind als Variablen immer Binär gespeichert. Man kann diese Werte aber unterschiedlich anzeigen lassen.

Serial.print(75); // "75" (Standardeinstellung) Serial.print(75, DEC); // "75" (75 in dezimal) Serial.print(75, HEX); // "4B" (75 in hexadezimal) Serial.print(75, BIN); // "1001011" (75 in Binärcode)

Ausgabe Binärwerte mit einer for-Schleife

Byte mit 8 Stellen ausgeben

void byteOut (byte wert) { Serial.print("Binärwert: "); for (int i = 7; i >= 0; i--) { if (bitRead(wert, i)) Serial.print("1"); else Serial.print("0"); } Serial.println(); }

Int mit 16 Stellen ausgeben

void intOut (unsigned int wert) { Serial.print("Binärwert: "); for (int i = 15; i >= 0; i--) { if ( i == 7) Serial.print(" "); if (bitRead(wert, i)) Serial.print("1"); else Serial.print("0"); } Serial.println(); }