Die Warteschleife in Assembler

Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 734
Registriert seit: Apr 2014
Bewertung: 5
#1
28.06.2015, 14:09

Hallo zusammen,

Warteschleifen sind für einen AVR (eigentlich für jeden Prozessor) Schwerstarbeit. Muss er doch eine schier unglaublich lange Zeit ausharren und im Kreis laufen.

Dennoch werden ganz häufig Warteschleifen benötigt. Sei es, um im Initialierungsprozess einer angeschlossenen Hardware ein gewisses Timing einzuhalten, oder um auf einer Anzeige einen Text blinken zu lassen oder oder oder.... Da fallen Euch sicher weitere Anwendungsgebiete ein.

Ich möchte an dieser Stelle einfach das Prinzip einer Warteschleife vorstellen. Es ist im Grunde ganz einfach:

Das folgende kleine Programm wartet auf einem mit 8 MHz getakteten AVR 2 Sekunden (oder eben 16.000.000 Takte)

 
; =============================
; Warteschleifen-Generator
; 16000000 Zyklen:
; -----------------------------
; warte 15999993 Zyklen:
ldi R17, 0x53
WGLOOP0: ldi R18, 0xFB
WGLOOP1: ldi R19, 0xFF
WGLOOP2: dec R19
brne WGLOOP2
dec R18
brne WGLOOP1
dec R17
brne WGLOOP0
; -----------------------------
; warte 6 Zyklen:
ldi R17, 0x02
WGLOOP3: dec R17
brne WGLOOP3
; -----------------------------
; warte 1 Zyklus:
nop
; =============================
 
 

Diese Schleife ist das Ergebnis eines Schleifengenerators, den man hier: Schleifengenerator finden kann.

Auf der Internetseite wird alles erklärt.

Natürlich sollte man, wenn möglich, auf Schleifen grundsätzlich verzichten. Schließlich bremst man den Prozessor damit aus. Es macht ja nicht wirklich Sinn, den Prozessor mit 20 MHz zu takten um ihn dann mit Schleifen soweit runter zu bremsen, dass dieser deshalb ins Schwitzen kommt. Big Grin
-----

Klopapier beidseitig verwenden und der Erfolg liegt auf der Hand!
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 734
Registriert seit: Apr 2014
Bewertung: 5
#2
27.01.2016, 13:07

Hallo zusammen,

das vorige Beispiel war ja das Ergebnis eines Schleifengenerators und ist deshalb auch recht starr. Eine etwas flexiblere Form stelle ich Euch nun vor:

 
; warteex10ms - Wartet 10 ms * Faktor
; Der Faktor steht im Register R16
waitex10ms: tst R16
breq waitex10msc ; Wenn R16 = 0 dann raus

push R16 ; Register auf den Stapel
push R24
push R25

waitex10msa: ldi R24,LOW(takt/400) ; "takt" muss zuvor festgelegt sein
ldi R25,HIGH(takt/400) ; bei 20 MHz ergibt sich ein Wert von 50.000

waitex10msb: sbiw R24,1 ; 2 Takte (R24 = R24 -1)
brne waitex10msb ; 2 Takte (Wiederholung bis R24 <= 0)

dec R16 ; Faktor = Faktor - 1
brne waitex10msa ; Und nächster Durchlauf

pop R25 ; Registerinhalte wieder herstellen
pop R24
pop R16

waitex10msc: ret ; Ende

 

Die Code-Darstellung im Forum ist etwas gewöhnungsbedürftig. Tabulatoren werden offensichtlich nicht richtig dargestellt. Dodgy

Egal... Ich hoffe, Ihr könnt den Ansatz erkennen. Der dargestellte Code lässt bei Faktor = 255 eine Verzögerung von 2,5 Sekunden zu.

Gruß
Uni
-----

Klopapier beidseitig verwenden und der Erfolg liegt auf der Hand!
Zitieren


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste