In einer ersten Übung wird ein sehr einfaches Assemblerprogramm geschrieben, das nur eine bestimmte LED auf der Bargraf-Anzeige des STK200 einschaltet. Das kurze Programm dient dazu, sich mit der Oberfläche von AVR Studio und der Hardware auf dem STK200 vertraut zu machen, den Workflow kennenzulernen sowie mit Begriffen wie OP-Code, Fetch und Execute Zyklus sowie Stromsenke und Stromquelle etwas mehr anfangen zu können.
Assembler-Direktiven und Speicher-Direktiven wurden bereits angesprochen. Damit wird die Übersetzungsarbeit des Compilers vom Anwender gesteuert. Die Direktiven selbst werden aber nicht in Maschinencode übersetzt. Bisher kennen wir bzw. lernen neu die folgenden Direktiven:
Eine LED zum Leuchten bringen (Assembler) | |
Material |
|
Aufgaben |
|
Das Programm LEDein.asm
Unter Project/Assembler Options im Hauptmenü von AVRStudio Create List File aktivieren.
Den Quellcode übersetzen | |
Aufgaben |
|
Programmlisting anlegen | |
Aufgaben |
|
Aufgaben |
|
In dem sich öffnenden Fenster wird der Inhalt des FLASH-Speichers angezeigt. Das 6 Byte große Programm (s. Abb. 4, links, 2. Spalte) ist ab Speicherstelle 00000000 abgelegt (little endian order - bezieht sich auf die Byte-Reihenfolge, bei der das niedrigstwertige Byte zuerst gespeichert wird).
Programm in den Controller brennen | |
Aufgaben |
|
Abbildung 7 - LED2 leuchtet auf. Von den 10 LEDs der Bargraf-Anzeige werden die oberen acht über PORTB angesprochen. Bei einem ATtiny13x mit 5 Ausgangsports PB.0 ... PB.4 lassen sich natürlich nur maximal fünf LEDs ansprechen.
Die unteren beiden LEDs sind Kontrollleuchten für das STK200-Board. Die unterste LED (ON) leuchtet dauerhaft auf, solange Spannung an das STK200 gelegt ist.
Wie arbeitet das Programm LEDein.asm?
Zwischen .nolist und .list wird die Beschreibungsdatei für den im Programm benutzten Controller – hier ist es ein ATtiny13A - aufgerufen. Dort findet sich auch die Segmentbelegung für die drei Segmentbereichen: .CSEG, .DSEG, .ESEG (s. Abb. 8).
In Zeile 33 des Programms (s. Abb. 1) taucht eine erste I/O Bit Instruction auf. Ihre Syntax setzt sich zusammen aus einem Operationscode (SBI -> Set Bit in I/O Register) sowie einer Adresse im I/O Adressierraum (DDRB - Data Direction Register B) mit Angabe des Zielbits 2. Bit 2 im DDRB wird HIGH (Set Bit) und damit Ausgang.
Nach dem gleichen Muster ist der folgende Befehl aufgebaut (CBI -> Clear bit in I/O Register).
Die erste Instruction setzt im Datenrichtungsregister den Portpin PB2 auf Ausgang und mit der zweiten Instruction wird Pin B2 auf 0 gesetzt. Die mit PB2 verbundene LED der Bargraf-Anzeige beginnt daraufhin zu leuchten (die LEDs auf dem STK200 sind active low geschaltet).
Fetch-Execute Zyklus
Ein Programm besteht immer aus zwei Teilen: einem Operationscode (kurz: OP-Code) und einem Operanden, der vom OP-Code benötigt wird, um eine Anweisung sachgerecht ausführen zu können.
Der OP-Code und der Operand werden bei einem Atmel-Mikrocontroller mit zwei Systemtakten (s. Datenblatt, S.242 - Bit Instructions)
Diese Vorgänge wiederholen sich, bis alle OP-Codes abgearbeitet worden sind.
Warum leuchtet die LED an PB2 auf?
Um das verstehen zu können, muss man etwas über die innere Beschaltung der Portpins eines ATtiny13x-Controllers wissen. Die Treibereigenschaften der Ausgänge eines Mikrocontrollers werden in seinem Datenblatt beschrieben. Je nach äußerer Beschaltung wirkt ein Pinport als Stromsenke oder Stromquelle, je nachdem, ob der Strom von einer externen Energiequelle über die LED in den Portpin des Controllers oder vom Controller über die LED nach GND fließt.
Wirkt ein Pinportausgang wie eine Stromsenke, dann leuchtet eine LED genau dann, wenn der Ausgang auf LOW gezogen wird (active low). Dafür verantwortlich ist bei einem Controller ein intern verbauter Transistor. Ein anderer Transistor wird eingeschaltet, wenn der Pinport auf HIGH gelegt wird.
Zum Abschluss der ersten Übung noch eine kurze Bemerkung zur Speicherorganisation.
1 - Die Speicherorganisation eines ATtiny13A
Für jeden Mikrocontroller stehen im zugehörigen Datenblatt des Herstellers Informationen über Typ, Größe und Ansprechbarkeit der jeweils implementierten Speicher. Ein ATtiny13A verfügt über drei verschiedene Speichertypen:
Die 32 Register werden von der ALU wie Akkumulatoren benutzt.
Der I/O Registerraum ist reserviert für den Zugriff spezieller Funktionen der Mikrocontroller-Einheit. Zwei I/O Register haben wir bereits kennengelernt:
2 - Die Pinbelegung eines ATtiny13x
Der ATtiny13A verfügt über 5 Ein- und Ausgänge, die im sogenannten Port B mit 5 Anschlüssen organisiert sind.
Auf PortB kann mit drei Registern des I/O Adressraumes zugegriffen werden: DDRB, PORTB und PINB.
Data Direction Register (DDRB)
Für DDRB muss bitweise festgelegt werden, welcher Pin als Ausgang ( HIGH oder 1) und welcher aus Eingang (LOW oder 0) vorgesehen ist.
Port Register (PORTB)
Dieses Register muss in einem Programm angesprochen werden, wenn der Mikroprozessor etwas nach "draußen" mitteilen möchte. In unseren Beispielen werden es sehr häufig LEDs sein, die ein- oder ausgeschaltet werden.
Pin Register (PINB)
Über dieses Register werden die Eingänge angesprochen, über die Daten an den Controller übertragen werden.
3 - Code-, Daten- und EEPROM-Segment
Damit ein Mikrocontroller das macht, was von ihm gefordert wird, muss ihm detailliert mitgeteilt werden, was er tun soll. Der
Assembler-Programmierer übernimmt diese Aufgabe. Er schreibt Anweisungen so, das der Assembler anschließend genau das macht, was vorgegeben ist.
Beispiel
Aufgabe: Die Zahlen 47 und 11 vom Typ Byte sollen erzeugt werden.
Lösung:
; die Direktive .db (define byte) macht genau dies. Direktiven beginnen immer mit einem
Punkt (.).
; die Direktive .dw (define word) erzeugt ein 16-Bit Wort. 2863 des Zehnersystems entspricht
; einer Zahl 0x0B2F im 16-System. Word-Daten werden immer in umgekehrter
; Byteanordnung (little-endian order) assembliert; das erste Byte steht also immer am Ende.
; beide Direktiven erzeugen das gleiche Ergebnis
Nachdem die Bytes erzeugt wurden, muss angeben werden, wo diese im Speicherbereich abgelegt werden sollen. Dabei gibt es eine Konvention:
In dem folgenden kleinen Programm wird gezeigt, wie der Assembler das eben Gesagte umsetzt. Gib dazu im Editor des AVR Studio die folgenden Programmzeilen (s. Abb. 6) ein.
Nach dem Assemblieren (F7) werden im Projektfenster "Project" die Dateien *.EEP, *.HEX, *.LST und *.MAP angelegt. Am Ende der MAP-Datei wird eine Übersicht über die Speichernutzung gegeben (s. Abb. 7).
Das zu diesem Programm zugehörige Maschinensprache-Programm wird vom Assembler in zwei Dateien mit den Suffixen *.HEX und *.EEP abgelegt. Im Programmspeicher (s. Memory in Abb. 6) findet man die Bytes 0x2F und 0x0B in Zeile 1 gleich zweimal. Das liegt daran, dass die Dezimalzahl 2863 als Hexadezimalzahl die Darstellung 0x0B2F hat. Die Ablage im FLASH-ROM erfolgt in little-endian order.
Im Data-Segment ab Adresse 0x60 (s. Memory2 in Abb. 6) erscheinen die abgelegten Konstanten: 10 (0x0A), 14 (0x0E) und 8 (0x08). Im Register R16 steht noch die Dezimalzahl 8 (s. Memory3).
Hier geht es weiter mit AVR Studio - Speicher Informationen (Vertiefung)
Hier geht es weiter mit AVR Studio - GPR und Befehlslisten (Vertiefung)
Hier geht es weiter mit AVR Studio - 8-Bit Arithmetik (Vertiefung)
Hier geht es weiter mit AVR Studio - Teil 2.