mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interrupt macht Endlosschleife?


Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht denn Deine "Funktion()" aus?

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was für einen Controller verwendest Du? Nimmst Du da nicht die falschen 
Register? Anstatt des MCUCR müsstest Du doch das EICRA nehmen.

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also eigentlich:
int main (void){

//Initzialisierung der Interrupts
  EICRA = (1<<ISC01) | (1<<ISC00);
  EIMSK = (1<<INT0);
  sei();

}

ISR(INT0_vect) //externer Interrupt auf Pin INT0
  {
    Funktion ();
  }

Aber das kommt auf Deinen Controller an.

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: tastendrücker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sicher, dass das Interrupt-Flag gelöscht wird?

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muss man das Flag am Ende des interrupts löschen?

Autor: tastendrücker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann mir jemand sagen wie das für einen Atmega32 unter C funktioniert?

mfg

Autor: MM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meiner ist Flankengetriggert, wird aber immer wieder durchlaufen?

Autor: SoLaLa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielleicht... vielleicht... vielleicht solltest Du mal Deinen kompletten 
source posten

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem sollte am Ende von Main noch ein
while(1);
 stehen. Sonst rennt der Controller über das Ende von Main hinaus und 
baut Mist.

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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]

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat keiner eine Idee?

Autor: tastendrücker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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".

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
---------------------------------------------------------

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Jürgen S. (starblue) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GIFR = (0<<INTF0);

am Ende de Interrupts ändert nichts
Bitte helft mir.

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Soll ich ne Positive Flanke von nen Pinn abfragen?

mfg

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schurli wrote:
> GIFR = (0<<INTF0);
>
> am Ende de Interrupts ändert nichts
> Bitte helft mir.

Zum Löschen des Bits muss man eine Eins schreiben.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: schurli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GIFR &= 0xDF;
Brachte die Lösung!
Danke an alle die mir helfen wollten!

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schurli wrote:
> GIFR &= 0xDF;
> Brachte die Lösung!
???
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.