Mail to Code: Tutorial

Lernt, wie man den Code für Rechenknechte schreibt.

English version English Version

Lauflicht, kurzer Code

Programmieren mit PORTs, Registern und Bitmanipulation

Mit dem bislang gelernten über Ports und Bitmanipulation können wir den Code für ein Lauflicht aus 8 LEDs, das wir bereits in dem vorangegangenen Kapitel kennengelernt haben, deutlich kürzer schreiben. Lediglich 4 Codezeilen genügen:

1
2
3
4
5
6
7
8
9
void setup() {
  DDRA  = 0b11111111;
  PORTA = 0b00000001;
}
 
void loop() {
  PORTA = PORTA << 1 | PORTA >> 7;
  delay(100);
}
    

In Zeile 2 werden die 8 GPIOs von Port A (Pin Nummer 22-29) in den Modus für Ausgabe geschaltet:
I.   DDRA = 0b11111111;

In der folgenden Zeile wird Port A initialisiert. Dabei werden die LEDs an den Pins 23 bis 29 ausgeschaltet und lediglich die LED an Pin 22 wird eingeschaltet:
II.  PORTA = 0b00000001;


In der folgenden loop() Schleife wird das Licht mit einer einzelnen Zeile zum Laufen gebracht:
III. PORTA = PORTA << 1 | PORTA >> 7;

Diese Zeile wird von dem Kompiler allerdings in 3 Schritte unterteilt. Dabei werden automatisch Zwischenspeicher generiert, in welchen die Teilergebnisse abgelegt werden. Im ersten Schritt wird die Speicherzelle temp_variable_1 erstellt und in dieser der Wert gespeichert, der sich ergibt, wenn die Bits von PORTA um eine Stelle nach links verschoben werden. Wie im Kapitel zur Bitmanipulation erläutert, wird dabei das Bit ganz links verworfen und das Bit rechts mit "0" aufgefüllt:
(1)  temp_variable_1 = PORTA << 1;

Im zweiten Schritt wird die Speicherzelle temp_variable_2 erstellt und in dieser der Wert gespeichert, der sich ergibt, wenn die Bits von PORTA um sieben Stellen nach rechts verschoben werden. Dabei werden die 7 rechten Bits verworfen und das Bit ganz links um 7 Positionen nach ganz rechts verschoben. Die 7 linken Bits werden mit "0" aufgefüllt. Als Ergebnis dieser Operation wird also das höchstwertige Bit (ganz links) nach ganz rechts verschoben und alle anderen Bits werden auf "0" gesetzt:
(2)  temp_variable_1 = PORTA << 7;

Im dritten Schritt werden die temporären Speicherzellen temp_variable_1 und temp_variable_2 mit dem ODER Operator verknüpft und das Ergebnis dieser Operation wird wiederum dem Port A zugewiesen:
(3)   PORTA = temp_variable_1 | temp_variable_2;

Das Ergebnis dieser 3 Schritte ist ein Ringtausch aller Bits von Port A um eine Position nach links, wobei das Bit ganz links für das Auffüllen an der Stelle ganz rechts übernommen wird. Nach jeder Verschiebeoperation wird eine Pause von 100 Millisekunden eingelegt:
IV.  delay(100);



Port A nimmt die folgenden Werte an:
(1) PORTA = 0b00000001
(2) PORTA = 0b00000010
(3) PORTA = 0b00000100
(4) PORTA = 0b00001000
(5) PORTA = 0b00010000
(6) PORTA = 0b00100000
(7) PORTA = 0b01000000
(8) PORTA = 0b10000000

Nach Schritt (8) werden die Bits von Port A erneut um eine Position nach links verschoben und das Bit ganz links, das jetzt eine "1" ist, wird ganz nach rechts gesetzt. Damit ist die Ausgangsposition (1) wieder erreicht und der Prozess wiederholt sich.

Experimentiert mit dem Programm

Was ändert sich, wenn Port A in der Setup() Routine mit dem Wert PORTA=0b11111110 initialisiert wird?
Oder mit dem Wert PORTA = 0b00110000 oder einem beliebigen anderen Wert?





Du findest diese Seite klasse?

Gummibärchen als Nervennahrung beim Programmieren und der Betrieb dieses Servers verschlingen mein Geld.
Helft mit einer Motivationsspritze, dieses Projekt am Laufen zu halten.

Klick hier oder scan den QR Code, um eine Spende zu überweisen.



Vielen Dank!

Fragen? Anregungen? Fehler gefunden?
Kontakt per E-mail: question@h1i1.de