Pfad: Home => AVR-Übersicht => Software Knowhow => Zeitschleifen

Design von Zeitschleifen

Hier wird erläutert, wie in Assembler exakte Zeitschleifen berechnet und programmiert werden.

Einfache Zeitschleife

Die einfachste Zeitschleife ist ein Zähler, der auf einen Anfangswert gesetzt wird und dann abwärts gezählt wird, bis er Null erreicht. Der Code einer solchen Schleife sieht so aus:

.EQU nLoop = 100 ; Anzahl Durchläufe durch die Schleife
.DEF rcnt = R16 ; Ein Register definieren
   ldi rcnt,nLoop ; auf Anfangswert setzen
loop:
   dec rcnt ; erniedrige Zähler
   brne loop ; springe falls nicht Null

Die Dauer einer solchen Schleife lässt sich aus der Dauer der Abarbeitung aller Befehle ermitteln. Die Dauer aller Befehle in Anzahl Takten des Prozessors lässt sich aus den Befehlstabellen im Datenbuch der AVRs nachlesen. Demnach braucht Eine solche Zeitschleife bringt dann folgende Verzögerung (in Takten): Die Anzahl Takte n ist also
   n = 1 + (nloop-1)*3 + 2
oder vereinfacht
   n = 3 * nloop
Im Beispielfall (mit nloop = 100) dauert die Schleife also 300 Takte. Die Verzögerungszeit ist dann natürlich von der Taktfrequenz abhängig. Jeder Takt braucht 1/Taktfrequenz Sekunden. Bei einer Taktfrequenz von z.B. 4 MHz dauert die Schleife dann
   t = 3 * nloop / 4.000.000 Sekunden
oder
   t = 75 µs
Maximal lassen sich mit dieser Methode Zeitverzögerungen von
   t = 192 µs
erreichen (bei 4 MHz).

Doppelte Zeitschleife

Für längere Zeiten wäre das Aneinanderfügen solcher Schleifen mühsam. Daher kommt hier das wiederholte Durchlaufen der Zeitschleife in Frage, das durch eine äußere Schleife vervielfacht wird, z.B. so:

.EQU nloop2 = 100 ; Anzahl Durchläufe äußere Schleife
.EQU nloop1 = 100 ; Anzahl Durchläufe innere Schleife
.DEF rcnt2 = R17 ; Register für äußere Schleife
.DEF rcnt1 = R16 ; Register für innere Schleife
   ldi rcnt2,nloop2 ; Anzahl außen setzen
loop2: ; Sprungziel zum Anfang der inneren Schleife
   ldi rcnt1,nloop1 ; Anzahl innere setzen
loop1: ; Sprungziel innere Schleife
   dec rcnt1 ; Erniedrige inneren Zähler
   brne loop1 ; Wiederhole falls nicht Null
   dec rcnt2 ; Erniedrige äußeren Zähler
   brne loop2 ; Wiederhole falls nicht Null


Das Ganze braucht folgende Taktzyklen: Insgesamt beträgt die Anzahl Takte also:
   n = 1 + (3*nloop2*nloop1) + 3*(nloop2-1) + 2
oder vereinfacht:
   n = 3 * nloop2 * (nloop1 + 1)

Setzen wir nloop2 und nloop1 auf den maximal möglichen Wert von 256 (entspricht dem Setzen auf Null zu Beginn der Schleife), dann erhalten wir bei 4 MHz Takt eine Verzögerung von
   t = 3 * 256 * 257 / 4.000.000
entsprechend
   t = 49,3 ms.

Dreifache Zeitschleife

Damit dürfte klar sein, dass wir mit einer dritten Zeitschleife operieren müssen, um in Regionen von Sekunden zu kommen. Das sieht dann so aus:

; Definitionen
.EQU nloop3 = 110 ; Dritte Schleife
.EQU nloop2 = 110 ; Zweite Schleife
.EQU nloop1 = 109 ; Erste Schleife
.DEF rcnt3 = R18 ; Drittes Register
.DEF rcnt2 = R17 ; Zweites Register
.DEF rcnt1 = R16 ; Erstes Register
;
; Beginn äußerste Schleife
   ldi rcnt3,nloop3 ; Laden drittes Register
; Beginn mittlere Schleife
loop3: ; Sprungziel Beginn mittlere Schleife
   ldi rcnt2,nloop2 ; Laden zweites Register
loop2: ; Sprungziel Beginn innere Schleife
   ldi rcnt1,nloop1 ; Laden erstes Register
loop1: ; Sprungziel innere Schleife
   dec rcnt1 ; Erniedrige erstes Register
   brne loop1 ; Springe falls nicht Null
   dec rcnt2 ; Erniedrige zweites Register
   brne loop2 ; Springe falls nicht Null
   dec rcnt3 ; Erniedrige drittes Register
   brne loop3 ; Springe falls nicht Null


Die Anzahl Takte errechnet sich hier nach
   n = 3 * nloop3 * (nloop2 * (nloop1+1) + 1)
Mit den gezeigten Einstellungen werden etwa eine Sekunde erreicht. Die maximal bei 4 MHz Takt erreichbare Verzögerungszeit beträgt bis zu 12,6 Sekunden.

Nachteile der gezeigten Methoden

Die Methode der Verzögerung mittels Schleifen hat folgende Nachteile: Um die Nachteile zu vermeiden, sollten Zeitschleifen wenn möglich mittels Timern erzeugt werden.

©2004 by http://www.avr-asm-tutorial.net