Hallo zusammen,
ich habe ein Verständnisproblem und würde mich freuen, wenn man mir
helfen könnte. Ich programmiere in C. Wenn ich einen Interrupt auslöse,
springt das Programm nach dem Durchlauf ja wieder an die Stelle, wo der
Interrupt ausgelöst wurde. Kann man auch einen Interrupt auslösen, ohne
das er sich merkt wo er gewesen ist? Das heißt, das Programm soll nach
dem Interrupt einfach weiter laufen. Wäre für jede Antwort dankbar
> Das heißt, das Programm soll nach> dem Interrupt einfach weiter laufen.
Wo soll er denn weiterlaufen?
Wenn die Interruptfunktion zu Ende ist, muss es ja irgendwo weitergehen.
Nur wo soll das denn sein, wenn nicht an der Stelle an der das
Hauptprogramm unterbrochen wurde?
Hallo Thomas,
was genau willst Du damit bezwecken?
Das Programm läuft an der Stelle weiter, an der es unterbrochen wurde!!!
Welcher Sinn steckt hinter Deiner Frage....
Zu deiner Frage habe ich ein Verständnisproblem.
Du sagst ja selbst, nach dem Ausführen der Interrupt-Routine springt der
Prozessor wieder an die Stelle, an der der Interrupt ausgelöst wurde.
Das hat eben genau zur Folge, dass dein "eigentliches" Programm so
weiterläuft, als sei es nie vom Interrupt unterbrochen worden.
thomas wrote:
> Interrupt ausgelöst wurde. Kann man auch einen Interrupt auslösen, ohne> das er sich merkt wo er gewesen ist?
Nein.
> Das heißt, das Programm soll nach> dem Interrupt einfach weiter laufen.
Das nennt sich dann Chaos-Programmierung.
Du wirst mit diesem Ansatz nicht glücklich, sobald das Projekt etwas
größer wird.
Wenn jeden Augenblich jede mögliche Task abgeschossen wird, kann man
keine vernünftige Funktion erreichen.
Versuch mal mit Word einen Brief zu schreiben und ein anderer drückt
ständig Alt-F4. Dann weißt Du wie sich die CPU bei Deinem Ansatz fühlt.
Peter
Also ich habe folgendes Problem:
Alle fünf Sekunden schicke ich über die Uart einen AT Befehl zu einem
GSM Modul um die Netzqualität zu überprüfen. Jetzt rufe ich das Modul an
und will einen anderen Interrupt auslösen, was auch funktioniert. Aber
wenn ich genau dann anrufe, wenn der erste Interrupt ausgelöst wird,
dann springt er im 2Interrupt an die Stelle des ersten Interrupts,
obwohl der zweite Interrupt noch nicht komplett Abgearbeitet ist! Ich
hoffe ihr könnt verstehen was ich meine, ist ein bischen doof zu
erklären.
Ich probiere es noch mal anders:
Nach fünf Sekunden schicke ich at+csq ab und erhalt als Antwort 19,0
alles super!
Dann rufe ich das Modul an erkennt, das ich z.B. nicht autorisiert bin
und legt mit at+chup wieder auf. Erkennen kann ich das daran, dass ich
"OK" zurückbekomme wenn at+chup erfolgreich war.
Jetzt passiert folgendes: Nach fünf Sekunden schickt das Programm at+csq
jetzt rufe ich an, dann macht das Programm at+chup und jetzt kommt kein
OK sonder z.B 17,00 (Signalstärke) und das Programm hängt sich auf.
Ich habe probiert den Interrupt zu sperren cli() vor dem Befehl at+chup
und danach wieder frezugeben mit sei(), aber trotzdem taucht der Fehler
auf.
Meine Glaskugel sagt mir, daß das alles überhaupt nichts mit Interrupts
zu tun hat, sondern schlicht und einfach an einer völlig ungeeigneten
Programmstruktur liegt.
Zumal auf einem AVR, auf dem die Befehle cli und sei Sinn machen würden,
eine ISR nicht freiwillig für eine andere unterbrochen wird.
Also wie immer: Zeig mal den Code.
Oliver
Ich werd zwar aus deiner Beschriebung nicht wirklich schlau, aber eines
ist sicher: Deine Software-Architektur stimmt nicht. Mit deinem
Interrupt-Return verbiegen löst du das eigentliche Problem nicht.
Ein Haus, das auf Sand gebaut ist, kann man zwar mit Holzbalken
abstützen. Das wird aber immer Stückwerk bleiben. Besser ist es das
Haus abzureissen und zuallererst mal ein vernünftiges Fundament bauen.
In deinem Fall klingt das für mich:
Du hast dir nicht richtg überlegt, wie man einen µC dazu bringen kann,
einzelne Tasks geordnet nacheinander abzuarbeiten. Das Stichwort dazu
lautet: Job-Flags.
Ein Interrupt macht so gut wie keine Arbeit selber, sondern er setzt ein
Jobflag, welches der Hauptschleife mitteilt, dass es wieder mal Zeit
wäre die Signalqualität zu überprüfen.
Die Hauptschleife registriert dieses Ansinnen anhand des Jobflags und
entscheidet, dass genau das zum jetzigen Zeitpunkt nicht machbar ist,
weil da noch ein Anruf in der Bearbeitung steckt. Oder umgekehrt: Das
ein Anruf reinkommt, der aber momentan nicht bearbeitet werden kann,
weil gerade eine Signalqualitätsprüfung läuft.
Dein Problem ist ganz einfach, dass die linke Hand nichts davon weiß was
die rechte Hand gerade macht. Die Lösung kann aber nicht lauten: Dann
hauen wir halt mal auf die Finger. Die Lösung kann nur lauten: Es
braucht eine Einrichtung, die die beiden Aktivitäten koordiniert.
(Oder so ähnlich. Wie gesagt, ich werde aus dem Zeugs da oben nicht
wirklich schlau)
Ich darf leider nicht viel an Programmcode posten, aber ich kann die
Struktur erklären, vielleicht liegt da ja der Hund begraben.
ISR(USART0_RXC_vect)
{
flag=1;
}
ISR(USART1_RXC_vect){}
ISR(TIMER2_OVF_vect)
{
time++;
}
int main()
{
if(flag==1)
{ mache was
;
;
;
;
;
flag=0;
}
if(time==5)
{
uart0_puts("at+csq\r");
}
wenn ich jetzt anrufe, dann wird über die uart0 vom gsm modul ein string
rübergeschickt, also flag =1
}
ist das schon eine schlecht struktur?
wenn ja, wie sieht denn ein e gute struktur aus?
thomas wrote:
> ISR(USART0_RXC_vect)> {> flag=1;> }> ISR(USART1_RXC_vect){}
Das ist tödlich! Die Interrupt Flags RXC0/1 werden erst dann gelöscht,
wenn das UDR ausgelesen wird. Im Interrupt Handler muss deshalb UDR0
bzw. 1 ausgelesen werden, sonst wird er immer wieder aufgerufen.
Dass das Programm / der µC sich aufhängen, wenn zwei Interrupt Handler
ständig wieder aufgerufen werden und zwischen ihnen nur jeweils ein
einzelner Befehl im Hauptprogramm bearbeitet wird, ist hoffentlich
klar...
>Ich darf leider nicht viel an Programmcode posten
Was ist das für eine Geheimprogrammierung? Willst Du ne fundierte
Antwort oder sollen alle raten, was Du falsch machst?
- Aufgabenstellung verständlich erklären
- Fakten auf den Tisch legen
- Frage in verständlichem Deutsch formulieren
So klappts auch mit den Interrupts.
Hallo Johannes, heißt das, dass der Interrupt sozusagen zu lange
ausgeführt wird? Bezw. zu oft? Wie müsste den dann der Händler aussehen?
Danke im voraus!
thomas wrote:
> Hallo Johannes, heißt das, dass der Interrupt sozusagen zu lange> ausgeführt wird? Bezw. zu oft? Wie müsste den dann der Händler aussehen?> Danke im voraus!
Schreib ich chinesisch? Ich habe oben geschrieben, dass in den beiden
Inerrupt Handlern das dazugehörige Datenregister ausgelesen werden muss,
damit das jeweilige Interrupt Flag gelöscht wird. Das kann doch nicht so
schwer zu verstehen sein...
Noch mal: Wenn einer der beiden Interrupts auftritt, wird das
dazugeörige Flag gesetzt und der Handler ausgeführt. Wenn der Handler
beendet wird, ohne dass das Datenregister gelesen wurde, ist das Flag
nach dem Rücksprung noch gesetzt und der Handler wird praktisch sofort
wieder aufgerufen, und zwar so lange, bis das Programm irgendwann mal an
einer Stelle anlangt, wo das UDR ausgelesen und damit das Flag gelöscht
wird!
Johannes M. wrote:
> thomas wrote:>> ISR(USART0_RXC_vect)>> {>> flag=1;>> }>> ISR(USART1_RXC_vect){}> Das ist tödlich! Die Interrupt Flags RXC0/1 werden erst dann gelöscht,> wenn das UDR ausgelesen wird. Im Interrupt Handler muss deshalb UDR0> bzw. 1 ausgelesen werden, sonst wird er immer wieder aufgerufen.
Ich denke mal, dass hier thomas aus 'Geheimhaltungsgründen' wieder mal
einiges nicht gezeigt hat.
Daher wieder mal der Appell: zeig deinen richtigen Code, nicht etwas was
so aussieht oder so ähnlich ist oder fast dem entspricht was du hast.
Abspecken auf das Notwendigste macht Sinn, aber die relevanten Sachen
genau so präsentieren wie sie wirklich im Code sind.
Und Freunde: Kommt nicht immer mit diesem Geheimhaltungsquatsch.
Entweder ihr dürft in der Öffentlichkeit nach Hilfe fragen oder ihr
dürft es nicht. Kein Mensch wird aus diesem Forum ein kommerzielles
Projekt, das noch in der Entwicklungsphase steckt, klauen.
thomas wrote:
> Es ist doch so, dass in den Interrupt Routinen so wenig wie möglich> stehen soll, damit die Zeit so kurz wie möglich gehalten wird, oder?
Aber das UDR muss trotzdem im Interrupt Handler gelesen werden. Und
wenn Du das nicht tust, wird es nicht funktionieren! Ansonsten muss ich
Karl heinz zustimmen...
Doch das ist alles was in der Interrupt Routine steht!
Wenn etwas über Uart0 empfangen wird, wird flag=1, und im Hauptrpogramm
wird dann alles weitere Gehändelt, wie die einzelnen Zeichen über uart1
ausgeben.
Ich wusste nicht, das man das UDR im Interrupthändler auslesen muss! das
Probiere ich mal aus