Forum: Mikrocontroller und Digitale Elektronik Interrupt wird nur einmal ausgeführt


von Uwe (Gast)


Lesenswert?

Hallo,

ich beschäftige mich aktuell mit Interrupts und habe ein Problem.

Ich verwende einen ATMEGA8 mit internen 8MHz.

Ich habe an Pin PD3 einen Taster gehängt (natürlich mit 10k gegen VCC) 
mit dem ich den Pin PD3 auf GND ziehe. Dieser Pin ist der 
Interrupteingang INT1 und dieser soll in der ISR eine Variable 
verändern. Es soll bei jedem Tastendruck die Variable s2 zwischen 1 und 
2 wechseln. Diese Variable wird in meinem Hauptprogramm ausgwertet und 
eine LED an- bzw. ausgeschaltet. Damit das Prellen des Tasters keinen 
Einfluß hat, habe ich in der ISR- Schleife eine Wartezeit definiert (ich 
weiß man sollte in ISRs keine "dummen" Wartezeiten programmieren aber 
für meine Anwendung reicht es aus).

Als Initialwert definiere ich in dem Hauptprogramm s2=2 und somit wird 
die LED eingeschaltet. Das funktioniert auch. Danach betätige ich den 
Taster und somit soll die Variable in der ISR von 2 auf 1 geändert 
werden und die LED soll ausgehen. Auch das funktioniert. ABER: Wenn ich 
jetzt den Taster wieder betätige passiert nichts mehr....

Anbei mein Code:
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
4
#define F_CPU 8000000L
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
8
9
volatile int s2;
10
11
ISR(INT1_vect)
12
{
13
  if(s2==1)
14
  {
15
    s2=2;
16
  }
17
  
18
  if(s2==2)
19
  {
20
    s2=1;
21
  }
22
  _delay_ms(300);
23
}
24
25
26
int main(void)
27
{
28
  DDRB |= (1<<DDB3); 
29
  DDRD &= ~(1<<DDD3); 
30
  
31
  //Interrupts anschalten
32
  MCUCR |=(1<<ISC11);
33
  GICR |= (1<<INT1);
34
  
35
  s2=2;
36
  
37
  
38
    while(1)
39
  {
40
    //GICR |= (1<<INT1)|(1<<INT0);
41
    sei();
42
    
43
    if(s2==1)
44
    {
45
      PORTB &= ~(1<<PB3);
46
    }
47
  
48
    if(s2==2)
49
    {
50
      PORTB |= (1<<PB3);
51
    }
52
  }
53
}

Danke schon mal und Gruß Uwe

von icke (Gast)


Lesenswert?

Naja, schau dir die Interrupt-Routine mal genauer an:
1
  if(s2==1)
2
  {
3
    s2=2;
4
  }
5
  
6
  if(s2==2)
7
  {
8
    s2=1;
9
  }


Im ersten Durchlauf greift das zeite if und die LED geht an.

Beim zweiten Durchlauf (s2==1) greift erst das erste if (s2 =2) und 
danach dann direkt das zweite if, dass s2 wieder auf 1 setzt.

Benutze
1
else if
antelle des zweiten if

von holgi (Gast)


Lesenswert?

Da brauchst du dir nur gedanklich vorzustellen, was in der ISR passiert, 
wenn S2 gleich 1 ist. S2 wird auf 2 gesetzt und danach gleich nochmal 
abgefragt und was passiert dann...?

von steffen (Gast)


Lesenswert?

Hallo Uwe,

zum ersten kommt sei(); vor den Mainloop.
Dann musst du dem MC noch sagen welche Richtung der Pin machen soll:
1
DDRB &= ~((1 << DDB3)); //Taster 
2
PORTB |= (1<<PB3); //Pullup ein

und zum dritten, du benutzt den INT1 als Ausgang wenn das ein Taster 
sein soll dann muss da ein Taster dran. Also am besten deinen Ausgang wo 
anders hin legen

Gruß Steffen

von Uwe (Gast)


Lesenswert?

Oh Mann, wie dumm kann man sein???

Vielen Dank für diesen völlig blöden Fehler.

Danke und Gruß Uwe

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
Noch kein Account? Hier anmelden.