Doch kommen wir zurück zum binären System. Wie berechnet man die Stellenwertigkeit? Das erfolgt nach folgender Formel:
Wie groß ist also die Wertigkeit des Bits an der Position 4? Dann wollen wir mal sehen:
Sehen wir uns jetzt die Variante an, die mithilfe der Register- beziehungsweise Bit-Manipulation realisiert wird. Um das gewünschte LED-Muster zu erzeugen, muss lediglich an den Stellen innerhalb des Bytes eine 1 stehen, an denen die LEDs leuchten sollen. Zum besseren optischen Verständnis habe ich hier anstelle der LED-Bar, wie sie auf dem Arduino Discoveryboard zum Einsatz kommt, richtige LEDs mit 5mm Durchmesser verwendet, was du natürlich ebenfalls machen kannst:
Der entsprechende Sketch-Code dazu sieht wie folgt aus:
void setup() { DDRB = 0b11111111; // PORT B komplett als OUTPUT PORTB = 0b00010101; // Erzeugung des LED-Musters } void loop() { /* leer */ }
Wir sehen, dass die Zeile mit der verwendeten Bit-Kombination
PORTB = 0b00010101;
genau dem LED-Muster entspricht. Natürlich muss bei der Initialisierung keine Binärzahl verwendet werden. Es funktioniert auch mit einer Ganzzahl. Machen wir ein kleines Experiment und lassen uns ein paar Bit-Kombinationen von 0 bis 63 anzeigen. Dazu muss lediglich ein Wert immer um 1 inkrementiert – also erhöht werden. Diesmal muss sich aber ein Teil des Codes innerhalb der loop -Funktion befinden, denn es soll ja in regelmäßigen Zeitabständen eine Änderung bewirkt werden:
byte pattern = 0; void setup() { DDRB = 0b11111111; // PORT B komplett als OUTPUT } void loop() { PORTB = pattern++; // Inkrementieren von pattern delay(100); // Kurze Pause von 100ms }
Die Variable pattern ist vom Datentyp byte und hat somit acht Bits und kann Werte von 0 bis 255 speichern. Wenn wir sie innerhalb der loop -Funktion inkrementieren, dann wird irgendwann einmal ein sogenannter Überlauf erfolgen, wenn der Inhalt der Variablen 255 beträgt und anschließend noch einmal der Wert 1 addiert wird. Das funktioniert natürlich nicht, denn das Fassungsvermögen ist erschöpft. Es erfolgt der genannte Überlauf und das Spiel beginnt bei 0 von vorn. Mit folgender Zeile erfolgt das Inkrementieren der Variablen, wobei der Inkrement-Operator , der durch die beiden Pluszeichen repräsentiert wird, die Aufgabe des Hochzählens übernimmt:
PORTB = pattern++;
Man hätte das Gleiche auch mit den folgenden Zeilen erreicht:
pattern = pattern + 1; PORTB = pattern;
Das ist natürlich Geschmackssache, aber Programmierer lieben es, Dinge zu verkürzen und so wenig Code wie möglich zu formulieren.
Kommen wir nun zu einem sehr interessanten Teil: der Bit-Manipulation . Es ist möglich, die Bits über geeignete Operatoren vielfaltig zu manipulieren, was jedoch ein wenig Übung erfordert. Aber wenn man sich diese Art der Programmierung erst einmal erschlossen ist, dann macht es richtig Spaß, die Bits in jeglicher Weise zu verbiegen. Da das Thema dieses Bastelprojektes ja ein Lauflicht ist (was später noch etwas anders als hier realisiert wird), wollen wir doch einmal sehen, wie es möglich ist, eine einzelne LED »wandern« zu lassen. Wir nutzen dazu die sogenannten Bit-Operatoren .
Damit eine einzelne LED von einem Bit zum anderen geschoben wird, nutzen wir einen der folgenden Schiebeoperatoren:
>> Bedeutet nach rechts schieben.
<<��� Bedeutet nach links schieben.
Wie soll das funktionieren? Sehen wir uns dazu die folgenden Inhalte von PORT B und was mit ihnen im Laufe der Zeit passiert:
Abb. 9:Die Inhalte von Register PORT B zu unterschiedlichen Zeiten
Man kann sehen, dass die 1 rechts außen schrittweise nach links wandert. Der kleine rote Punkt markiert die Endposition zur angegebenen Zeit. Wie können wir aber diese 1 von rechts nach links schieben? Der angesprochene Schiebeoperator für das nach links Schieben wird uns gute Dienste leisten. Wir gehen davon aus, dass die 1 auf der rechten Außenposition, die – wir erinnern uns – LSB (Least Significant Bit) genannt wird und das Bit mit dem niedrigsten Wert kennzeichnet, immer als Ausgangsposition für alle Schiebeoperationen genommen wird. Der folgende Sketch-Code übernimmt diese Funktion des Schiebens:
byte pos = 0; // Positionswert void setup() { DDRB = 0b11111111; // PORT B komplett als OUTPUT } void loop() { PORTB = 1 << pos++; // Die 1 nach links schieben if(pos > 5) pos = 0; delay(500); // Kurze Pause von 500ms }
Die Variable tritt in der Funktion als Schiebeweitenangeber in Erscheinung. Zu Beginn hat sie den Wert 0, was bedeutet, dass beim ersten Schleifendurchlauf die 1 auf ihrer Position bleibt, wie das auch bei Zeitmarke t1 der Fall ist. Nach der Abarbeitung des Befehls wird die Variable pos um den Wert 1 erhöht, was wiederum bedeutet, dass beim nächsten Schleifendurchlauf eine Schiebeaktion nach links um eine Position bedeutet. Es muss jedoch darauf hingewiesen werden, dass durch das Schieben nach links auf der rechten Seite eine 0 eingeschoben wird. In gleicher Weise wird bei jedem erneuten Durchlauf verfahren. Ist der Wert von pos jedoch größer 5, was außerhalb unserer LED-Darstellungsmöglichkeit von sechs Bits liegt, wird er mithilfe der if -Anweisung und des nachfolgenden Befehls auf den Wert 0 zurückgesetzt und das Spiel beginnt von vorn.
Jetzt wollen wir einmal sehen, wie es möglich ist, einzelne Bits zu setzen, also mit dem Wert 1 zu versehen, ohne bestehende Bits in ihrem aktuellen Zustand zu beeinflussen. Schauen wir uns die folgende Situation an, wobei die gezeigte Bit-Kombination die Ausgangs-Bit-Maske (Folge von Bits) darstellt:
Die Aufgabe ist es jetzt, das Bit mit der Wertigkeit 8 an Position 3 zu setzen. Wir könnten den folgenden Sketch-Code schreiben, um diese Anforderung zu realisieren:
void setup() { DDRB = 0b11111111; // PORT B komplett als OUTPUT PORTB = 0b00000110; // Ausgangs Bit-Maske delay(500); PORTB = 1 << 3; // 3 Positionen nach links schieben } void loop() { /* leer */ }
Die Ausgangs-Bit-Maske, die 500ms lang zu sehen ist, sieht also wie folgt aus:
Im Anschluss soll dann die LED mit der Wertigkeit 8 zusätzlich zu den schon leuchtenden angehen. Doch was ist das Ergebnis? Schau mal:
Was ist schiefgelaufen? Nun, wir haben eine 1 rechts außen auf das LSB gesetzt und dann diese um 3 Positionen nach links geschoben. Wir erinnern uns, dass beim Schieben immer eine 0 an die vorherige Position eingeschoben wird. Für unser Vorhaben nicht so gut, denke ich. Was also tun? Die Lösung verbirgt sich hinter einem weiteren Operator, der aus der Kategorie der Bit-Operatoren entnommen wird. Es handelt sich um das binäre ODER . Dazu sollten wir uns jedoch die folgende Wertetabelle anschauen, damit wir erkennen, welche Auswirkungen dieser Operator hat:
Читать дальше