Pfad:
Home =>
AVR-Übersicht =>
Software Knowhow =>
Zeitschleifen => Design von 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
- ldi einen Takt,
- dec ebenfalls einen Takt,
- brne einen Takt, wenn nicht gesprungen wird, und zwei Takte im Fall
eines Sprungs.
Eine solche Zeitschleife bringt dann folgende Verzögerung (in Takten):
- ein Takt für den ldi-Befehl,
- (nloop-1) mal einen Durchlauf durch die Schleife mit Sprung, zu je
drei Takten (1 Takt dec, 2 Takte brne mit Sprung), entsprechend 3 * (nloop
- 1) = 297 Takte,
- einen Durchlauf durch die Schleife ohne Sprung, mit zwei Takten
(1 Takt dec, 1 Takt brne ohne Sprung).
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:
- einen Takt für das Laden des äußeren Zählers,
- nloop2 Durchläufe der inneren Schleife, also nloop2 mal die
Dauer der inneren Schleife, die ja 3*nloop1 beträgt,
- (nloop2 - 1) Durchläufe des Restes der äußeren
Schleife, also ein dec und ein brne mit Sprung mit zusammen drei Takten,
- ein Durchlauf des Restes der äußeren Schleife, also ein
dec und ein brne ohne Sprung mit zusammen zwei Takten.
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:
- Der Prozessor tut während dieser Zeit nichts anderes, er ist
ausschließlich mit Zählen beschäftigt.
- Der Stromverbrauch des Prozessors ist maximal.
- Interrupts würden entsprechend ihrer Dauer das Timing
stören und können nicht sinnvoll mit Zeitschleifen kombiniert
werden.
Um die Nachteile zu vermeiden, sollten Zeitschleifen wenn möglich
mittels Timern erzeugt werden.
©2004 by http://www.avr-asm-tutorial.net