Hi Wenn ich den Externen Interrupt auslöse, wird "Funktion ()" in einer Endlosschleife ausgeführt. Wie kann ich das Verhindern? Hier mein kurzer Code: int main (void){ //Initzialisierung der Interrupts MCUCR = (1<<ISC01) | (1<<ISC00); GICR = (1<<INT0); sei(); } ISR(INT0_vect) //externer Interrupt auf Pin INT0 { Funktion (); } Vielen Dank!
Was für einen Controller verwendest Du? Nimmst Du da nicht die falschen Register? Anstatt des MCUCR müsstest Du doch das EICRA nehmen.
Also eigentlich:
1 | int main (void){ |
2 | |
3 | //Initzialisierung der Interrupts
|
4 | EICRA = (1<<ISC01) | (1<<ISC00); |
5 | EIMSK = (1<<INT0); |
6 | sei(); |
7 | |
8 | }
|
9 | |
10 | ISR(INT0_vect) //externer Interrupt auf Pin INT0 |
11 | {
|
12 | Funktion (); |
13 | }
|
Aber das kommt auf Deinen Controller an.
Hi Der Prozessor macht 100% einen Rücksprung aus der Funktion. Hab das ganze schon mit nem LCD und Textausgabe getestet. Habe folgendes gemacht um es zu Testen: ISR(INT0_vect) //externer Interrupt auf Pin INT0 { ...LCD Ausgabe "start" Funktion (); ...LCD Ausgabe "ende" while(1) {; } } Mit der Eingebauten Endlosschleife wird die Funktion nur einmal ausgeführt - ist aber nicht sinn und Zweck meines Programms. mfg
Das weiss ich bei deinem µC bzw. Compiler nicht. Bei PIC's/Assembler muss man die Flags löschen, bzw. sie werden bei bestimmten Aktionen gelöscht. Z.B. wird das USART RXIF durch lesen des RX-Registers gelöscht (wenn ich's richtig in Erinnerung habe).
Ja, zum Beispiel bei ARM geschieht das nicht automatisch. Und solange man da das Flag/Bit der Quelle, welche den Interrupt ausgelöst hat, nicht zurücksetzt, wird sofort nach Rücksprung aus der Interrupt-Routine wieder ein Interrupt ausgelöst.
Kann mir jemand sagen wie das für einen Atmega32 unter C funktioniert? mfg
Das hängt davon ab, was es für ein Interrupt ist. Wenn es ein Level getriggerter Interrupt ist, wird der solange wie der Pin LOW ist immer wieder aufgerufen. Vermute, daß es das ist was passiert. Ein flankengetriggerter INT wird nur jeweils einmal ausgelöst und ausgeführt. Gruß, Marcus
Meiner ist Flankengetriggert, wird aber immer wieder durchlaufen?
vielleicht... vielleicht... vielleicht solltest Du mal Deinen kompletten source posten
Außerdem sollte am Ende von Main noch ein
1 | while(1); |
stehen. Sonst rennt der Controller über das Ende von Main hinaus und baut Mist.
Hier der Code: Dient dazu, ein Sms mit dem Avr zu versenden. Code zum Versenden stammt hauptsächlich von Ulrich Radig - vielen Dank. Warum läuft der Interrupt in einer Endlosschleife. Ausgelöst wird er duch einen prellenden Schalter. Das ist meiner Meinung nach aber kein Grund für die Endlosschleife. [c] #include <main.h> #include <stdint.h> #include <avr/interrupt.h> #include <inttypes.h> #include "lcd.h" int main (void){ //Initzialisierung der Interrupts MCUCR = (1<<ISC01) | (1<<ISC00); GICR = (1<<INT0); sei(); /* initialize display, cursor off */ lcd_init(LCD_DISP_ON); /* clear display and home cursor */ lcd_clrscr(); lcd_puts("AVR Test\n"); //Hauptprogramm while (1) { } return (1); } ISR(INT0_vect) //externer Interrupt auf Pin INT0 { lcd_clrscr(); lcd_puts("* sending! *"); Send_SMS("464646467","TESTALARM",0,0); lcd_clrscr(); lcd_puts("funktioniert!"); } char Send_SMS (char* zielnummer,char* nachricht, char i,char j) { unsigned char tmp1 = 0; unsigned char tmp2 = 0; unsigned char tmp3 = 0; unsigned char tmp4 = 1; unsigned char nachrichtneu[49]; unsigned char zielnummerneu[16]; unsigned char shift = 0; unsigned char k=0; //erzeugen des Nachrichten Strings if (!i) { while (nachricht[tmp1] != 0){ nachrichtneu[tmp4] = (nachricht[tmp1]&0x7F)>>shift; if (shift != 0){ nachrichtneu[tmp4-1] |= (nachricht[tmp1]&((1<<shift)-1))<<(8-shift); }; shift++; tmp1++; if (shift == 8){ shift=0; } else{ tmp4++; } } nachrichtneu[0]= tmp1; } else { for(tmp4=0;tmp4<(2*strlen(nachricht));tmp4=tmp4+2) { nachrichtneu[tmp4+1]=0; nachrichtneu[tmp4+2]=nachricht[k]; k++; //printf("%02X", nachrichtneu[v]); //printf("%02X", nachrichtneu[v+1]); } tmp4; //++; nachrichtneu[0]=tmp4; printf("\n"); } while (zielnummer[tmp3] !=0){ tmp2 = zielnummer[tmp3+1]; zielnummerneu[tmp3+1] = zielnummer[tmp3]; if (tmp4 == 0){ zielnummerneu[tmp3] = 'F'; tmp3=tmp3 + 2; zielnummerneu[tmp3] = 0x0; break; } zielnummerneu[tmp3] = tmp2; tmp3=tmp3 + 2; zielnummerneu[tmp3] = 0x0; } printf("at+cmgs=%i\r\n",(tmp4+(tmp3/2)+ smsclen)); while(uart_getchar()!='>'); printf("%02X", smsclen); printf(smscnumber); printf(firstoctet); printf(tp_mr); if(zielnummerneu[tmp3-2] =='F'){ tmp3--; }; printf("%02X91",tmp3); printf(zielnummerneu); printf(tp_pid); if (!i) { if(j) {printf(tp_dcs7_c1);} else {printf(tp_dcs7_c0);} } else {printf(tp_dcs16_c0);} for (tmp1=0;tmp1<tmp4;tmp1++){ printf("%02X", nachrichtneu[tmp1]); }; printf("%c",0x1a); //Strg+Z while(uart_getchar()!='+'); return (1); } [c]
hmmm. Ich (PICer) habe mir mal ein Datasheet vom Atmega32 runtergeladen. Da steht zumindest, das das I-Flag automatisch gelöscht wird, wenn die ISR aufgerufen wird: ---------------------------------------------- • Bit 6 – INTF0: External Interrupt Flag 0 When an edge or logic change on the INT0 pin triggers an interrupt request, INTF0 becomes set (one). If the I-bit in SREG and the INT0 bit in GICR are set (one), the MCU will jump to the corre- sponding interrupt vector. The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared when INT0 is configured as a level interrupt. ---------------------------------------------- Da ich aber die AVRs nicht kenne, kann ich die nicht sehr weiterhelfen. Allerdings denke ich, dass soetwas: Send_SMS("464646467","TESTALARM",0,0); : char Send_SMS (char* zielnummer,char* nachricht, char i,char j) { : return (1); } eher schlechter Stil ist. Wenn Send_SMS ein char zurückgibt, dann sollte der Aufruf den auch übernehmen. char res; res = Send_SMS("464646467","TESTALARM",0,0); Kann es da nicht evtl. einen Stack-Überlauf geben, wenn Send_SMS einen Wert zurückgibt, der nicht übernommen wird?
tastendrücker wrote: > hmmm. Ich (PICer) habe mir mal ein Datasheet vom Atmega32 runtergeladen. > Da steht zumindest, das das I-Flag automatisch gelöscht wird, wenn die > ISR aufgerufen wird: Ist beim AVR genauso. > eher schlechter Stil ist. Wenn Send_SMS ein char zurückgibt, dann sollte > der Aufruf den auch übernehmen. Muss aber nicht, wenn er nicht benötigt wird. > Kann es da nicht evtl. einen Stack-Überlauf geben, wenn Send_SMS einen > Wert zurückgibt, der nicht übernommen wird? Nein. In C ist es problemlos möglich, einen Rückgabewert zu ignorieren. Das bringt auch keinerlei Nachteile oder Nebeneffekte mit sich. Es gibt eine ganze Reihe Funktionen (auch Standard-Bibliotheksfunktionen), die einen Wert zurückgeben, der aber nur in Sonderfällen wirklich sinnvoll verwendet werden kann und deshalb in den meisten Fällen verworfen wird. Die besten Beispiele dafür stehen in der stdio.h. Oder verwendest Du etwa immer den Rückgabewert von printf & Co.? Schließlich gibt printf einen int zurück...
tastendrücker wrote: > Kann es da nicht evtl. einen Stack-Überlauf geben, wenn Send_SMS einen > Wert zurückgibt, der nicht übernommen wird? Nein. Es ist völlig in Ordnung (im technischen Sinne), wenn man einen Rückgabewert nicht verwendet.
schurli wrote: > Ausgelöst wird er duch einen prellenden Schalter. Das ist meiner Meinung > nach aber kein Grund für die Endlosschleife. Nun, zumindest wird dadurch der Interrupt schon mal 2 mal direkt hintereinander ausgeführt. Lösche am besten am Ende des Interrupt das Anforderungsbit nochmal "per Hand".
Hi Heißt das ich muss das INTF0 Bit am Intrruptende rücksetzen? Irgendwo muss es ja auch wieder gesetzt werden, damit der Interrupt wieder funktioniert? --------------------------------------------------------- • Bit 6 – INTF0: External Interrupt Flag 0 When an edge or logic change on the INT0 pin triggers an interrupt request, INTF0 becomes set (one). If the I-bit in SREG and the INT0 bit in GICR are set (one), the MCU will jump to the corre- sponding interrupt vector. The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared when INT0 is configured as a level interrupt. ---------------------------------------------------------
schurli wrote: > Heißt das ich muss das INTF0 Bit am Intrruptende rücksetzen? > Irgendwo muss es ja auch wieder gesetzt werden, damit der Interrupt > wieder funktioniert? Nicht, damit er wieder "funktioniert", sondern damit er nicht sofort nochmal aufgerufen wird. Schließlich ist es zu dem Zeitpunkt schon wieder gesetzt, und genau deswegen wird nach Verlassen des Interrupt Handlers dieser erneut aufgerufen. Das was Du da machst mit stangenweise printf & Co. in der ISR geht auch nur gut, solange das der einzige Interrupt in Deinem Programm ist...
Johannes M. wrote: > > Das was Du da machst mit stangenweise printf & Co. in der ISR geht > auch nur gut, solange das der einzige Interrupt in Deinem Programm > ist... Auf deutsch gesagt, es macht keinen Sinn, hier überhaupt einen Interrupt zu verwenden. Jürgen
GIFR = (0<<INTF0); am Ende de Interrupts ändert nichts Bitte helft mir.
schurli wrote: > GIFR = (0<<INTF0); > > am Ende de Interrupts ändert nichts > Bitte helft mir. Zum Löschen des Bits muss man eine Eins schreiben.
schurli wrote: > GIFR = (0<<INTF0); > > am Ende de Interrupts ändert nichts > Bitte helft mir. Schau bitte ins Datenblatt bzw. ins AVR-GCC-Tutorial. Da steht, wie man ein Interrupt Flag löscht. So jedenfalls nicht...
GIFR &= 0xDF; Brachte die Lösung! Danke an alle die mir helfen wollten!
schurli wrote: > GIFR &= 0xDF; > Brachte die Lösung! ???
1 | GIFR = 1 << INTF0; |
hätte es getan, ist lesbar und macht wirklich genau das was es soll... Das mit dem & funktioniert eigentlich nur zufällig wegen Nebeneffekten von Read-Modify-Write-Operationen.
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.