Bewährt hat sich ein erster Zugang über BASCOM. Ein Assembler-Programm lässt sich in seinem Editor genau so erstellen wie man vorher bereits BASIC Programme geschrieben hat. Der Unterschied: man muss neue "Vokabeln" lernen und sich mit der neuen Syntax und benutzten Hardware etwas intensiver auseinandersetzen, als es bei einer Hochsprache notwendig ist. Das Datenblatt eines Controllers gehört ab sofort mit zur unverzichtbaren Lektüre.
Wer bisher ausschließlich in Hochsprachen programmiert hat (BASIC, PASCAL, C o.ä.) wird umlernen und sich deutlich mehr auf die physikalische Ebene einlassen müssen, um die in einem Controller ablaufenden Prozesse besser verstehen und umsetzen zu können.
Parallel zum BASCOM Compiler wird die ebenfalls kostenfrei im Internet erhältliche integrierte Entwicklungsumgebung AVR Studio in der Version 4.19 benutzt; in diesem Kapitel nur zur Simulation von Programmen und als Debugger. Ab "AVR Assembler - Teil 1" folgt ein umfassender Einstieg in Assembler mit AVR Studio 4.19.
Für die Arbeit mit BASCOM wird als Hardware ein Brenner möglichst mit Nullkraftsockel, ein Steckbrett für den Aufbau von Schaltungen (auch dieses möglichst mit Nullkraftsockel) und eine Energiequelle benötigt.
Als Energiequelle eignet sich auch - falls vorhanden - jedes Controller-Board mit herausgeführten Buchsen über +5V und/ oder +3,3V.
Wie ich bereits sagte, reicht das Programm BASCOM als Editor und Compiler für die ersten Assemblerprogramme völlig aus. Als Debugger und vor allem Disassembler ist es nicht geeignet; dass übernimmt das kostenfreie Programm AVRStudio in der etwas älteren Version 4.19. Die neueste Version 7 von ATMEL kommt deutlich behäbiger und langsamer daher als die Version 4.x und sie erkennt unter Windows 10 die Schnittstellen von angeschlossenen Debuggern und Brennern, wie zum Beispiel dem AVR Dragon, nicht. So etwas ist in der Schule oder im Hobbybereich m. E. nicht zu gebrauchen. Die Dinge müssen funktionieren und nicht erst durch Patches oder Herumgelöte lauffähig gemacht werden.
Nach dem Herunterladen und der Installation des Programms öffnet sich der Startbildschirm von AVR Studio mit verschiedenen Auswahlmöglichkeiten.
Wähle in diesem Fall
In dem sich öffnenden Welcome-Bildschirm werden folgende Eintragungen vorgenommen
Project Type : Atmel AVR Assembler
Project Name: LEDs
Initial file : LED_0.asm
Location : Arbeitsverzeichnis auf dem eigenen Rechner
Abgeschlossen werden die Eintragungen mit einem Klick auf den Button Next >>. Im folgenden Bildschirm wird die Plattform für den Debugger und der in der Schaltung benutzte Controller ausgewählt.
Folgende Einstellungen werden vorgenommen:
Die Eingaben werden mit Finish beendet und AVRStudio meldet sich mit einer neuen Arbeitsoberfläche zurück.
Ganz links befindet sich das Projekt-Fenster, in dem alle Dateien für das aktuelle Projekt LEDs gelistet sind. In der Mitte ist das Editor-Fenster, in das der Quellcode eingegeben wird und rechts oben das I/O Ansicht - Fenster.
Klickt man im Fenster I/O Ansicht vor dem Eintrag PORTB auf das Plus-Zeichen, öffnet sich ein Unterfenster mit den drei Registern: Data Register - Port B, Data Direction Register - Port B und Input Pins - Port B.
Im darunter befindlichen Fenster werden die drei Register mit ihrem jeweiligen Namen, der Adresse und den Bits angezeigt.
Einen ersten Zugang zum AVRStudio verschaffen wir uns im folgenden Abschnitt mit einem sehr kleinen Assemblerprogramm.
Aufgabe
Die Schleife zwischen wdh: und rjmp wdh wird jetzt beliebig oft durchlaufen; eine an B.2 angeschlossene LED mit Vorwiderstand leuchtet.
In allen folgenden Übungen wird das AVR Tool zur Simulation und als Debugger eingesetzt.
Was man wissen sollte - Nibble, Byte, Word und andere
Einzelne Bits fasst man gerne in Gruppen zusammen und gibt ihnen Namen. Übliche Gruppennamen sind:
Nibble |
4 Bit |
Byte | 8 Bit |
Word | 16 Bit |
Double Word | 32 Bit |
Quadword | 64 Bit |
Die Bedeutung der Begriffe
ist nicht eindeutig und muss immer im Zusammenhang mit dem benutzten Prozessor gesehen werden. Bei einem 64-Bit Prozessor ist es durchaus üblich, dass ein Word aus 64-Bit besteht.
Die Bezeichnung aus der obigen Tabelle geht auf die 80-er Jahre zurück, als es nur 8- und 16-Bit Prozessoren für den Massenmarkt gab.
Der Einstieg in Assembler wird durch BASCOM sehr erleichtert. Wer nicht beim einfachen Abtippen von Programmen stehen bleiben und etwas tiefer in die Abläufe der Controller einsteigen möchte, sollte sich die Zeit nehmen, die hier vorgestellten Übungen intensiv durcharbeiten und dann auf die integrierte Entwicklungsumgebung AVR Studio 4.19 umschwenken.
Im vorherigen Abschnitt 4 wurde gezeigt, wie man sich mit Hilfe eines Debuggers die Ablauffolge in einem Assemblerprogramm mit gleichzeitiger Betrachtung verschiedener Register anzeigen lassen kann. In diesem Abschnitt wird erst einmal gezeigt, wie ein Assemblerprogramm in BASCOM aussehen muss. Dazu greifen wir das kurze Programm aus Abschnitt 4 auf und schauen uns seinen Verlauf in BASCOM an, brennen das Programm in einen ATtiny13A und überprüfen an der Hardware die vorhergesagte Verhaltensweise des Programms.
Einfaches Assemblerprogramm mit LED | |
Material |
|
Aufbau der Anwenderschaltung
Einfaches Assemblerprogramm mit LED | |
Aufgaben |
|
Das Programm led_0.bas
Dieses Programm ist identisch zum Assembler-Programm aus Abschnitt 4.
In der Simulation in Abschnitt 4 wurde bereits gezeigt, dass dieses Programm Pinport B.2 auf HIGH oder 1 setzt und damit eine LED einschaltet.
Wie arbeitet das Programm led_0 ?
Ein Assembler-Programm unter BASCOM beginnt immer mit
und endet mit
Zwischen diesen beiden Markern muss das Assembler-Programm eingegeben werden.
Das eigentliche Programm besteht aus nur 5 Programmzeilen (Zeilen 16 - 21).
Zeile 16
Sprungadresse Start:, die nie angesprungen wird. Im Prinzip kann diese Zeile weggelassen werden; ich setze sie aus reiner Gewohnheit;-)
Zeile 17
SBI oder Set Bit ist ein sogenanntes Mnemonic für einen Maschinenbefehl. Was diese Instruktion tut, steht im Datenblatt des ATtiny13A unter Kapitel 21: Instruction Set Summary (S. 160ff). Dort findet sich unter dem Abschnitt BIT AND BIT-TEST INSTRUCTIONS
SBI DDRB, Bit Setze ein Bit in einem Data Direction Register B auf 1
SBI DDRB, 2 setzt das 2. Bit im Data Direction Register auf 1.
Befehlsausführungszeit: zwei Clocks (Taktimpulse). Bei 9,6 MHz entspricht das 208,3 ns, bei einem ATtiny mit 1,2 MHz dauert die Ausführung dieses Befehls 1,67 µs oder 1667 ns. Statusregister-Flags sind nicht betroffen.
Zeile 19
Die Sprungadresse Wdh: markiert eine Endlosschleife mit den beiden folgenden Befehlszeilen.
Zeile 20
SBI PORTB, 2 Setzt Bit 2 im Register PORTB auf 1.
Zeile 21
RJMP (relativ jump) ist ein Rücksprungbefehl zur besagten Adresse wdh. Die genaue Syntax dieses Befehls findet sich ebenfalls im Datenblatt des Controllers:
RJMP k führt einen Sprung relativ zur momentanen Adresse aus.
Es wird ein Sprung von k (Offset) relativ zur momentanen Adresse ausgeführt. Der Inhalt des Programmzählers ändert sich um den Wert k + 1, alternativ kann eine Sprungmarke angegeben werden.
Befehlsausführungszeit: zwei Clocks, das entspricht 208,3 ns bei 9,6 MHz oder 1667 ns bei 1,2 MHz. Statusregister-Flags sind nicht betroffen.
Die Richtung eines Portpins kann von Eingang auf Ausgang geändert werden; die Ausgangstreiber sind stark genug, eine LED direkt anzusteuern und jedem Portpin kann individuell ein Pull-Up Widerstand zugeschaltet werden. Als Bezeichner tauchen in den Datenblättern die Buchstaben "x" für den Buchstaben des angesprochenen Ports und "n" für die Bitposition auf; wir werden sie genau so benutzen.
Beispiel
Jedem Port werden drei I/O Speicheradressen zugeordnet, jeweils eine für das
Der Zugriff auf die Register wird durch die folgende Tabelle näher erklärt.
Eingang DDBn = 0
Ausgang DDBn = 1
Bit n = 0 weist immer auf einen Eingang, Bit n = 1 immer auf einen Ausgang hin.
---------------------------------------------------------------------------------------------
Widerstand einschalten DDBn = 0 UND PORTBn = 1
Widerstand ausschalten DDBn = 0 UND PORTBn = 0
oder PBn wird als Output deklariert.
----------------------------------------------------------------------------------------------
PBn auf HIGH setzen DDBn = 1 UND PORTBn = 1
PBn auf LOW setzen DDBn = 1 UND PORTBn = 0
----------------------------------------------------------------------------------------------
Setzt man in einem PINBn-Register eine 1, führt das zu einem Umschalten des Zustandes im korrespondierenden Bit des Ausgangsregisters PORTBn, völlig unabhängig vom Wert im Register DDRBn.
Mit Hilfe des kleinen Programms led_1.bas lässt sich das schnell nachweisen. Es ist gegenüber dem Programm led_0.bas in Zeile 20 abgeändert worden. Compiliere zunächst das Programm mit F7, schalte den Simulator ein und gehe anschließend Instruktion für Instruktion durch das Programm.
Das Augenmerk ist auf die drei Register DDRB, PINB und PORTB gerichtet, in denen mit dem Start der Simulation die Werte 00 stehen. Mit Ausführung der Instruktion SBI DDRB, 2 in Programmzeile 17 wird in DDRB der Wert 4 geschrieben.
Im folgenden Schritt wird mit SBI PORTB, 2 in PB.2 eine 1 geschrieben.
Wiederholt man das Ganze noch einmal, tauscht aber in Programmzeile 17 vorher SBI durch CBI (clear bit) aus, verhält sich das Programm genau wie vorher. Die Einstellung von DDRB hat keinen Einfluss auf das Verhalten von PORTB.2 oder allgemein von PORTB.n.
Warum steht eine 04 bei PORTB und DDRB statt einer 01?
SBI DDRB, 2 bedeutet, im Register DDRB wird an der Bitposition 2 eine 1 geschrieben.
Wird in das PortB.2 Bit eine 1 geschrieben, dann befindet sich dieses Bit an der 3. Stelle einer 8-Bit Zahl. Die binäre Zahl 0b00000100 entspricht der Zahl 4 im 10-er System und ebenso der Zahl 4 im 16-er System. Es ist dieser Wert 4, der vom Simulator als Registerinhalt angezeigt wird.
Umschalten zwischen INPUT und OUTPUT
Das Umschalten von INPUT zu OUTPUT ist nicht immer unproblematisch. Der Hersteller ATMEL gibt dazu in seinen Datenblättern entsprechende Hinweise, wo Probleme auftauchen können und wie man sie tunlichst umgeht.
Wird von einem Hi-Z Zustand (DDBn = PORTBn = 0 ODER DDBn = 0 UND PORTBn = 1) zu einem Output HIGH (DDBn = PORTBn = 1) gewechselt, sollte das immer über einen Zwischenzustand von entweder DDBn = 0 UND PORTBn = 1 (Pull-Up Widerstand EIN) ODER DDBn = 1 UND PORTBn = 0 (Output LOW) geschehen.
Das gleiche Problem tritt bei einem Übergang von einem Input mit Pull-Up zu einem Output LOW auf. In diesem Fall sollte man als Zwischenschritt entweder DDBn = PORTBn = 0 (Hi-Z) oder DDBn = PORTBn = 1 (Output HIGH) wählen.
Was steht eigentlich in der Datei attiny13a.dat?
Zu Beginn des kleinen Programms led_0.bas wird mit $regfile = "attiny13a.dat" eine Datei aufgerufen. Den Inhalt dieser Datei schauen wir uns etwas genauer an, dazu muss sie mit einem beliebigen Editor geöffnet werden.
Irgendwo im ersten Drittel der Datei finden sich zum Beispiel die folgenden Einträge
aus denen man erahnen kann, welche Arbeit sie uns bei der Erstellung eines Assemblerprogramms bereits abgenommen hat. Diese *.DAT Datei enthält alle notwendigen Voreinstellungen und Namenszuweisungen, die ein Assemblerprogramm später lesbar machen. Mit
wird die Zuweisung der I/O Adresse $18 zum Wort PORTB vorgenommen. Mit gleichem Verfahren werden die anderen I/O Adressen, DDRB und PINB den entsprechenden Portregisternamen zugewiesen. Statt nach den Adressen für einen bestimmten I/O Port zu suchen, muss nur sein Name, den man sich leichter merken kann, eingegeben werden. Den Rest erledigt die entsprechende *.DAT Datei für uns, die es zu jedem von uns benutzten Controller gibt.
In diesem Abschnitt werden wir das neue Wissen weiter vertiefen. In einer ersten Übung wird eine LED mit Vorwiderstand anfangen zu blinken. Die Schwierigkeit in dieser einfachen Schaltung besteht darin, dass zwischen dem Ein- und Ausschalten der LED eine Pause von einigen 100 ms eingebaut werden muss.
Blinkende LED - Versuch 1 | |
Material |
|
Schaltungsaufbau
Blinkende LED | |
Aufgaben |
|
Das Programm led_1_blinker.bas
Wie arbeitet das Programm led_1_blinker.bas?
Einige Elemente aus dem Quellcode sind uns bereits bekannt. Aber beginnen wir von vorne. Das Assemblerprogramm startet nach dem Marker $asm in Programmzeile 15.
Zeile 17
SBI DDRB, 2 | Setzt Bit 2 im DDRB-Register auf 1. | 2 CLK |
Zeile 19
Wdh: |
Einsprungstelle für eine Schleife |
0 CLK |
Zeile 20
SBI PORTB, 2 |
Setzt Bit 2 im PORTB-Register. Als Folge davon geht die LED an; sie ist mit ihrem Vorwiderstand gegen Masse geschaltet. |
2 CLK |
Zeile 21
CBI PORTB, 2 |
Setzt Bit 2 im PORTB-Register auf 0 zurück. Als Folge davon geht die LED aus. |
2 CLK |
Zeile 22
RJMP Wdh |
Springt zurück an die Marke Wdh: und alles beginnt von vorne. |
2 CLK |
Der Vorgang: LED ein - LED aus läuft in diesem Programm sehr schnell ab; es werden gerade mal 6 CLKs (Taktzyklen) benötigt. Bei einer voreingestellten Taktfrequenz von 9,6 MHz und gesetztem Fusebit E (Divide by 8) ergibt das
Der Ein-/Ausschaltvorgang der LED läuft 200.000-mal pro Sekunde ab und das ist für unser Auge einfach zu schnell.
Das folgende Oszillogramm wurde am I/O PortB2 des Controllers aufgenommen und zeigt die Ein-/Aus-Schaltvorgänge. Gut zu erkennen sind:
Die gemessene Schaltfrequenz liegt bei ca. 187 kHz
Der HIGH-Zustand dauert nur halb so lange wie der LOW-Zustand. Dem Oszillogramm kann man entnehmen:
Ein Blick in das Assembler-Programm klärt diesen Unterschied. Nach SBI PORTB, 2 - LED geht AN (2 CLK) folgt CBI PORTB, 2 - LED geht AUS (2 CLK) gefolgt von einem RJMP wdh - LED immer noch aus (2 CLK). Insgesamt 4 Taktzyklen bleibt die LED dunkel, 2 Taktzyklen hell - schade, dass wir das der LED nicht angesehen haben;)
Wer tiefer in die Assemblerprogrammierung einsteigen möchte, sollte sich den Kapiteln AVR Studio - Teil x zuwenden. Es wird ausschließlich mit der Programmieroberfläche AVR Studio und der Sprache Assembler gearbeitet. Interessiert? Dann geht es hier weiter zu AVR Studio - Teil 1.
Für erste kleine Schritte mit dem Controller ATtiny13A geht es hier weiter.
F4F506