Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupts per Programmcode auslösen?
Hallo zusammen,
ich habe eine Grundsätzliche Frage. Ist es möglich per Programm ein Interrupt-Flag zu setzen, so dass ein Interrupt ausgelöst wird und somit die ISR aufgerufen wird?
Kleines Beispiel:
on oc2 ISR_OC2
enable oc2
enable interrupts
do
tifr.ocf2 = 1
Wait 1
loop
ISR_OC2:
nop
Return
Funktioniert sowas? Kann man das mit jedem Interrupt machen, auch mit INT0 und INT1, oder gibts da irgendwelche Einschränkungen?
Hintergrund ist einen 2. Interrupt bedingt inerhalb einer gerade laufenden Interrupt-Routine zu iniziieren. Der Programmcode soll jedoch erst nach beenden der ersten ISR ausgelöst werden.
Gruß Mitch.
Besserwessi
14.01.2009, 22:34
Mit den normalen Interrupt flags kann man das so nicht machen. Im Datenlabtt steht das man gerade eine 1 reinschreiben muß um das Flag zu löschen.
Einige Interrupts wie die externen Interrupts kann aber künstlich auslösen indem man entweder die Bedingung für den Interrupt ändert, so das es paßt, oder indem man den Pin als Ausgang definiert und dann das passende ausgibt. Die externen Interrupts auf low werden aber nicht gepuffert. Dier werden also nur dann ausgefürt wenn der Pin nach der ISR noch auf low ist.
Alternativ könnte man doch gleich nach der 1. ISR in die 2 te ISR weiterspringen.
Besserwessi
14.01.2009, 22:35
Mit den normalen Interrupt flags kann man das so nicht machen. Im Datenlabtt steht das man gerade eine 1 reinschreiben muß um das Flag zu löschen.
Einige Interrupts wie die externen Interrupts kann aber künstlich auslösen indem man entweder die Bedingung für den Interrupt ändert, so das es paßt, oder indem man den Pin als Ausgang definiert und dann das passende ausgibt. Die externen Interrupts auf low werden aber nicht gepuffert. Dier werden also nur dann ausgefürt wenn der Pin nach der ISR noch auf low ist.
Alternativ könnte man doch gleich nach der 1. ISR in die 2 te ISR weiterspringen.
Wenn ich ein Flag (ext. Interrupt) durch schreiben einer 1 lösche, was passiert dann, wenn ich eine 0 rein schreibe?
Es würde mir schon reichen, wenn das mit den internen Interrupts geht. Im Simulator funktioniert das jedenfalls nicht.
Hallo Mitch64,
Probier doch mal Enable (Disable) Interrupts (oc2)?
Gruß, Michael
Ich will nicht im Mask-Register rumspielen.
Ich kenne Enable und Disable.
Das war nicht die Frage.
Hallo Mitch64,
wird der globale Interrupt beim Einsprung nicht automatisch "disabelt" und bei Return wieder "enabled"?
Gruß, Michael
Besserwessi
15.01.2009, 18:41
Die interrupt flag Register kann man nicht so direkt per software setzen. Die kann man über das Register nur löschen.
Der externe Interrupt hängt vom zusatd des Pins ab. Wieso der sich ändert ist egal. Es zählt also auch wenn der Pin als Ausgang definiert ist und man den Ausgangewert ändert. Wenn man auch noch echte externe Interrupts zulassen will, müßte man den über einen Widertand anschließen.
Was ich mich frage: Du könntest doch die Glob-Interrrupts disablen und dann die ISR-Routine direkt anspringen. (Gosub).
Welchen speziellen Effekt, der darüber hinausgeht, willst du denn erreichen ?
Also,
ich wollte nur wissen, kann ich einen Interrupt (z.B. OC2) per Software im Programmcode auslösen oder nicht. Ich habe gelesen, das dies bei den internen Interrupts geht. Mit den Externen Interrupts muß ich den pin eben als Ausgang schalten und dann das Signal entsprechend per Software schalten. Das ist es was ich wissen wollte. Danke schon mal für diese Infos. Das hilft mir schon mal weiter.
Der Grund warum ich denn einen Interrupt per Programm auslösen will ist, weil ich in einer ziemlich zeitkritischen Interruptroutine keinen zu langen Code schreiben kann. Ich kann aber dafür sorgen, dass Quasi Synchron der andere Programmteil gestartet wird. Sozusagen direkt danach. Der Gag ist aber, dass ich den 2. Programmteil nicht immer ausführen muß, sondern nur wenn bestimmte Bedingungen gegeben sind.
Um dies zu erreichen dachte ich an einen internen Interrupt, den ich einfach nur iniziiere, wenn es sein muß.
Übrigens:
Mit Gosub kann ich keine ISR-Routine aufrufen, da diese mit IRET abgeschlossen sein muß. Der Compiler macht das halt so, wenn eine Unterroutine als Interrupt-Sprungziel angegeben ist. Das würde zum Absturz des Controllers führen.
Der Unterschied zwischen RET und RETI ist nur, das letzerer auch das Glob-Int-Enable Flag wieder setzt. Da stürzt nix ab, wie auch.
Wenn das berücksichtigt wird, und das wäre es ja auch in diesem Fall, kann dir das nur recht sein.
EDIT: Vielleicht meinst du die alten Intels. die haben tatsächlich das statusregisrter zusätzlich zurückgeladen bei IRET, glaub ich mich zu erinnern
Besserwessi
15.01.2009, 20:12
In assembler get das in eine andere ISR zu springen. Man muß aber nur aufpassen, das die Register auf die gleiche Wiese wieder hergestellt werden. Wegen der Register auf dem Stack geht ein gosub nicht, höchstens ein goto. Soweit ich weiss werden von BASCOM immer alle Register gerettet da gibts also nur eine version. Mit GCC hätte man da Probleme.
Gerade wenn es zeitkritisch ist, ist der umweg über den extra Interrupt unpraktisch, denn in Basic braucht es recht lange bis alle Register rerettet und wieder hergestellt sind. Oft dauert das länger als die eigentliche ISR. Da wird es besser sein den Code einfach 2 mal da zu haben, wenn der Flash nicht zu knapp ist.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.