Unterrichts- und Lernmaterial für Mikrocontroller
Unterrichts- und Lernmaterial fürMikrocontroller

Arbeiten mit AVR Studio - Teil 1

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

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:

Abb. 1a - Assemblerdirektiven (Auswahl)

Abb. 1b - Speicherdirektiven

Übung 1 - Eine LED zum Leuchten bringen

Eine LED zum Leuchten bringen (Assembler)
Material
Aufgaben
  • Starte AVR Studio 4
  • Lege neues Projekt LEDein an
  • Gib das Assemblerprogramm LEDein in den Editor ein (Abb. 1) und speichere es ab.
  • Aktiviere im Hauptmenü von AVRStudio über Project – Assembler Options die Option Create List File

Das Programm LEDein.asm

Abbildung 1 - Programm LEDein.asm

Unter Project/Assembler Options im Hauptmenü von AVRStudio Create List File aktivieren.

Abbildung 2 - AVR Studio 4.19 Auswahlfenster "Project - Assembler Options"
Den Quellcode übersetzen
Aufgaben
  • Assembliere mit F7 den Quellcode.
  • Im Project Manager von AVRStudio erscheint im Ordner Output das erzeugte Listfile LEDein.lst.
Abbildung 3 - Project Manager (AVR Studio 4.19)
Programmlisting anlegen
Aufgaben
  • Öffne mit einem Doppelklick die Datei LEDein.lst. Der Inhalt sollte ähnlich dem in Abb. 4 (Auszug) sein.
Abbildung 4 - Auszug aus der Datei LEDein.LST
Aufgaben
  • In der linken Spalte erscheint der Hexadezimalcode des binär codierten Programms. Die Instruktion SBI DDRB, PB0 wird vom Assembler in den Maschinencode 9AB8 übersetzt.
  • Die Instruktion CBI PORTB, PB0 wird zu 98C0.
  • Das mit F7 assemblierte Programm wird im Projektordner Output in der Datei LEDein.HEX abgelegt (Abb. 3).
  • Rufe jetzt über das Hauptmenü von AVR Studio mit Tools – KandaTools – AVRISP-U das Brennerprogramm auf.

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).

Abbildung 5 - Die Oberfläche des Brennerprogramms AVRISP-U. Das 6 Byte umfassende Programm ist in little-endian-order im FLASH abgelegt.
Programm in den Controller brennen
Aufgaben
  • Lösche ein im Speicher vorhandenes altes Programm über das Hauptmenü des Brennerprogramms mit Device – Erase.
  • Mit Device - Read Flash sollte der Flash-Speicher nur FF enthalten. 
  • Lade über File - Load Project Settings die Datei LEDein.prj mit einem Doppelklick. Im Flash-Memory sollten jetzt die ersten sechs Byte durch BA 9A, C2 98 und FE CFausgetauscht sein (s. Abb. 5).
  • Brenne das Programm in den Controller mit Device – Program – Flash und starte es anschließend mit Device – Run.
  • Überprüfe, ob auf der Bargraf-Anzeige die LED an Position 2 der Bargraf-Anzeige aufleuchtet (s. Abb. 7).

 

 

 

 

 

 

 

 

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).

Abb. 8 - Belegung der Speichersegmente: Programm-, Daten- und EEPROM-Speicher. Die sechs Programmbytes wurden im Codesegment abgelegt. Das Datensegment beginnt ab Speicherstelle 0x60.

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.

P steht für Port, b für Bit

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)

  • in das I/O Register geladen (fetch), in ein Steuersignal dekodiert und
  • die Anweisung ausgeführt (execute).

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.

Abbildung 4 - Der Ausgangstreiber als Stromsenke und Stromquelle. MCU - Mikrocontroller Unit

Zum Abschluss der ersten Übung noch eine kurze Bemerkung zur Speicherorganisation.

Etwas Theorie

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:

  • FLASH mit 512 x 16 Bit
  • SRAM  mit 32 x 8 Bit Register, 64 x 8 Bit I/O Register und 64 x 8 Bit internes SRAM
  • EEPROM mit 64 x 8 Bit

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:

  • DDRB   - Port B Data Direction Register - Speicheradresse: 0x18
  • PORTB - Port B Output Latch - Speicheradresse: 0x17

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.

 

 

 

 

 

 

Abb. 5

Pinbelegung des ATtiny13A

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:

  • .db  0x2F, 0x0B

; die Direktive .db (define byte) macht genau dies. Direktiven beginnen immer mit einem Punkt (.).
 

  • .dw 2863

; 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:

  • Anweisungen und Konstanten werden häufig im Codesegment (FLASH) abgelegt (.cseg),
  • Daten im SRAM (.dseg).
  • Manchmal werden Konstanten aber auch im EEPROM abgelegt (.eseg).
  • Variable Größen - wie auch der Stack - werden im SRAM dynamisch verwaltet, das heißt, dass die Speicherbereichszuweisungen sich während eines Programmlaufs den veränderten Gegebenheiten anpassen.

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).

Abb. 6 - Gebrauch der Direktiven .DSEG und .CSEG. Daten werden ins FLASH ROM und SRAM geschrieben. Eingeblendet sind die Fenster des Programm-, Data- und Registersegments.

 

 

Abb. 7

Das Codesegment enthält 18 Byte Befehlscode und 4 Datenbytes. Das Datensegment enthält 3 Byte.

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.

Druckversion | Sitemap
© Reinhard Rahner - Gettorf