; 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 Wörter kennzeichnen vordefinierte Befehlsworte ; oder mit dem Prozessortyp vordefinierte Ports. ; - Klein geschriebene Worte sind von mir definiert und willkürlich ; gewählt. ; Prozessor definieren ; .NOLIST .INCLUDE "C:\avrtools\appnotes\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 für 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 ; über einen Namen anspricht. .DEF mp = R16 ; Restart ; ; Bis jetzt war alles Vorgeplänkel. 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 ausgeführt. Ein Neustart wird bei Power-On, bei einem ; Hardware-Reset am Reset-Pin oder durch den Watchdog-Timer ; ausgelöst. Der Watchdog ist in diesem Programm nicht aktiv. ; In allen Fällen wird ein Sprung zum Programm mit dem Namen ; "main" ausgeführt. ; 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 vorwärts oder rückwärts nicht überschreiten 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 Übersicht 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 Binärwert 1111.1111 in ein ; Register geschrieben: ldi mp,0b11111111 ; Der Befehl LDI (LoaD Immediate) lädt einen 8-Bit-Wert in das Register ; mp. Dieser Befehl ist nur für die Register R16 bis R31 zulässig, des- ; halb ist mp am Programmanfang als Register R16 definiert worden. Die ; Befehle mit zwei Parametern sind durchgängig so aufgebaut, dass der ; erste Parameter (Register mp) immer das Ziel angibt, in dem das Ergeb- ; nis gespeichert wird. Nach der Durchführung dieses Befehls enthält ; das Register 16 den Binärwert 11111111, hexadezimal FF oder dezimal ; 255. ; Die Schreibweise "0b..." kennzeichnet immer eine Binärzahl, mit "0x..." ; wird eine Hexadezimalzahl angegeben. Die führende Null lässt den ; Assembler eine gültige Zahl erwarten. Zahlen ohne diesen Vorsatz sind ; automatisch dezimal ( LDI mp,255 wäre gleichwertig). ; Dieser Wert muss jetzt in das Datenrichtungs-Register gegeben ; werden, damit der Port B in ganzer Breite zu Ausgängen wird. Eine 1 ; im Datenrichtungsregister macht den zugehörigen 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 ; über den .DEVICE-Befehl oder wie hier über 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 ; Portausgänge 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 lädt 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 über 1 k an die Versor- ; gungsspannung geführt 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 Lämpchen wieder aus. rjmp loop ; Mit diesem relativen Sprung geht es wieder zurück 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 ...