Path: Home => AVR-Überblick => Zeitschleifen => N-Bit mit SBC    (This page in English: Flag EN) Logo
Zeitschleife

Sehr einfache Zeitschleife mit ganz vielen Bits für lange Zeiten in AVR Assembler

Es gibt noch eine weitere Zeitschleifen-Methode, die sich den besonders cleveren Befehlssatz der AVR zunutze macht: das fortgesetzte Subtrahieren von Null mit Carry. Es geht für einen 32-Bit-Zähler so:

.equ zaehler = 12345678
  ldi R17,Byte1(Zaehler) ; 1 Takt
  ldi R18,Byte2(Zaehler) ; +1 = 2 Takte
  ldi R19,Byte3(Zaehler) ; +1 = 3 Takte
  ldi R20,Byte4(Zaehler) ; +1 = 4 Takte
Schleife: ; Schleifentakte
  clr R16 ; +1 = 1 Schleifentakt
  sec ; +1 = 2 Schleifentakte
  sbc R17,R16 ; +1 = 3 Schleifentakte
  sbc R18,R16 ; +1 = 4 Schleifentakte
  sbc R19,R16 ; +1 = 5 Schleifentakte
  sbc R20,R16 ; +1 = 6 Schleifentakte
  brne Schleife ; +1 beim letzten Durchlauf = 7 Schleifentakte, +2 bei allen anderen = 8 Schleifentakte
  ; Ende des Schleifenzaehlers

Zu Beginn wird der Schleifenzähler in den Registern R20:R19:R18:R17 auf eine Zahl gesetzt. Werden statt der Register R16 bis R20 solche aus dem unteren Registerbereich gewählt, müssen die Zählregister mit MOV aus einem oberen Register geladen werden. Das braucht dann 8 Takte (4 für LDI, 4 für MOV).

Jetzt kommt die Schleife. Zuerst wird mit CLR R16 die Z-Flagge gesetzt und eine Null in das Register geschrieben. Mit SEC wird die Carry-Flagge gesetzt. Mit vier SBC wird jeweils Null und die Carry-Flagge abgezogen. Ist am Ende die Z-Flagge nicht gesetzt, geht es wieder an den Anfang der Schleife. Nur bei gesetzter Z-Flagge ist die Schleife fertig.

Der Algorithmus macht sich eine Besonderheit der Z-Flagge bei den SBC zunutze. Wenn vor dem SBC die Z-Flagge nicht gesetzt ist, wird sie selbst dann nicht gesetzt, wenn beim SBC Null herauskommt. Oder anders ausgedrückt: die Z-Flagge bleibt nur dann gesetzt, wenn sie auch schon vorher gesetzt war UND wenn beim SBC Null herauskommt. Ein einziger Nicht-Null-Fall in der Vierkette an SBCs löscht daher die anfangs mit CLR gesetzte Z-Flagge und alle nachfolgenden SBC können daran dann auch nichts mehr ändern. Einfach nur clever!

Die Formel zur Zeitberechnung ist recht viel einfacher als bei anderen Methoden. Sie lautet
N = 4 + (Zaehler - 1 ) * 8 + 7 = 8 * Zaehler + 3

Umgekehrt kriegen wir den Zähler aus einer vorgegebenen Anzahl an Takten N mit
Zaehler = (N - 3) / 8

Brauchen wir also 1.000.000 Takte Verzögerung, dann kommt für den Zähler 124.999,625 heraus. Für Grobmotoriker reichen 124.999 oder 125.000 aus, der sehr penible Takt-Erbsen-Zähler macht am Anfang noch fünf NOP dazu und nimmt 124.999.

In die 32 Bits passen Zahlen bis zu 4.294.967.295, was dann bei 1 MHz Takt mal eben bis zu 1,9 Stunden Zählzeit entspricht und auch höchsten Ansprüchen gerecht wird. Wer's noch länger braucht, fügt weitere Zählbits und SBCs dazu und korrigiert die Formel ein wenig.

An den Seitenanfang

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