www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR Assembler Interrupt verlassen


Autor: Thomas M. (tmo)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Commtel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: 2921 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Thomas M. (tmo)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

reset:
    ....   ; Hardware initialisieren

main:
    ....   ; was immer es auch zu tun gibt

    rjmp   main

Halte dich an diese Struktur und du hast weniger Probleme.

Autor: Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Commtel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thomas M. (tmo)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: AVRFan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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

MfG Spess

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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

MfG Spess

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.