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
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
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
>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.
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
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.
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
@ 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
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
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
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);
>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.
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
@ 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
Hi Tut mir leid. Aber ich habe das Tudorial nicht mal ansatzweise gelesen. Ist das jetzt Plicht? MfG Spess
@ 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.