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

Arbeiten mit AVR-Studio - Teil 3

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.

Warteschleifen

In einer ersten Übung soll eine LED mit Vorwiderstand blinken. Die Schwierigkeit in dieser einfachen Schaltung besteht darin, dass zwischen dem Ein- und Ausschalten der LED eine Pause eingebaut werden muss.

Übung 1 - Eine LED blinkt

Blinkende LED
Material
  • 1x  STK200 mit ATmega 8515-16PU
  • 1x  Schaltnetzteil 9V DC, 1000 mA
  • 1x  ISP2 Programmer
  • 1x  AVR Studio 4.19 auf PC

Schaltskizze

Abbildung 1 - Schaltskizze "Blinkende LED" an PB.2
Blinkende LED
Aufgaben
  • LED2 wird so programmiert, dass sie deutlich erkennbar blinkt. Die Blinkfrequenz wird nicht vorgegeben.
  • Lege ein neues Projekt led_1 an
  • Gib das Assemblerprogramm led_1 in den Editor ein und speichere es ab.
  • Brenne das Programm in den Controller und starte es anschließend.
  • Überprüfe, ob LED3 blinkt.

Vorüberlegungen zum Programmentwurf

Würde man eine LED in einer endlosen Schleife ein- und anschließend wieder ausschalten, geschieht das mit einem Assemblerprogramm so schnell, dass das menschliche Auge den Eindruck hat, die LED leuchtet dauerhaft.

Eine Methode, die Blinkfrequenz einer LED zu senken, besteht darin, den Controller zwischen den beiden  Zuständen LED HIGH und LED LOW in eine Warteschleife zu schicken. Zum Beispiel dadurch, dass der Controller - nachdem er die LED auf 1 gezogen hat - von 0 bis 10.000 aufwärts  oder von 10.000 bis 0 abwärts zählt und erst dann die LED auf 0 zieht. Durch das Zählen ist soviel Zeit vergangen, dass zwischen "LED leuchtet" und "LED leuchtet nicht" eine endliche Zeitspanne liegt.

Für das Aufwärtszählen gibt es u.a. den Befehl ADIW (add immediate to Word), für das Abwärtszählen den Befehl SBIW (Subtract immediate from Word); die Ausführungszeit für beide Instruktionen ist vom Hersteller ATMEL angegeben: 2 CLKs.

Wir entscheiden uns für das Abwärtszählen SBIW, da hier die Abbruchbedingung (Stopp des Schleifendurchlaufs und weiter im Programm) über das Setzen des Z-Flags im Statusregister mit einem Verzweigungsbefehl einfach abzufragen ist.

Wenn also zum Beispiel von einer Zahl 10.000 bis auf 0 in 1-er Schritten zurückgezählt und anschließend das Zero-Flag gesetzt wird und die LED umschaltet, dann werden dafür 2 x 10.000 = 20.000 CLK benötigt;  das entspricht je nach Taktung des Controllers einer bestimmten Zeit. Das wird der Ansatz im folgenden Programm sein.

Das Programm led_1.asm

Abbildung 2 - Programm led_1.asm

Wie arbeitet das Programm led_1.asm?

Die Direktiven .NOLIST, .LIST, .INCLUDE sind uns bereits bekannt. Das Programm enthält vier Einsprungadressen: Start, Wiederhole, Warten1 und Warten2.

Einsprungstelle Start: 

Im Datenrichtungsregister B wird Port2 auf Ausgang (1) gesetzt.

SBI DDRB, 2

Set Bit in I/O Register
Setzt Bit 2 im DDRB-Register auf 1. 2 CLK

Einsprungsstelle Wiederhole:

Wiederhole:

Einsprungstelle 0 CLK

SBI PORTB, 2

Set Bit in I/O Register

Setzt Bit 2 im PORTB-Register. Als Folge davon geht

LED2 AUS; sie ist LOW ACTIVE geschaltet.
2 CLK

Einsprungsstelle Warten1:

SBIW ZL, 1

SuBtract Immediate from Word

Der Inhalt des Doppel-Registers ZH:ZL startet bei Null und wird bei jedem Schleifendurchlauf um den Wert 1 dekrementiert. ZL ist das Lower-Byte, ZH das Higher Byte.

Die Instruktion SBIW ist auf die letzten drei Pointer X, Y und Z und R24:R25 im General Purpose Register anwendbar.
2 CLK

BRNE Warten1

