AVR Assembler Interrupt verlassen

OP #688768
Lesenswert?

Hallo,

ich habe folgendes Problem:

Ich möchte verschiedene Unterprogramme, die jeweils als Endlosloops 
laufen, über Tasteninterrupt der Reihe nach aufrufen.
Also z.B.: ich bin in prog1, drücke Taste und lande in prog2 usw.
Wie mache ich jetzt aber der Inerruptserviceroutine klar, daß ich nicht 
wieder an den Ursprungsort zurückkehren will?
Ich neheme an, ich muß irgenwie den Stapel manipulieren ...
Geht das überhaupt (z.B. mit tiny13 oder tiny25), oder bin ich da völlig 
auf dem Holzweg?

Bin für alle Tipps dankbar,

Gruß
Thomas
Gast #688784
Lesenswert?

>Wie mache ich jetzt aber der Inerruptserviceroutine klar, daß ich nicht
>wieder an den Ursprungsort zurückkehren will?

Der ISR brauchst Du das nicht sagen. In der ISR wertest Du lediglich die
Taste aus, die gedrückt wurde. Im Hauptprogramm (Endlosschleife)
wird in Abhängigkeit von der Tastennummer dann das dazugehörige
Unterprogramm angesprungen.
OP #688828
Lesenswert?

Ok, danke für die Antworten!
Also den Stack verbiegen tut man nicht ohne Not, hab ich verstanden.
Interrupts brauch ich nur einen, den kann ich in diesem Fall ja auch 
verschwenden.
Jetzt muß ich nur noch sehen, wie ich aus meinen Endlosschleifen in den 
Unterprogrammen regelmäßig im main nachfrage.
Ich denke, das krieg ich hin ...

Thomas
#688840
Lesenswert?

Thomas M. wrote:

> Jetzt muß ich nur noch sehen, wie ich aus meinen Endlosschleifen in den
> Unterprogrammen regelmäßig im main nachfrage.

Ganz einfach.
Mach in den Unterprogrammen keine Endlosschleifen.
Im ganzen Programm gibt es nur eine Endlosschleife und die
liegt in main
1
reset:
2
    ....   ; Hardware initialisieren
3

4
main:
5
    ....   ; was immer es auch zu tun gibt
6

7
    rjmp   main

Halte dich an diese Struktur und du hast weniger Probleme.
Gast #688852
Lesenswert?

Hallo,
Der Stackpointer ist eine Resource im AVR-Chip wie jede andere auch und
es gibt keinen Grund den Stackpointer nicht zu manipulieren.
Hauptsache man weiss und versteht was man da tut.

Um aus einem INT woandershin zurückzuspringen kannst du z.B.:
1. Alte Rücksprungadresse von Stack "poppen".
2. Neue Rücksprungadresse auf den Stack "pushen".
3. RETI Befehl ausführen

Geht bei allen AVRs die SRAM haben.

Gruß Jan
Gast #688863
Lesenswert?

@ jan

hast schon recht aber du hast selber geschrieben
> Hauptsache man weiss und versteht was man da tut.

aber es ist trotzdem nicht ohne!
klar bei so einer einfachen sache wie tatster ist das auch nicht so das 
ding
aber wie sieht es bei anderen progs aus
Ich würds nicht unbedingt tun wenn ich nicht in der klemme stecke
#688865
Lesenswert?

Jan wrote:
> Hallo,
> Der Stackpointer ist eine Resource im AVR-Chip wie jede andere auch und
> es gibt keinen Grund den Stackpointer nicht zu manipulieren.

Doch, den gibt es:
Man will sich nicht selber das Leben unnötig schwer machen.

Sobald Du Unterfunktionen verwendest, weißt Du nicht mehr, ob Du nun 2 
oder 4 Byte löschen mußt und auch, wenn Du Variablen pushst.

Programme haben die Angewohnheit zu wachsen und irgendwan fällst Du auf 
Deine eigenen Stackschweinereien herein (warum wird dieser Code nicht 
ausgeführt ? warum wird diese Variable überschrieben ? usw.).


Wenn es eine Lösung ohne Schweinereien gibt, dann sollte man immer diese 
bevorzugen.


Peter
OP #688866
Lesenswert?

Jan wrote:
1. Alte Rücksprungadresse von Stack "poppen".
2. Neue Rücksprungadresse auf den Stack "pushen".
3. RETI Befehl ausführen

Genau so dachte ich, daß es geht!
Woher habe ich aber die Adresse wo ich hinspringen will, wenn ich z.B. 
nach 'prog3:' will? Habe bisher leider nur wenig Erfahrung auf diesem 
Gebiet.

Thomas
Gast #688912
Lesenswert?

>1. Alte Rücksprungadresse von Stack "poppen".
>2. Neue Rücksprungadresse auf den Stack "pushen".
>3. RETI Befehl ausführen

das wird lustig, wenn Du das so machst.  Da Tasten prellen, wird es bei 
jedem Tastendruck mehrere Interruptauslösungen geben, und somit auch das 
zugehörige Programm bei jedem Tastendruck mehrmals gestartet werden. 
Tritt nun einer der Prellinterrupts zufällig dann auf, während sich das 
z. B. schon zum dritten mal gestartete Programm _in einer Subroutine 
befindet_, bleibt die zu dieser Subroutine auf dem Stack gespeicherte 
Rücksprungadresse für alle Zeiten dort liegen, weil ja nie ein 
Rücksprung aus dem Unterprogramm erfolgt (der Interrupthandler holt es 
"gewaltsam" dort heraus, ohne an die Unterbrechungsstelle 
zurückzukehren).  D. h. es kann sein, dass mehr als eine alte 
Rücksprungadressen zu poppen wären.  Wenn Du dann nur eine poppst, würde 
Dein Stack evtl. mit jedem Tastendruck anwachsen. Um das zu verhindern, 
müßtest Du am Ende des Interrupthandlers eine absolute Stackadresse 
beschreiben, und den Stackpointer darauf setzen.  Vielleicht würde das 
tatsächlich funktionieren, vielleicht aber auch nur ein anderes Problem 
nach sich ziehen - ich weiß es nicht.

Viel Spaß :-)

PS: Gute Lösungsmöglichkeiten für Deine Aufgabe hast Du ja schon 
ausreichend genannt bekommen.
Gast #689178
Lesenswert?

Hi

Ich bin zwar auch für jede Schwein... in Assembler zu habe, aber hier 
würde ich eine andere Methode benutzen:

In der Isr nur die Tastennummer feststellen und in einem Register oder 
Ram speichern. Im Hauptprogramm eine Sprungtabelle für die 
Unterprogramme. Wenn eine Taste erkannt wurde Z mit dem Anfang der 
Sprungtabelle laden, Tastennummerx2 dazu addieren und icall ausführen. 
Bei Änderung der Tastennummer Unterprogramm verlassen und Prozedur von 
vorn ausführen.

Das ist wesentlich weniger fehlerträchtig, leicht zu erweitern und man 
vermeidet ellenlange Vergleiche.

MfG Spess

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