; Test 1: Board kennenlernen, Ausgabe an die Leuchtdioden. ; Was es hier zu lernen gibt: ; - Einen Ausgabe-Port ansteuern (Port B mit den LEDs) ; - Aus welchen Teilen ein Programm besteht. ; Von mir verwendete Konventionen: ; - Gross geschriebene Woerter kennzeichnen vordefinierte Befehlsworte ; oder mit dem Prozessortyp vordefinierte Ports. ; - Klein geschriebene Worte sind von mir definiert und willkuerlich ; gewaehlt. ; Prozessor definieren ; .NOLIST .INCLUDE "8515def.inc" .LIST ; Die Befehle NOLIST und LIST schalten das Auflisten der INCLUDE-Datei ; in der Datei TEST1.LST aus. ; Register definieren ; ; Dieses Register wird fuer die Zwischenspeicherung der Zahlen ; verwendet. Mit dem Befehl .DEF kriegt eins der 32 8-Bit-Register ; einen Namen (hier: mp), den man sich einfacher merken kann als ; R16. Ausserdem kann man einfacher Register verlegen, wenn man sie ; ueber einen Namen anspricht. .DEF mp = R16 ; Restart ; ; Bis jetzt war alles Vorgeplaenkel. Hier beginnt nun das Programm. ; mit dem Reset- und Interrupt-Sprung-Teil. Dieser Teil ; produziert die ersten Programm-Bytes an der Adresse 0000 und ; folgende. ; Vorerst besteht dieser Teil nur aus einem Sprungbefehl in das ; Hauptprogramm. Dieser Befehl wird bei jedem Neustart des Pro- ; zessors ausgefuehrt. Ein Neustart wird bei Power-On, bei einem ; Hardware-Reset am Reset-Pin oder durch den Watchdog-Timer ; ausgeloest. Der Watchdog ist in diesem Programm nicht aktiv. ; In allen Faellen wird ein Sprung zum Programm mit dem Namen ; "main" ausgefuehrt. ; RJMP heisst "Relative Jump" oder relativer Sprung. Bei dem rela- ; tiven Sprung wird in dem Befehlswort eine relative Distanz mit ; angegeben, die der Assembler aus der Differenz zwischen der Adresse ; des Ziels (main) und der aktuellen Adresse ausrechnet. Die Sprung- ; Distanz darf 2 kB vorwaerts oder rueckwaerts nicht ueberschreiten und ; es gibt Fehlermeldungen. rjmp main ; Hier beginnt das Hauptprogramm mit dem Namen "main". Als erstes ; muss deshalb ein sogenanntes Label gesetzt werden. Ein Label ist ; ein frei definierter Name, gefolgt von einem Doppelpunkt. Zur ; besseren Uebersicht beginnen alle Label in Spalte 1 einer Zeile, ; alle Programmbefehle jedoch mit einem oder mehr Leerzeichen oder TAB. ; Hinter dem Label kann schon ein Programmbefehl stehen, getrennt ; mittels Leerzeichen oder TAB. Habe ich aber hier nicht gemacht. main: ; Als erstes muss der Port B, an den die LEDs angeschlossen sind, als ; Ausgang definiert werden. Dies macht man, indem man acht Einsen in ; das Datenrichtungs-Register des Ports B schreibt. Das Datenrichtungs- ; Register von Port B heisst DDRB (Data Direction Register B). Das er- ; fordert zwei Schritte: Erstens wird der Binaerwert 1111.1111 in ein ; Register geschrieben: ldi mp,0b11111111 ; Der Befehl LDI (LoaD Immediate) laedt einen 8-Bit-Wert in das Register ; mp. Dieser Befehl ist nur fuer die Register R16 bis R31 zulaessig, des- ; halb ist mp am Programmanfang als Register R16 definiert worden. Die ; Befehle mit zwei Parametern sind durchgaengig so aufgebaut, dass der ; erste Parameter (Register mp) immer das Ziel angibt, in dem das Ergeb- ; nis gespeichert wird. Nach der Durchfuehrung dieses Befehls enthaelt ; das Register 16 den Binaerwert 11111111, hexadezimal FF oder dezimal ; 255. ; Die Schreibweise "0b..." kennzeichnet immer eine Binaerzahl, mit "0x..." ; wird eine Hexadezimalzahl angegeben. Die fuehrende Null laesst den ; Assembler eine gueltige Zahl erwarten. Zahlen ohne diesen Vorsatz sind ; automatisch dezimal ( LDI mp,255 waere gleichwertig). ; Dieser Wert muss jetzt in das Datenrichtungs-Register gegeben ; werden, damit der Port B in ganzer Breite zu Ausgaengen wird. Eine 1 ; im Datenrichtungsregister macht den zugehoerigen Pin zum Ausgang, eine ; 0 zum Eingang. out DDRB,mp ; Der Befehl OUT schreibt Registerinhalte (hier: mp oder R16) auf einen ; Port (hier DDRB). DDRB ist in der Datei "8515def.inc" definiert, die ; ueber den .DEVICE-Befehl oder wie hier ueber den .INCLUDE-Befehl in den ; Assembler-Text eingebunden ist. Dadurch muss man sich die Portnummer ; des Datenrichtungsregisters nicht merken. ; Dieser Programmteil gibt nun abwechselnd Nullen und Einsen auf die ; Portausgaenge aus. Die LEDs leuchten in einem sehr schnellen Takt. ; Da dieser Programmteil unendlich lang wiederholt ist, kriegt er das ; Label loop, da nach dem Klappern der Bits wieder dorthin gesprungen ; werden muss. loop: ldi mp,0x00 out PORTB,mp ; LDI laedt erst mal acht Bits Nullen in das Universalregister mp. ; OUT gibt diese Nullen auf dem Port B aus. Diesmal kommen sie in das ; Datenausgaberegister von Port B (PORTB). ; Die Nullen lassen die LEDs leuchten, da sie ueber 1 k an die Versor- ; gungsspannung gefuehrt sind (0=an, 1=aus). ldi mp,0xFF out PORTB,mp ; Anschliessend kommen acht Einsen in das Register und von da aus in ; den Datenausgabe-Port. Das macht die Laempchen wieder aus. rjmp loop ; Mit diesem relativen Sprung geht es wieder zurueck an den Anfang der ; Schleife, und das Ganze dauert ewiglich. ; Bei 4 MHz Quarzfrequenz dauert jeder LDI- und OUT-Befehl in der Schleife ; 250 ns, der RJMP braucht zwei Takte und dauert 500 ns. Macht zusammen ; 1500 ns, die LEDs werden folglich mit 667 kHz angesteuert. ; ; Nach dem Assemblieren sollte das Programm acht Worte haben. In der ; Datei TEST1.LST kann man sich das Ergebnis der Assemblierung an- ; schauen. ; Dieses war der erste Streich ...