BRunch if Not Equal

Solange das Z-Flag nicht gesetzt ist, mache weiter bei Warten1:

2 CLK

CBI PORTB, 2

Clear Bit in I/O Register

Setzt Bit 2 im PORTB-Register auf 0 zurück. Als Folge

davon geht die LED2 AN.

2 CLK

Einsprungsstelle Warten2:

Die Abfolge der Instruktionen bei der Einsprungstelle Warten2: ist identisch mit der bei Warten1. Erst nachdem diese Schleife ebenfalls durchlaufen wurde, geht es mit RJMP Wiederhole zurück auf Anfang.

RJMP Wdh

Relative JuMP

Springt zurück an die Marke Wiederhole: und alles beginnt von

vorne.

2 CLK

Übung 2 - Der AVR-Debugger

Über den internen Ablauf eines Assemblerprogramms kann man mit dem Einsatz des Debuggers (Strg + F7) viel lernen. Ist das Programm fehlerfrei, erscheint nach kurzer Zeit im Editorfenster ein gelber Programmzeiger. In dieser Übung wird das Programm led_1.asm mit dem Debugger näher untersucht. Mit dem Start erkennt man:

  • Alle Register sind auf 0 gesetzt, so auch das 16-Bit Z-Register [R31: R30].

Im Datenrichtungsregister B (DDRB) ist Pin 2 auf Ausgang gesetzt und Portpin B.2 auf HIGH gezogen. LED2 wird ausgeschaltet.

Abbildung 3 - Alle Register sind nach dem Programmstart auf Null zurückgesetzt. Der gelbe Programmzeiger erscheint links neben der ersten Instruktion im Editorfenster. Der rote Punkt links im Editorfenster markiert einen sogenannten Breakpoint.

Mit F11 wird jetzt zeilenweise jede Instruktion des Assemblerprogramms durchlaufen. Man erkennt, dass sich der Inhalt des Z-Registers (Z-Pointer) mit jedem Schleifendurchlauf um 1 erniedrigt.

Gestartet wird bei 0x0000, geht mit 0xFFFF, 0xFFFE, ... weiter und erreicht ein vorläufiges Ende mit 0x0000.

Um nicht alle Zählschritte mit F11 durchlaufen zu müssen, wird der Z-Pointer im Fenster "Processor" durch Anklicken mit der Maus auf 0x0001 gesetzt und mit F11 die nächste Instruktion aufgerufen. In dem Moment, wo der Z-Pointer auf 0x0000 springt, wird im SRegister das Zero-Flag (Z-Flag) gesetzt.

Abbildung 4 - Der Inhalt von Z-Pointer ist 0, das Z-Flag wird gesetzt und die LED eingeschaltet.

Das Z-Flag ist gesetzt, die BRNE-Bedingung nicht mehr erfüllt; das Programm macht weiter mit der Instruktion CBI. portb, 2. LED2 wird eingeschaltet und das Programm setzt seine Arbeit im Block Warten2: fort. Der Ablauf dort ist identisch mit dem in Block Warten1:.

Ist Block Warten2: abgearbeitet (dies dauert genau so lange wie bei Block Warten1:), dann kehrt das Programm zurück an die Stelle Wiederhole: und das heißt: LED2 wird ausgeschaltet.

Übung 3 - Berechnung einer Blinkfrequenz

Die erste Schleife mit der Einsprungmarke Warten1 gibt die Zeit für die eingeschaltete LED vor. Der ATmega8515 ist mit 1,0 MHz getaktet (Werkseinstellung). Jeder CLK verbrät somit 1,0.. µs (nach Formel 1). Bei 4 CLKs pro Schleifendurchlauf (SBIW - 2CLK, BRNE - 2CLK) und 65536 Zählzyklen ergibt das insgesamt 262.144 CLKs. Hinzu kommen noch 2 CLK von der CBI-Instruktion. Macht insgesamt also 262.146 CLKs.

Insgesamt entspricht das einer Zeit von 262.146 µs oder 262,146 ms oder 0,262146 s für eine Halbperiode (LED an). Die gleiche Berechnung gilt für die zweite Halbperiode (LED aus). Eine Periode dauert somit 0,524292 s; umgerechnet in eine Frequenz über die Formel

ergibt sich f =  1,907.. Hz.

Das an der Schaltung über PB2 und GND aufgenommene Oszillogramm zeigt folgenden Verlauf

