Forum: Mikrocontroller und Digitale Elektronik Atmega8A - Einfaches Interrupt Problem


von Patrick E. (f4550tim)


Lesenswert?

Guten Abend,

ich möchte gerne mit einem Taster (INT1) eine LED ein, bzw. aus 
schalten.
Interrupt hätte ich gerne auf der LOW-Flanke.

Nach meinem Verständnis, sollte doch der Controller wenn er in einer ISR 
ist keine anderen Interrupts erlauben, bzw diese auf die "wartebank" 
schieben. Es sei denn ich schalte am Anfang meiner ISR mit sei() das GIE 
Bit ein.

So ist für mein Verständnis ein Interrupt welcher gerade in der ISR 
steckt und keine weitere Konfiguration hat nur damit beschäftig seine 
ISR abzulaufen und wenn diese wieder im Hauptprogramm zurück gesprungen 
ist erst wieder weitere Interrupts annehmen kann.

Das Problem in meinem Quellcode ist, dass wenn ich in der ISR bin, und 
noch die 5 Sekunden Delay ablaufen und ich den Taster noch einmal wärend 
dessen drücke, dass nach Abarbeitung der ISR diese noch einmal 
aufgerufen wird.
Als würde dieser "zwischen Interrupt" gespeichert werden und danach 
ausgeführt werden.

Wie kann ich das Problem lösen ?

Vielen Dank
Patrick
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 8000000
4
#include <util/delay.h>
5
6
7
int main(void)
8
{
9
  //Interrupt Config
10
   DDRD    = 0b00000001; //PD0 ist LED Ausgang
11
   PORTD  |= (1 << PD3);  //PullUp Taster
12
   MCUCR  = (0 << 2) | (1 << 3);  //Low Flanke
13
   GICR  |= (1 << 7);  //INT1 erlauben
14
   sei(); //GIE setzten
15
  //Hauptschleife
16
    while(1)
17
    {
18
      //nothing
19
    }
20
}
21
22
// Interruptroutinen
23
ISR(INT1_vect)
24
{
25
  PORTD ^= 1 << PORTD0;
26
  _delay_ms(5000);
27
}

von Karl H. (kbuchegg)


Lesenswert?

Patrick E. schrieb:

> Nach meinem Verständnis, sollte doch der Controller wenn er in einer ISR
> ist keine anderen Interrupts erlauben, bzw diese auf die "wartebank"
> schieben.

Kommt drauf an, was genau du mit 'auf die Wartebank schieben' meinst.

Auch wenn Interrupts gesperrt sind, wird die Interrupt Anforderung 
trotzdem registriert. Wenn dann Interrupts wieder freigegeben sind, 
kommt diese registrierte Anforderung zum Zug und die entsprechende 
Interrupt Behandlung  läuft an.
Ist ja auch logisch: Nur weil gerade eine ISR läuft, darf ja trotzdem 
die Warnung vom Badwannenüberlauf nicht verloren gehen, die an einen 
Interrupt geschaltet wurde.


> Das Problem in meinem Quellcode ist, dass wenn ich in der ISR bin, und
> noch die 5 Sekunden Delay

5 Sekunden Delay sind sowieso nicht tragbar.
Im Grunde ist die ganze Delay-Programmierung ab einem gewissen Zeitpunkt 
in der Softwerker-Kariere nicht tragbar. Am Anfang ok. Aber irgendwann 
ist der Zeitpunkt erreicht, an dem man sagen muss: Delay ist nicht die 
Lösung - Delay ist das Prfoblem.

Und dann müssen andere Techniken ran.

> Wie kann ich das Problem lösen ?

Entprellung

mein persönlicher Favorit: die Danegger Entprellung.

: Bearbeitet durch User
von Pepe (Gast)


Lesenswert?

Du kannst die Interrupts mit CLI() bzw. SEI() deaktivieren bzw wieder 
aktivieren.
Aber eigentlich sollten INTs nicht länger dauern als nötig. Benutze 
einen Timer der z.B. alle 10ms  oder 100ms einen INT auslöst und einen 
Zähler hochzählt.
Damit kannst Du dann deine Wartezeit implementieren ohne alles andere 
blockieren zu müssen.

von m.n. (Gast)


Lesenswert?

Es wird zwar der PCINT-Interrupt verwendet, aber INT1 geht auch, indem 
man den Interrupt auf beide Flanken zuläßt. Geschaltet wird aber immer 
mit der negativen Flanke: 
http://www.mino-elektronik.de/power_at90s/powerat90s.htm

von Patrick E. (f4550tim)


Lesenswert?

Danke für die schnellen Antworten.
Das die 5 Sekunden an der stelle Bödsinn sind, ist klar.
Hier ging es um die Theorie.

Leider wenn ich am Anfang meiner ISR cli(); schreibe, wird der Interrupt 
dennoch registriert.
Das es sinnvoll ist verstehe ich, kann ich es dennoch ausschalten.
Damit meine ich das wenn ich in meine ISR rein bin, dass keine weiteren 
Interrupts registriert werden, bis ich wieder aus bin ? cli(); und 
sei(); machen das nicht.

Danke auch an m.n. Ja das Taater entprellen ist auch genau der Punkt.
Hier in dieser Aufgabe möchte ich aber darauf verzichten und dies über 
die ISR mitein Wenig delay() regeln. Das dient nur zu Test und Funktions 
Zwecken.


Schönen Abend

von Karl H. (kbuchegg)


Lesenswert?

Patrick E. schrieb:
> Danke für die schnellen Antworten.
> Das die 5 Sekunden an der stelle Bödsinn sind, ist klar.
> Hier ging es um die Theorie.
>
> Leider wenn ich am Anfang meiner ISR cli(); schreibe, wird der Interrupt
> dennoch registriert.
> Das es sinnvoll ist verstehe ich, kann ich es dennoch ausschalten.

Nein das kannst du nicht.
Aber du kannst einen aufgelaufenen Interrupt Request am Ende der ISR 
löschen.

Sieh dir mal im Datenblatt das Flag INTF1 im Register GIFR an.
Achtung: Diese Flags werden durch einschreiben einer 1 gelöscht!
1
   GIFR = ( 1 << INTF1 );

: Bearbeitet durch User
von Patrick E. (f4550tim)


Lesenswert?

Vielen Dank Karl Heinz !!

Ich habe das FlagBit "gelöscht". Aber leider mit einer 0...
Daran lag es :)

Super, nun kann ich ruhig schlafen!

Grüße
Patrick

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.