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

Arbeiten mit AVR Studio - Teil 1

Alle hier dargestellten Vorgänge und Erklärungen lassen sich auf alle anderen Atmel-Controller übertragen. Im Einzelnen muss immer das Datenblatt hinzugezogen werden; die Bezeichnungen unterscheiden sich - wenn überhaupt - nur geringfügig voneinander.

Wer sich ernsthafter mit Mikrocontrollern befassen möchte und bereits Erfahrung mit der BASIC STAMP, dem Propeller Controller oder Arduino UNO, vielleicht auch dem Raspberry Pi gesammelt hat, sollte hier einsteigen. Man erfährt mehr über die innere Struktur von Controllern, warum sie so arbeiten, wie sie es tun und ist nicht mehr auf fremde Bibliotheken angewiesen, wenn es um die Steuerung bestimmter Bauteile geht.

Programmiert wird vorrangig in ASSEMBLER und C. Die Möglichkeiten von AVR Studio, quasi hinter die Kulisse eines Programmes zu schauen, werden genutzt und gezeigt. Sehr hilfreich - aber nicht unbedingt notwendig - ist, wenn man vorher die Kapitel AVR-Assembler - Teil 0 durchgearbeitet hat.

In diesem Kapitel wird ausschließlich mit einem Kanda STK200 Board und AVR Studio 4.19 gearbeitet. Das Board besticht durch seinen günstigen Preis und die auf der Platine vorinstallierten Elemente (Taster, LEDs, Potentiometer, ADC etc.). Programmiert wird ein 40-poliger ATmega 8515 über einen ebenfalls zum Kit gehörenden ISP-Programmer. Alternativ kann auch ein AVR Dragon eingesetzt werden. Dazu später mehr. Zusätzlich wird ein Schaltnetzteil von 9V DC, 1000 mA benutzt.

AVR Studio in der Version 4.19 wurde deshalb gewählt, weil es schnell und nicht so überfrachtet ist, wie die neueste Studioversion aus dem Hause ATMEL. Es ist kostenfrei aus dem Internet herunterladbar und muss für die Durchführung der Übungen auf einem PC oder Laptop installiert sein. Gleiches gilt für den ISP2-Programmer.

Die benutzte Hardware

Abbildung 1 - STK200-Board und ISP2 Programmer

Statt des ISP2-Programmers wird an anderer Stelle auch gezeigt, wie man den AVR-Dragon mit dem Board nutzen kann und welche zusätzlichen Möglichkeiten sich dadurch ergeben.

Einige Eigenschaften des ATmega8515 und ATmega16

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 vertraut zu machen, den Workflow kennenzulernen und mit Begriffen wie OP-Code, Fetch und Execute Zyklus sowie Stromsenke und Stromquelle etwas mehr anfangen zu können.

Was man wissen sollte - Schreibweise von Zahlen

Bei der Darstellung von Zahlen muss das zugrunde liegende Zahlsystem (binär, hexadezimal, dezimal, ...) angegeben werden. Durchgesetzt haben sich verschiedene Schreibweisen:

Zahlsystem Schreibweisen Präfix/Suffix

Binärsystem

0b00011010

%00011010

00011010b

Präfix

Präfix

Suffix

Hexadezimalsystem

0x0A

$0A

0Ah

Präfix

Präfix

Suffix

Dezimalsystem

11010 ohne Präfix oder Suffix

Übung 1 - Eine LED zum Leuchten bringen

Eine LED zum Leuchten bringen (Assembler)
Material
  • 1x  STK200 mit ATmega 8515-16PU
  • 1x  Schaltnetzteil 9V DC, 1000 mA
  • 1x  ISP2 Programmer
  • 1x  AVR Studio 4.19 auf PC
  • 1x  Datenblatt ATmega 8515
Aufgaben
  • Starte AVR Studio
  • Lege neues Projekt LEDein an
  • Gib das Assemblerprogramm LEDein in den Editor ein (Abb. 6) und speichere es ab.
  • Aktiviere im Hauptmenü über Project – Assembler Options die Option Create List File
Abbildung 2 - AVR Studio 4.19 Auswahlfenster "Project - Assembler Options"
Den Quellcode übersetzen
Aufgaben
  • Assembliere mit F7 den Quellcode.
  • Im Project Manager 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 sein.
