Interrupt macht Endlosschleife?

Gast #915154
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!
Gast #915164
Lesenswert?

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.
Gast #915166
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
Gast #915187
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).
Gast #915191
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.
Gast #915239
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
Gast #915937
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]
Gast #916183
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?
#916193
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...
#916196
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".
Gast #916216
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.
---------------------------------------------------------
#916220
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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren