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.
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?
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
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.