rjmp Problem

OP #4214066
Lesenswert?
• ▲
▼
Hallo,
ich versuche gerade mein erstes Assembler Programm zu erstellen.
Hierzu habe ich vor eine LED Blinken zu lassen.
Das Programm läuft vorerst nur im Simulator.
Das Problem ist nun das das Programm nach dem ersten rjmp nicht weiter 
läuft sondern wieder unter "MainLoop" springt.
Wieso läuft das nicht weiter?
Hier der Code:
1
 .nolist
2
 .include <m8Adef.inc>
3
 .list
4
  
5
 .DEF reg16 = R16    ;definition Register16
6

7
 .EQU freq = 1000000  ;1 MHz itern
8
 .EQU ticksDelay = 0xff  ;ein Tick = 1µsec
9
  
10
 Start:          ;Start des Programms
11
  sbi DDRB, PB0    ;PORTB direction register laden PortB 0 = out
12
  cbi PORTB, PB0    ;PORTB bit 0 setzen
13
 
14
 MainLoop:
15
  ;LED ON
16
  sbi PORTB, PB0    ;PORTB bit 0 setzen
17
  ldi reg16, ticksDelay  ;Wert in Register laden
18
  rjmp Delay      ;Sprung zur Schleife
19
  
20
  ;LED OFF
21
  cbi PORTB, PB0    ;PORTB bit 0 rueck setzen
22
  ldi reg16, ticksDelay  ;Wert in Register laden
23
  rjmp Delay      ;Sprung zur Schleife
24

25
  rjmp MainLoop    ;Ruecksprung zur Hauptschleife
26

27
 Delay:
28
  dec reg16      ;runter zaehlen
29
  brne Delay      ;Jump wenn nicht Null
30

31
 End:          ;End des Programms
Könnte mir Jemand sagen was ich falsch mache?

Gruß Robert
#4214080
Lesenswert?
• ▲
▼
Das "End" ist doch nicht richtig.Es ist irgendwie ein Widerspruch zur 
Arbeitsweise eines Kontrollers. Der arbeitet immer in irgendeiner 
Endlosschleife, außer es wird die bei einigen Kontrollern mögliche 
HALT-funktion benutzt. END wird nicht in einen Maschinenbefehl 
umgesetzt. Es ist eigentlich nur ein Hinweis für den Programmierer, dass 
an dieser Stelle der text zuende ist.

nach brne Delay muss also die Alternative dazu stehen z.B. rjmp MainLoop
#4214086
Lesenswert?
• ▲
▼
Robert C. schrieb:
> Hallo Frank,
> Danke für die schnelle Antwort.
> Hatte schon versucht das rjmp durch rcall zu ersetzen und im Delay ein
> ret eingebaut.

Dazu musst du dann auch noch den Stackpointer initialisieren.
Aber prinzipiell ist das schon mal der richtige Weg.
Denn egal von wo der Aufruf von delay kommt, du willst ja wieder an 
diese Aufrufstelle zurück kommen. Ein rjmp springt einfach nur. Ein 
rcall hingegen springt zwar auch, legt aber die Adresse von wo der µC 
gekommen ist, auf den Stack, damit ein ret sich dann diese Adresse holen 
kann und mit dieser Information weiss, wohin er wieder zurckspringen 
muss.
Nur: dazu muss wiederrum der Stackpointer so initialisiert sein, dass 
der Stack auch dort liegt, wo es im µC Speicher gibt.

Wir haben ein so schönes Tutorial auf dieser Site.
Warum schaust du denn da nicht rein und arbeitest es (von vorne weg) 
durch?
AVR-Tutorial

> Hast du noch eine Idee?

Im Simulator ist der richtige Prozessor eingestellt?
Moderator Persönliche Seite #4214096
Lesenswert?
• ▲
▼
Robert C. schrieb:

> Hatte schon versucht das rjmp durch rcall zu ersetzen und im Delay ein
> ret eingebaut.

Im Prinzip ist das richtig, nur gilt es, da noch ein paar Regeln zu 
beachten. Ich kann daher nur Karl Heinz' Rat unterstützen, dass Du das 
AVR-Tutorial von Anfang an durcharbeitest.

Auch wenn ich Dir jetzt direkt das Kapitel vorsage

   https://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack

wo es drin steht, was bei Unterprogrammen zu beachten ist, empfiehlt es 
sich wirklich, es ganz von Anfang an zu lesen. Es lohnt sich.
#4214098
Lesenswert?
• ▲
▼
Dein Programmm muss bei der mit Delay beginnenden Routine ein ret als 
Ende haben und mit rcall delay aufgerufen werden. Dann läuft die 
hauptschleife ab, ständig mit delay unterbrochen.

Das Ganze geht aber sehr schnell, so etwas mehr als 520 µsec für ein 
bzw. aus

da leuchet die LED scheinbar nur mit halber Helligkeit.

Beweg mal, wenn möglich , die LED schnell hin und her. Vieleicht siehst 
Du dann anstelle eines leuchtenden Strichs eine Punktekette.
Moderator (Firma: Titel) Persönliche Seite #4214114
Lesenswert?
• ▲
▼
Peter R. schrieb:
> Vieleicht siehst Du dann anstelle eines leuchtenden Strichs eine
> Punktekette.
Bei knapp 1kHz? Das muss aber ein flottes Auge sein :-o

Und mit ein wenig Glück sind es gut 8kHz, weil zwar 1MHz angegeben ist, 
die Fuses aber immer noch auf 8MHz stehen...

Robert C. schrieb:
> Könntest du mir trotzdem einen Tipp geben wieso das nicht so läuft wie
> erwartet?
Das steht doch schon im 
Beitrag "Re: rjmp Problem"
Moderator Persönliche Seite #4214130
Lesenswert?
• ▲
▼
Robert C. schrieb:
> Ne Idee wieso das rjmp nicht geht wie erwartet?

Wenn Du nur mit rjmp arbeiten willst, dann kannst Du Deine Routine 
"Delay" niemals wiederverwenden.

Du willst:
1
         Sprung in Delay
2
LED an  ------------------ Warten ---
3
.                                    |
4
.       <----------------------------
5
.        Rücksprung in Hauptschleife hinter "LED an"
6
.
7
.        Sprung in Delay
8
LED aus ------------------ Warten ---
9
.                                    |
10
.        <----------------------------
11
.         Rücksprung in Hauptschleife hinter "LED aus"
12
.
13
Sprung nach oben

Wenn Du auf rcall/ret verzichtest, dann kannst Du nach Deiner 
Warteschleife nur noch an genau eine Stelle im Hauptpgrogramm per rjmp 
zurückspringen, nämlich entweder hinter "LED an" oder hinter "LED aus"

Das reicht aber nicht. Du musst einmal zurückspringen hinter "Led An" 
und einmal hinter "Led Aus".

Das geht nur mit rcall/ret und einem initialisierten Stackpointer. Den 
Link aufs Tutorial hatte ich auch schon verraten:

   https://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack

P.S.
Manche Dinge funktionieren auch nicht, wenn man mit dem Kopf durch die 
Wand will. Im Zweifel ist die Wand stärker.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren