ATtiny2313 ext. Interrupt wird doppelt ausgelöst

OP #3099180
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
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
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 ;-)
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
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

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.