Forum: Mikrocontroller und Digitale Elektronik Atmega32, Taster löst Interrupt zweimal aus


von Marc (Gast)


Lesenswert?

Hi,

ich habe mir vor etwa einem Jahr einen LED-Cube nach einer Anleitung 
gebastelt, wobei ich damals aber noch keine Ahnung von Mikrocontrollern 
hatte - der Code war bei der Anleitung dabei. Mittlerweile habe ich mich 
etwas in die Welt der Mikrocontroller eingearbeitet und verstehe 
immerhin den bestehenden Code. Jetzt wollte ich ihn so abändern, dass 
ich per Knopfdruck immer einen Effekt weiterschalten kann. Also einen 
Taster an den INT1 gehängt mit folgendem Code:
1
volatile unsigned char current_effect = 0;
2
volatile unsigned char effects_mode = 2;
3
4
ISR(INT1_vect)
5
{
6
  if (effects_mode == 2) {
7
    delay_ms(1000);
8
    ++current_effect;
9
    if (current_effect >= EFFECTS_TOTAL) current_effect = 0;
10
  }
11
}

Vorher kommt natürlich noch beim Initialisieren:
1
GICR |= (1 << INT1);
2
MCUCR |= (1 << ISC11);

delay_ms() hat zwar ms im Namen, sind aber keine Millisekunden. Wurde 
aber vom Autor des Codes aus mir unbekannten Gründen so genannt. 1000 
entspricht eher 200 ms. Die Funktion rufe ich natürlich auf, weil der 
Taster wie blöd prellt. Habe auch noch ein kleines RC-Glied (1kR, 10nF) 
zwischen Taster und Atmega gesetzt.

Das Problem ist jetzt, dass current_effect immer um 2 erhöht wird, statt 
um 1. Ich denke nicht, dass es an Schwingvorgängen am Taster liegt, da 
ich auch schon delay_ms(5000) ausprobiert habe mit demselben Ergebnis.

Ich hoffe ihr könnt mir da irgendwie weiterhelfen. Falls das zu wenig 
Code ist, einfach sagen - es ist genug für alle da. ;-)


Grüße,
Marc

von Peter D. (peda)


Lesenswert?

Marc schrieb:
> Also einen
> Taster an den INT1 gehängt

OMG

von Rudolph (Gast)


Lesenswert?

Delay Funktionen sind an sich schon blöd, die bewirken nur, dass der µC 
für die Wartezeit maximal Strom aufnimmt und überhaupt nicht mehr 
reagiert.

In Interrupts haben Delays garnichts zu suchen!

Taster fragt man einfach in der Hauptschleife zyklisch ab, gegen das 
Prellen lässt man einen Zähler mitlaufen.
Taster betätigt -> Zähler plus 1
Taster nicht betätigt -> wenn Zähler grösser Null, Zähler Minus 1
Zähler grösser Schwellwert -> Taster gilt als betätigt

von Peter D. (peda)


Lesenswert?

Am Ende des Interrupt ein
1
GIFR = 1<<INTF1;
behebt das Problem.
Es bleibt aber eine Notlösung.

Wenn das Delay nicht stimmt, hast Du vermutlich F_CPU nicht oder falsch 
definiert.

: Bearbeitet durch User
von innerand i. (innerand)


Lesenswert?

Das wait bringt in dem Fall halt reichlich wenig, da das Flag im ISR 
trotzdem gesetzt wird wenn der Interrupt getriggert wird.

Hier passiert jetzt Folgendes:
Der erste Interrupt vom prellende Taster kommt, die Interrupt-Routine 
wird aufgerufen und das Flag im ISR wieder 0 gesetzt.
Während die Interrupt-Routine jetzt abgearbeitet wird, kommt das nächste 
Impuls vom prellenden Taster und das Flag im ISR wird wieder auf 1 
gesetzt.
Wenn der µC jetzt mit der Abarbeitung fertig ist, "bemerkt" er, dass da 
ja schon wieder eine 1 im ISR stellt und ruft die Interrupt-Routine 
erneut auf...

von Marc (Gast)


Lesenswert?

Danke, für die schnellen Antworten. Ich habe mal versucht Rudolphs 
Prinzip zu verfolgen, also weg vom externen Interrupt. Mein Hauptproblem 
ist, dass die Hauptschleife ziemlich langsam ist. Sie ruft nur eine 
Funktion auf, die einen neuen Effekt erzeugt, wartet bis dieser vorbei 
ist (mehrere Sekunden) und startet dann wieder einen neuen. Allerdings 
läuft nebenbei noch ein Timer-Interrupt, der die Daten an den Cube 
sendet (ca. 10k interrupts pro Sekunde). Habe mal versucht das Ganze 
dort zu implementieren:
1
char ncount = 0;
2
  
3
if (effects_mode == 2) {
4
  if (!(PIND & RS232_BTN)) ++ncount;
5
  else {
6
    if (ncount > 0) --ncount;
7
    }
8
9
  if (ncount > 100) {
10
    ++current_effect;
11
    ncount = 0;
12
    }
13
  if (current_effect >= EFFECTS_TOTAL) current_effect = 0;
14
}

Leider schaltet er jetzt nicht mehr auf andere Effekte um. Woran könnte 
das liegen?


Grüße,
Marc

von chris (Gast)


Lesenswert?

1
 static char ncount = 0;

Versuchs mal mit static.
Sonst wird ncount jedes mal neu angelegt und mit 0 initialisiert --> es 
kann nie > 100 werden

von Marc (Gast)


Lesenswert?

Danke chris, jetzt funktioniert alles wie es soll. Auch nochmal danke an 
alle, die hier geantwortet haben! :-)

Grüße,
Marc

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.