ATtiny2313 ext. Interrupt wird doppelt ausgelöst

OP #3099180
Lesenswert?

Hallo,

ich möchte per INT0 eine Tasterentprellung machen. Beim Testen (Taster 
wird ganz schnell mehrfach betätigt) wird meine ISR 2 mal ausgeführt!

Warum?

Mit cli(); sperre ich doch weitere Interrupts und auch wenn ich das Flag 
im EIFR lösche passiert das-
1
ISR (INT0_vect)          // ISR ext. Interrupt Request 0
2
{
3
  cli();            // Int. sperren
4
  EIFR = (1<<INTF0);      // Int.Flag löschen
5
  _delay_ms(300);
6
  asm("NOP");  
7
  sei();            // Int aktivieren
8
}
Gast #3099189
Lesenswert?

Du löscht das Flag vor den 300ms, d.h. wenn da was prellt wird das Flag 
wieder gesetzt und nach dem verlassen der ISR wird diese nochmal 
angesprungen. Schlimmer geht's kaum, dass is die mit Abstand 
schlechteste Variante die ich je gesehen habe.
OP #3099204
Lesenswert?

Ingo schrieb:
> Du löscht das Flag vor den 300ms, d.h. wenn da was prellt wird das Flag
> wieder gesetzt und nach dem verlassen der ISR wird diese nochmal
> angesprungen.
Stimmt, da hast du recht!

Schlimmer geht's kaum, dass is die mit Abstand
> schlechteste Variante die ich je gesehen habe.
Na siehst du, dann ist das ja neu für dich ;-)
#3099205
Lesenswert?

m. g. schrieb:
>ich möchte per INT0 eine Tasterentprellung machen. Beim Testen (Taster
>wird ganz schnell mehrfach betätigt) wird meine ISR 2 mal ausgeführt!

>Warum?

>Mit cli(); sperre ich doch weitere Interrupts und auch wenn ich das Flag
>im EIFR lösche passiert das-

Deswegen macht man das ja auch nicht so.


ISR (INT0_vect)          // ISR ext. Interrupt Request 0
{
  cli();            // Int. sperren
  EIFR = (1<<INTF0);      // Int.Flag löschen
  _delay_ms(300);
  asm("NOP");
  sei();            // Int aktivieren
}

Das vergisst du alles ganz schnell wieder.
1. Die Interrupts werden vom Controller automatisch gesperrt und 
freigegeben. cli() und sei() haben in einer ISR nichts verloren.
2. Ein delay genauso wenig
3. Das Interrupt Flag wird beim Eintritt in die ISR automatisch 
gelöscht.

Damit bleibt das von deiner ISR übrig:

ISR (INT0_vect)          // ISR ext. Interrupt Request 0
{
  asm("NOP");
}

Tasten werden mit einem Timer entprellt:
http://www.mikrocontroller.net/articles/Entprellung

Lies dir das durch. Was du jetzt machst, ist Stochern im Nebel ohne 
Aussicht auf Erfolg.

mfg.
Gast #3099294
Lesenswert?

Thomas Eckmann schrieb:
>Damit bleibt das von deiner ISR übrig:

>ISR (INT0_vect)          // ISR ext. Interrupt Request 0
>{
>  asm("NOP");
>}


Das bringt nur nichts mehr.
Wenn das nach seiner Vorstellung gelöst werden sollte müsste er solange 
in der ISR verbleiben bis der Kontakt sauber steht. Nur düfte das 
schlechte Programmierung sein weil das vermutlich alle anderen 
Interrupts derweil blockiert.

Ich würde das lösen indem ich in der ISR den Auftrag erteilen würde den 
bestimmten Pin-Interrupt zu sperren und einen Timerauftrag starten würde 
der nach festgesetzter Zeit zB 200ms, den Pin-Interrupt wieder frei 
gibt. Der Umweg über den Timer hat den Vorteil dass in der Zwischenzeit 
nichts blokiert wird, weder Interrupts noch sonstiger Programmablauf.

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