Abbildung 4 - Die 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 oder starte es direkt durch einen Doppelklick auf das Programm-Icon in der Benutzeroberfläche.
Abbildung 5 - Die Oberfläche des Brennerprogramms AVRISP-U
Programm in den Controller brennen
Aufgaben
  • Lösche ein im Speicher vorhandenes altes Programm über das Hauptmenü des Brennerprogramms mit Device – Erase und lade über File – Reload Flash das neue Programm.
  • 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 oberste LED aufleuchtet.

Das Programm LEDein.asm

Abbildung 6 - Programm LEDein.asm

 

 

 

 

 

 

Abbildung 7 - LED0 (obere LED) leuchtet auf. Von den 10 LEDs  der Bargraf-Anzeige werden die oberen acht über PORTB angesprochen. Die unteren beiden LEDs sind Kontrollleuchten für das STK200-Board.

Wie arbeitet das Programm LEDein.asm?

Zwischen .nolist und .list wird die Beschreibungsdatei für den im Programm benutzten Controller – hier ist es ein ATmega 8515 - aufgerufen.

In der folgenden Zeile 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 (PB0). PB0 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 PB0 auf Ausgang und mit der zweiten Instruction wird Pin B0 auf 0 gesetzt. Die mit PB0 verbundene LED der Bargraf-Anzeige beginnt daraufhin zu leuchten.

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 PB0 auf?

Um das verstehen zu können, muss man etwas über die innere Beschaltung der Portpins eines ATmega-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

Die Speicherorganisation eines ATmega8515

Für jeden Mikrocontroller stehen im zugehörigen Datenblatt des Herstellers Informationen über Typ, Größe und Ansprechbarkeit der jeweils implementierten Speicher. Ein ATmega 8515 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. Die geläufigsten I/O Register sind:

Die Ein- und Ausgänge

Der ATmega8515 verfügt über 35 Ein- und Ausgänge, die in sogenannten Ports A, B, C und D mit je 8  sowie E mit 3 Anschlüssen organisiert sind.

Pinbelegung eines ATmega 8515

Auf jeden Port kann mit drei Registern des I/O Adressraumes zugegriffen werden: DDRx, PORTx und PINx. x steht dabei für einen Buchstaben aus der Menge A ... E.

 

Data Direction Register (DDRx)

Für jeden Port muss bitweise festgelegt werden, welcher Pin als Ausgang ( HIGH oder 1) und welcher aus Eingang (LOW oder 0) vorgesehen ist.  

 

Port Register (PORTx)

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 (PINx)

Über dieses Register werden die Eingänge angesprochen, über die Daten an den Controller übertragen werden.

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-Speicher) 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 ein:

.CSEG
.DB  0x2F, 0x0B
.DW 2863
.ESEG
.DB $A0, $0B
.DSEG
.byte 10

 

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.

Im Codesegment (cseg, beginnt bei 0x000000) werden vier Bytes, im EEPROM-Segment (eseg, beginnt bei 0x000000) zwei Bytes und im Datensegment (dseg, beginnt bei 0x000060) 10 Bytes reserviert.

Das zu diesem Programm zugehörige Maschinensprache-Programm wird vom Assembler in zwei Dateien mit den Suffixen *.HEX und *.EEP abgelegt. In der HEX-Datei findet man die Bytes 0x2F und 0x0B in Zeile 2 gleich zweimal. Das liegt daran, dass das Wort 2863 als Hexadezimalzahl ebenfalls die Darstellung 0x0B2F hat (little-endian-order).

In der EEP-Datei erscheinen die beiden Bytes 0xA0 und 0x0B in der ersten Zeile.

Übung 2 - Addition von zwei 8-Bit Zahlen

In diesem Abschnitt wird gezeigt, wie man zwei Zahlen addiert. Als optische Hilfe wird die Bargraf-Anzeige genutzt. Wer nicht (mehr) vertraut ist mit dem binären Zahlsystem, sollte sich das vorher noch einmal anschauen. Insbesondere, wie zwei Dualzahlen addiert, subtrahiert und multipliziert werden.

