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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Marc (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Marc schrieb:
> Also einen
> Taster an den INT1 gehängt

OMG

von Rudolph (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

Grüße,
Marc

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.