Forum: Mikrocontroller und Digitale Elektronik AVR Assembler Interrupt verlassen


von Thomas M. (tmo)


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

von Commtel (Gast)


Lesenswert?

bin kein freund vom stack(Stapel) manipulieren.
ich setz ein bit in der interrupt routine
die in der main abgefragt wird bzw gelöscht wird.

c.u
commtel

von 2921 (Gast)


Lesenswert?

Ja, das macht man nicht so. Eine Taste auf einen Interrupt ist auch 
verschwendung. Wie Commtel schon sagte, die Taste(n) mit einem Timer 
abfragen und entprellen und im main auf eine Verzweigung

von jack (Gast)


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.

von Thomas M. (tmo)


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

von Karl H. (kbuchegg)


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.

von Jan (Gast)


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

von Commtel (Gast)


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

von Peter D. (peda)


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

von Thomas M. (tmo)


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

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Mach doch so, das du eine Falg sezt und ie Endlosschleife einfach 
solange läuft bis das Flag gesezt ist.

Ansosnten kannst du die Adresse eines Labels, z.B. in r17/r18 laden über

ldi r17, HIGH(label);
ldi r16, LOW(label);

von AVRFan (Gast)


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.

von Spess53 (Gast)


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

von Falk B. (falk)


Lesenswert?

@ Spess53 (Gast)

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

Auf gut deutsch eine Mehrfachverzweigung.

AVR-Tutorial: Mehrfachverzweigung

MFG
Falk

von Spess53 (Gast)


Lesenswert?

Hi

Tut mir leid. Aber ich habe das Tudorial nicht mal ansatzweise gelesen. 
Ist das jetzt Plicht?

MfG Spess

von Falk B. (falk)


Lesenswert?

@ Spess53 (Gast)

>Tut mir leid. Aber ich habe das Tudorial nicht mal ansatzweise gelesen.
>Ist das jetzt Plicht?

???
Es war lediglich ein Hinweis.

MFG
Falk

von Spess53 (Gast)


Lesenswert?

Hi

Den hättest du aber früher und jemand anders geben können.

MfG Spess

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.