Abbildung 5 - Umschaltfrequenz an PB2 aufgenommen mit PicoScope2000. Die Frequenz beträgt 1,914 Hz, die HIGH und LOW Phasen sind nahezu identisch lang.

Übung 4 - Lauflicht

Nachdem wir wissen, wie man Zeitverzögerungen programmieren kann, soll jetzt ein Programm entworfen werden, das ein Lauflicht erzeugt. Die acht LEDs auf dem STK200 werden nacheinander ein- und wieder ausgeschaltet, so dass der Eindruck eines Lauflichtes entsteht.

Lauflicht mit 8 LEDs
Material
  • 1x  STK200 mit ATmega 8515-16PU
  • 1x  Schaltnetzteil 9V DC, 1000 mA
  • 1x  ISP2 Programmer
  • 1x  AVR Studio 4.19 auf PC
Aufgaben
  • Die acht LEDs werden so programmiert, dass sie nacheinander ein- und wieder ausgeschaltet werden und so ein Lauflichteffekt erzeugen.
  • Lege ein neues Projekt led_2 an
  • Gib das Assemblerprogramm led_2 in den Editor ein und speichere es ab.
  • Brenne das Programm in den Controller und starte es anschließend.
  • Überprüfe, ob das Lauflicht funktioniert.

Schaltungsaufbau und Schaltskizze

Abbildung 6 - Acht LEDs (LED0 ... LED7) werden nacheinander angesteuert und bilden ein sogenanntes Lauflicht.

Vorüberlegung zum Programmaufbau

Die Ablauffolge bei einem Lauflicht könnte so aussehen:

  • Schalte das Datenrichtungsregister B auf Ausgang.
  • START:
  • Schalte LED0 an und gehe in eine Warteschleife.
  • Schalte LED0 aus und LED1 an und gehe in eine Warteschleife.
  • ...
  • Schalte LED6 aus und LED7 an und gehe in eine Warteschleife.
  • Schalte LED7 aus
  • gehe zurück nach START.

Geht man in der hier skizzierten Reihenfolge vor, wird das Assemblerprogramm sehr zeilenintensiv.

Das Programm led_2.asm

            ...

Das Programm lässt sich deutlich verkürzen, wenn man Teile davon in einem Macro ablegt. Wie man es anlegt, wurde in Kapitel AVR Studio - Teil 2 gezeigt. Ein Macro könnte zum Beispiel das folgende Aussehen haben:

Das Programm led_2.asm mit Macroaufruf zeigt die folgende Abbildung.

Kleine Nachbetrachtung

Die kleinste Zeitperiode des mit 1,0 MHz getakteten ATmega8515 beträgt nach (1) ca. 1 µs. Es lassen sich mit der hier vorgestellten Schleifenmethode nur Vielfache dieser "Einheitszeit" erzeugen. Es gilt:

  • 1 µs      entspricht 1 CLK
  • 1 ms     entspricht  ~ 1.000 CLKs
  • 1s         entspricht  ~ 1.000.000 CLKs

Um zum Beispiel eine Pause von 1s zu realisieren, wird der Prozessor in sinnlose Schleifendurchläufe gezwungen, in denen er - außer sie stupide abzuarbeiten - nichts tut. Für einen so kleinen mit vielen Optionen vollgepfropften Arbeitsbolzen ist das klassische Ressourcenverschwendung.

Für eine LED, die im Sekundentakt blinken soll, wird der Controller 500 ms in eine Zeitschleife geschickt, ändert dann den Zustand der LED zum Beispiel von HIGH auf LOW und taucht dann wieder ab in eine zweite Zeitschleife von 500 ms, an deren Ende der Zustand der LED umgeschaltet wird. Während die Zeitschleife läuft, ist der Controller für andere Aufgaben blockiert.

Eine wesentlich bessere Lösung wäre, wenn der Controller eine innere Uhr in Gang setzte, die alle 500 ms ein Signal abgibt, dass den Zustand einer angeschlossenen LED umschaltet. Bis zum nächsten Zeitsignal widmet er sich wieder anderen Dingen. Wie man das umsetzt, wird im folgenden Kapitel Timer/Counter gezeigt.

Im diesem Abschnitt wurden die Op-Codes

  • SBIW - Subtract Immediate from Word
  • BRNE - Branch if not equal

eingeführt.

Weiter gehts mit AVR Studio - Teil 4.

Druckversion Druckversion | Sitemap
© Reinhard Rahner - Gettorf