Bevor es an die Programmierarbeit geht, wird erst einmal das Datenblatt des ATmega8515 befragt. Gib eine Antwort auf die folgenden beiden Fragen:

  • Welche arithmetischen Rechenbefehle stellt der Controller laut Datenblatt zur Verfügung? Schaue hierzu im Instruction Set Summary nach.
  • Welche Rechenoperation wird nicht bereit gestellt?

 

Antworten:

Es sind über 10 OP-Codes im Datenblatt zu finden.

Ein Operation Code für die Division ist nicht angegeben.

Addition zweier 8-Bit Zahlen
Material
  • 1x  STK200 mit ATmega 8515-16PU
  • 1x  Schaltnetzteil 9V DC, 1000 mA
  • 1x  ISP2 Programmer
  • 1x  AVR Studio 4.19 auf PC
Aufgaben
  • Lege ein neues Projekt rechnen1 an
  • Gib das Assemblerprogramm rechnen1 in den Editor ein und speichere es ab.
  • Brenne das Programm in den Controller und starte es anschließend.
  • Überprüfe, ob auf der Bargraf-Anzeige LED1 und LED2 leuchten.

Schaltungsaufbau

Hat man kein STK200 Board zur Verfügung, lässt sich die Schaltung auf einem Steckbrett aufbauen.

Abbildung 4a - Schaltungsaufbau mit 10 Segment Bargraf-Anzeige. Nicht gezeigt werden die peripheren Beschaltungen (Spannungsversorgung, Abblockkondensatoren) des Controllers.

 

 

 

 

 

Abbildung 5

Auf der Bargraf-Anzeige wird das Ergebnis der Addition binär angezeigt.

Das Programm rechnen1.asm

Wie arbeitet das Programm rechnen1.asm?

  1. Die drei Direktiven (.nolist, .include, .list) zu Anfang des Programms kennen wir bereits.
  2. Der Hauptteil beginnt mit LDI (Load Immediate). Er lädt eine 8-Bit Konstante mit dem Wert 2 direkt in das Register R16 und eine zweite Konstante mit dem Wert 4 in das Register R17.
  3. ADD (Add without Carry) addiert die Inhalte der beiden Register R16 und R17 und legt das Ergebnis in R16 ab. 
  4. Die Ausgabe des Ergebnisses erfolgt über eine Bargraf-Anzeige. Die LEDs leuchten genau dann, wenn sie auf 0 gezogen werden. Deshalb muss aus der Binärzahl 6 (Summe aus 2 und 4) 0b00000110 durch Komplementbildung (0 wird zu 1 und umgekehrt) 0b11111001 erzeugt werden. Das macht COM R16.
  5. Die Ausgabe erfolgt über die Bargraf-Anzeige, die mit PORTB verbunden ist. Von PORTB müssen alle Portpins auf Ausgang geschaltet werden. Dazu wird R18 mit 1 gefüllt -> SER (Set all bits in Register) und anschließend über OUT in das DDRB-Register entsprechend gesetzt.

Über das in AVR-Studio integrierte Hilfe-Menü (Help - Assembler Help) lassen sich zu allen hier benutzten Operanden-Codes umfangreiche Hilfetexte mit Programmbeispielen aufrufen. Eine weitere Besprechung der Wirkungsweise dieser Operanden entfällt deshalb.

Mit 8-Bit lassen sich nur Zahlen von 0 bis 255 (0b1111_1111) darstellen. Was ist zu beachten, wenn zwei Zahlen - größer als 8-Bit - addiert werden sollen? Das wird in Übung 3 untersucht. Mit 16-Bit lassen sich Zahlen zwischen 0 und 65.535, mit 32-Bit zwischen 0 und 4.294.967.294 darstellen.

Übung 3 - Addition von zwei 16-Bit Zahlen

Die Addition zweier 16-Bit Zahlen verläuft im Prinzip wie die von zwei 8-Bit Zahlen. Es werden zuerst die lower Bytes und anschließend die higher Bytes mit Carry addiert. Fertig.

Das Addieren mit Carry wird über ADC, das Addieren ohne Carry mit ADD aufgerufen. Ein Ablaufplan oder Pseudocode könnte so aussehen:

 

  • Addiere zahl1L und zahl2L (SummeLowByte)
  • Addiere mit Carry zahl1H und zahl2H plus Carry-Bit (SummeHighByte).
  • Gib auf der Bargraf-Anzeige das SummeHighByte aus.
