PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Sprung aus Interrupt



Picht
05.06.2007, 17:25
Hallo Profis,
Ein Interrupt unterbricht eine Sub-Funktion.
Ich will aber nach den Interrupt zu einer anderen Stelle
ins Hauptprogramm springen.
Mit Goto kriege ich das nicht hin.Geht das überhaupt

Wigbert

Yossarian
05.06.2007, 18:48
Hallo
Das sollte schon gehen.Du solltest nur darauf achten,daß entsprechende Interrupflags zurückgesetzt werden und die Return Adresse vom Stack gezogen wird
(bzw. der Stackpointer dekrementiert oder inkrementiert -je nach Prozessor- wird).
Mit freundlichen Grüßen
Benno

Picht
05.06.2007, 19:26
Hallo Yossarian,
soviel Fremdwörter in einem Satz.
Also ich muss drauf achten, dass nichts überschwappt. ich sags mal so.
Wie setze ich die Interruptflags zurück?

Wigbert[/code]

Gento
05.06.2007, 20:10
Einfache Lösung:

Im Interrupt Flag setzen z.B. War_drin=1


in der Sub 'öfter' abfragen

if War_Drin=1 then
War_drin=0
exit Sub
end if

und in der Haubtschleife entsprechend hin wo Du willst.

Gento

Yossarian
05.06.2007, 20:11
Hallo
Indem die entsprechenden bits in den entsprechenden Registern gelöscht werden.
Mit freundlichen Grüßen
Benno

Picht
06.06.2007, 14:17
Dank Euch,
ich habe festgestellt, wenn ich aus dem Interrupt springe,
wird der nicht mehr ausgefuhrt.Ist das richtig?

Wigbert

wkrug
13.06.2007, 13:08
Wenn Du einen Interrupt ausführst wird automatisch das Interrupt ENABLE Flag im Status Register gelöscht und somit keine weiteren Interrupts zugelassen.
Das könnte man zwar mit "SEI" wieder ändern ist aber nicht ganz ungefährlich.
Du kannst nicht einfach aus einer Interruptroutine in einen Hauptprogrammanteil springen. Nach ein paar Interrupt Aufrufen läuft dir dein Stack über und der Controller macht nur noch Mist.

Die einzige gerade noch zu akzeptierende Möglichkeit wäre im Interrupt eine Stack Manipulation durchzuführen, die die Rücksprungadresse ändert, ob das aber mit BASCOM hinzukriegen ist kann ich nicht beantworten.

Sub Routinen kann man natürlich aus Interrupts heraus aufrufen, wenn Sie sauber mit RET wieder beendet werden.
Allerdings sollte auch hier gelten im Interrupt so wenig wie nur irgendwie möglich Code ausführen zu lassen. Ausserdem sollte die Subroutinentiefe nicht zu hoch werden, weil jeder erneute nicht abgeschlossene Subroutinen Aufruf den Stack zumüllt.

Vitis
13.06.2007, 13:28
aus nem Interrupt, der in nem beliebigen Teil des Codes ausgelöst wird
zu einer bestimmte Stelle ausspringen macht wenig Sinn und ist mE
ziemlich schlechter Stil.
Wie geschrieben, Stack overflow und ganz unliebsame Nebeneffekte können
da die Folge von sein. Nein, das macht man nicht, auch wenns prinzipiell
möglich ist.
Eine Erklärung zum Interupt:
Ein Interrupt wird für gewöhnlich von einer HArdwarekomponente des
µC ausgelöst. TWI, UART, INT0, INT1, SPI, Timer0, Timer1, Timer2 etc.
Der Controller macht dann folgendes. Er springt aus dem laufenden
Programmteil raus (vorausgesetzt er ist nicht gerade in einer
Interruptroutine), merkt sich wo er war, schaut welches Unterprogramm
bei genau diesem Interrupt ausgeführt werden soll, springt dann genau
da hin, arbeitet das Unterprogramm ab, löscht den jeweiligen Flag,
schaut wo er zuletzt tätig war im Hauptprogramm, springt aus der
Interrupt Routine raus an die ursprüngliche Programmstelle zurück
und werkelt dann fröhlich weiter bis zum nächsten Interrupt.

falerion
13.06.2007, 13:48
Warum nicht einfach in der Interruptroutine eine Variable setzen (a=1) und dann im Hauptprogramm immer mal wieder überprüfen ob a nun 1 ist und entsprechend das Hauptprogramm verzweigen, anstatt direkt aus der Interruptroutine dorthin zu springen.

Vitis
13.06.2007, 15:10
GENAU so wirds gemacht. Man setze ein Flag :)
und schon ist die ISR schön kurz.

Picht
13.06.2007, 20:15
Hallo,
in der Interruptroutiene setze ich ein Flag a=1 richtig
wo setze ich den Flag zurück? a=0
ist mein Bz richtig?



Bz:

Do
'mein Programm
'wait 1
dahin;
'dein programm
If a=1 then
goto
dahin
loop
end

int1: 'interrupt
pinb.1 =0
If pinb.1 = 1 then
a=1
else
a=0
end if

wigbert

falerion
13.06.2007, 21:00
In der Schleife direkt nach der Abfrage If a=1 die Variable zurücksetzen

Do
'mein Programm
'wait 1
dahin;
'dein programm
If a=1 then
a=0 'variable zurück setzen
goto
dahin
loop
end



(ob die syntax stimmt kann ich Dir leider nicht sagen, aber das Prinzip sollte so funktionieren)

Picht
13.06.2007, 21:06
Dank Dir Falerion,
jetzt muss aber die Hauptschleife sich bis zur Flagabfrage
durcharbeiten,oder geht das noch anders.

Wigbert

falerion
13.06.2007, 21:52
Ja, das muss Sie allerdings.

Ich weiß ja nicht, wie Deine Hauptschleife aufgebaut ist, aber evtl. kannst Du die Abfrage ja an mehreren Stellen einfügen.
Vielleicht am besten eine Funktion schreiben, die das prüft und dann gegebenenfalls das goto ausführt. Und diese dann in der Hauptschleife aufrufen. Du mußt abwägen zwischen der Häufigkeit der Prüfung auf das Flag und den anderen Aufgaben, welche Deine Hauptschleife erfüllt.

Was soll nach dem Interupt den ausgeführt werden? Kann man das nicht evtl. auch in eine Funktion packen und somit auf das goto evtl. ganz verzichten?

Falerion

wkrug
13.06.2007, 23:08
Ich hab mal eine rein Flag gesteuerte Hauptroutine in Assembler gebastelt.
Die Hauptroutine bestand nur aus Abfragen, ob bestimmte Flags gesetzt waren und CALL Sprüngen für die entsprechende Verarbeitung.

Die Hauptroutine wird somit sehr schnell durchlaufen und die Subroutinen nur bei Bedarf angesprungen. Die Hauptroutine wird dadurch auch sehr übersichtlich.

Der Vorteil ist auch, das man die Subroutinen anpassen kann ohne die Hauptroutine zu verändern.

Picht
14.06.2007, 11:08
Hallo,
wkrug +falerion dank Euch.
Es ging mir genenrell um Sprung bzw Flag,
da ich das noch nie gemacht habe.


Wigbert