Forum: Mikrocontroller und Digitale Elektronik Programmablauf in AVR-Assembler


von Karl (Gast)


Lesenswert?

Hallo zusammen,

so langsam klappt es mit dem Programmieren des Mega8 immer besser, dank
Google, diversen Tutorials und selbstverständlich den hilfreichen
Antworten auf meine Fragen in diesem Forum.


Folgendes kleine Makro ist mir in diesem Forum als Delay empfohlen
worden. Es funktioniert hervorragend. Das I-Tüpfelchen wäre allerdings
jetzt noch, zu verstehen, warum das Makro funktioniert.

 .macro  mdelay
  ldi  r24, low( @0 - 7 )
  ldi  r25, high( @0 - 7 )
  sbiw  r24, 3
  brcc  pc - 1
  cpi  r24, 0xFE
  brcs  pc + 3
  nop
  brne  pc + 1
.endmacro

Insbesondere r25 wird in der 3. Zeile geladen, aber komischerweise
nirgendwo mehr verwendet.
Und pc, was vermutlich Programmcounter heisst springt in Zeile 7 und 9
an die gleiche Stelle.(Zeile 7 + 3 ist doch das gleiche wie Zeile 9
+1)

Ich bedanke mich schon mal für Eure Erklärungen.
Karl

von Peter D. (peda)


Lesenswert?

Laß es doch einfach mal im Simulator laufen.

Peter

von Tobi (Gast)


Lesenswert?

schau dir mal die beschreibung zu 'sbiw' genauer an. dann wirst du
drauf kommen

von Ingo Henze (Gast)


Lesenswert?

Naja, deshalb wäre es schöner (übersichtlicher,verständlicher), bei den
Doppelregisterbefehlen auch beide Register anzugeben, obgleich es nicht
zwingend erforderlich ist:

sbiw r25:r24,3

Gruß
Ingo

von Andi (Gast)


Lesenswert?

Mal was anderes:
Die Befehle SBIW und BRCC benötigen doch jeweils 2 Takte.
BRCC braucht 2 Takte, wenn die Bedingung Carry clear zutrifft was ja
meißt der Fall ist.
Müßte die "Warteschleife" dann nicht so aussehen damit es genau den
"Wartetakten" entspricht?

  sbiw  r24, 4
  brcc  pc - 1

Gruß
Andi

von Thomas O. (Gast)


Lesenswert?

Hallo,

ich habe heute auch ne gute Möglichkeit gefunden, zwar mit dem Timer
aber im Polling-Modus mit dem Compare-Match Interrupt ist das aber eine
super Funktion.

init:  lsi temp, 0b00000010 ;Vorteiler Timer0 auf CK/8 einstellen
       out TCCR0, temp

init_delay: clr temp        ;Setze Timerstand0 auf 0 zurück
            out TCNT, temp

            sbi PortB, LED ;Schalte LED ein
delay: in temp, TCNT0       ;Lade Timerstand nach temp
       cpi temp, 245        ;Vergleiche Timerstand mit Wert 245
       brlo delay           ;wenn nicht gleich wieder zu delay zurück
                            ;dadurch erreicht man dann eine Pause von
480µSek
       cbi PortB, LED

von Karl (Gast)


Lesenswert?

Hallo Peter,

ich hab das mit dem Debugger mal getestet. Wenn ich das Makro so wie es
sein sollte einbinde, springt mein F11 über das Makro drüber,ohne es
sichtbar zu durchlaufen.

Erst als ich die Makrodirektiven raus geworfen habe, so dass der
Makroinhalt quasi wie normaler Programmcode  durchlaufen wurde, hat das
geklappt.

Dadurch, durch Ingos Hinweis auf implizite Doppelregister und Andis
Hinweis auf die Anzahl der benötigten Takte ist mir einiges klarer
geworden.

Aber noch nicht so 100%ig.
Ich vesuche es noch mal mit meinen eigenen Worten zu erklären, so dass
Ihr mir letzte Denkfehler noch erklären könnt. (Wenn Ihr noch Nerv dazu
habt:

.macro  mdelay                     ; Klar
  ldi  r24, low( @0 - 7 )          ; Lädt den unteren Teil des 16Bit-
                                   ; Parameters ins Register r24

  ldi  r25, high( @0 - 7 )         ; Lädt den oberen Teil des
                                   ; übergebenen 16-Bit Param in r25
  sbiw  r24, 3
  ; Zieht vom Doppereg r24/25 (Wort) die drei ab und falls dabei
  ; der Wert 0 erreicht oder unterschritten wird, wird irgendein
  ; Bit im Statusregister gesetzt. (Wo erfährt man welches Bit das
  ;ist?) Die drei wohl deshalb, weil dieser Schleifendurchlauf 3
  ; Takte benötigt

  brcc  pc - 1
  ; Dieser Befehl springt, einen Programmschritt zurück, falls das
  ; Carrybit cleared (also Null?) ist. Dabei wird dieses Carrybit
  ; wahrscheinlich automatisch wieder gesetzt.
  ; Daraus kann ich schliessen, dass der vorhergehende Befehl das
  ; Carrybit beeinflusst.

  cpi  r24, 0xFE
  ; Vergleicht r24 mit der Zahl 2Dezimalzahl 254 (Warum 254?)
  ; Dabei wird wohl das Carrybit gesetzt, je nachdem wie der
  ; Vergleich ausgeht. (Aber wann wird es gesetzt oder cleared?)

  brcs  pc + 3
  ;Springt aus dem Programm heraus, sofern das Carrybit gesetzt ist
  ;Anderenfalls wird das Programm in der nächsten Zeile fortgesetzt

  nop
  ; einen Takt nichts tun.
  ; Ist wohl ein Korrekturtakt, damit das Programm wirklich punktgenau
  ; so lange delayed, wie man als Parameter übergibt.
  brne  pc + 1
  ; Springt zur nächsten Zeile wenn das Z-Bit gesetzt ist.
  ; (Und wenn nicht? Was macht es dann ? Es geht zum nächsten Befehl
  ; was ja genau das gleiche bedeutet. Warum also dieser Befehl?

.endmacro


Danke noch mal für die Antworten. Ich hoffe, dass ich noch mehr
Fragen stellen darf.  Eure armen Nerven ;-)

Viele Grüsse
Karl

von Peter D. (peda)


Lesenswert?

Wenn Du Dich wunderst, warum das Macro falsch ist, lies bitte hiervon
das 3. Posting:

http://www.mikrocontroller.net/forum/read-4-15758.html#new


In der Tat dienen alle Instruktionen nach der Schleife nur dazu, auf
den Takt genau zu sein.
Das war bei dem ersten AVR-Assembler notwendig.
Inzwischen erlaubt der Assembler komfortablere Macro-Befehle, so daß
man es heutzutage einfacher machen könnte.


Peter

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.