Addition von zwei 16-Bit Zahlen
Material
  • 1x  STK200 mit ATmega 8515-16PU
  • 1x  Schaltnetzteil 9V DC, 1000 mA
  • 1x  ISP2 Programmer
  • 1x  AVR Studio 4.19 auf PC
Aufgaben
  • Lege ein neues Projekt rechnen2 an
  • Gib das Assemblerprogramm rechnen2 in den Editor ein und speichere es ab.
  • Brenne das Programm in den Controller und starte es anschließend.
  • Notiere, welche LEDs der Bargraf-Anzeige leuchten (1) und welche nicht (0).

Schaltungsaufbau

wie in Abb. 4a.

Das Programm rechnen2.asm

Wie arbeitet das Programm rechnen2.asm?

  1. Die drei Direktiven (.nolist, .include, .list) zu Anfang des Programms kennen wir bereits. Neu ist die Direktive .equ. Über sie wird einer Variablen ein Wert zugewiesen.
  2. Der Hauptteil beginnt mit LDI (Load Immediate). Es werden vier 8-Bit Zahlen (der Controller verarbeitet nur 8-Bit Zahlen!!!), je zwei Lowbytes und Highbytes der beiden 16-Bit Zahlen in vier verschiedene Register geladen.
  3. ADD (Add without Carry) addiert die Inhalte der beiden Lowbyte-Register R16 und R17 und legt das Ergebnis in R16 ab.
  4. ADC (Add with Carry) addiert die Inhalte der beiden Highbyte-Register R18 und R19 und legt das Ergebnis, unter Berücksichtigung des Carry, in R18 ab. 
  5. Die Ausgabe des Ergebnisses erfolgt über eine Bargraf-Anzeige. Die LEDs leuchten genau dann, wenn sie auf 0 gezogen werden (low active). Deshalb muss aus der Binärzahl 6 (Summe aus 2 und 4) 0b00000110 durch Komplementbildung (0 wird zu 1 und umgekehrt) 0b11111001 erzeugt werden. Das macht COM R16.
  6. Die Ausgabe erfolgt über die Bargraf-Anzeige, die mit PORTB verbunden ist. Von PORTB müssen alle Portpins auf Ausgang geschaltet werden. Dazu wird R20 mit Einsen gefüllt -> SER (Set all bits in Register) und anschließend über OUT in das DDRB-Register gesetzt. Über das Programm werden die 8 höchstwertigen Bits angezeigt.
  7. Für die Ausgabe der 8 niedrigwertigen Bits muss das Programm in zwei Zeilen geändert werden: com r16 und out portb, r16 muss es dann heißen.

Wenn man das Prinzip verstanden hat, dann ist die Addition von beliebig großen Zahlen mit Assembler möglich und einfach durchzuführen. Im vorliegenden Beispielprogramm der Übung 3 werden die beiden Zahlen

  • 0xC2F3 oder dezimal 49907   und
  • 0x04BA oder dezimal 1210

miteinander addiert. Die Summe ist: 51117 oder 0b1100_0111_1010_1101. Die rot markierten acht Bit stehen für das Highbyte, die blauen acht Bit für das Lowbyte. Dreht man das STK200-Board um 90° nach rechts, so dass die Bargraf-Anzeige horizontal liegt, kann man die entsprechende Bitkonfiguration unmittelbar ablesen (Abb. 6).

Abbildung 6 - Bargraf-Anzeige des Higher- und Lowerbyte des Summenterms. Nacheinander aufgenommen. LED10 (ON) wurde etwas abgeschwächt in der Darstellung.

Im diesem Abschnitt wurden die Op-Codes

  • LDI - load immediate
  • ADD - add without carry
  • ADC - add with carry
  • COM - one´s complement
  • SER - set all bits in register
  • OUT - store register to I/O location
  • RJMP - relative jump

 

und die Direktiven

  • .NO
  • .NOLIST
  • .INCLUDE
  • .EQU

eingeführt.

 

Im folgenden Abschnitt wird gezeigt, wie man den Zustand eines Tasters abfragt. Interessiert? Dann geht es hier weiter mit AVR Studio - Teil 2.

Druckversion Druckversion | Sitemap
© Reinhard Rahner - Gettorf