Forum: Compiler & IDEs Zu blöd für Interrupt an Atmega32


von Chris G. (chris_g)


Angehängte Dateien:

Lesenswert?

Guten Abend zusammen.
Ich brauche dringend einen frischen Denkansatz für mein Problem,
darum hoffe ich auf Hilfe durch dieses Forum, bzw. seine Nutzer.

Folgendes Problem raubt mir seit drei Tagen den letzten Nerv und
ich glaube, ich habe mich da etwas verfahren. Jedenfalls finde ich 
selber keine Lösung.

Es geht um eine Temperaturregelung.
Eine Temperatur wird eingelesen, mit einem Sollwert verglichen und 
anhand dessen ein Regelungsvorgang vollzogen.

Grundsätlich wird die Regelung nur über zwei Taster bedient:
Solltemperatur "Auf" und "Ab".
Soll- und Ist-Wert werden über ein LCD-Display ausgegeben.

Bei einem Tastendruck auf die Tasten "Auf" oder "Ab" wird ein Interrupt
ausgelöst, der den µController aus der Regelschleife holt und den 
Sollwert
inkrementiert bzw. dekrementiert. Danach geht's wieder in die 
Regelschleife.

Als Testplatform nutze ich hier ein STK500 und einen Atmega32.
Auf meiner Fehlersuche habe ich das Programm bereits soweit abgespeckt, 
daß eigentlich nur noch die Interruptfunktion für einen Taster über ist,
die primitiver Weise den LED-Block des STK500 Board löschen soll.

Aber trotz des reduzierten Codes begreife ich nicht, was ich falsch 
geschrieben habe. Evtl. liegt hier ein "Man sieht den Wald vor lauter 
Bäumen nicht"-Effekt vor, weil ich schon zu lange an diesem Fehler 
arbeite.

Jedenfalls möchte ich mich jetzt schonmal bedanken,
falls sich jemand die Mühe macht, mit mir zu grübeln und mir zu helfen.

von Klaus W. (mfgkw)


Lesenswert?

Vielleicht noch die Register GICR und ggf. MCUCR passend setzen?

von Karl H. (kbuchegg)


Lesenswert?

Chris G. schrieb:

> Aber trotz des reduzierten Codes begreife ich nicht, was ich falsch
> geschrieben habe.

Du musst den INT0 schon auch noch freigeben. Im Moment sind zwar 
Interrupts gnerell freigegeben, aber die spezifische Freigabe des INT0 
ist nicht vorhanden.

Aber eigentlich ist das sowieso keine gute Idee, Taster über einen 
Interrupt Eingang auszuwerten. Die bessere Variante sind die 
Komfort-Taster Entprellroutinen, die über einen Timer Interrupt die 
Taster pollen und gleichzeitig entprellen

*) sie funktionieren wesentlich besser, egal wie stark die Taster
   prellen
*) durch die Autorepeatfunktion ermöglichen sie auch komfortable
   Eingaberoutinen, ohne dass sich der Benutzer an den Tasten einen
   Wolf drückt.
*) Sie sind einfach in der Verwendung

http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29

von Torsten K. (ago)


Lesenswert?

Problem 1: Du hast nicht geschrieben, wo du jetzt eigentlich ein Problem 
hast :-)

Problem 2: Tastenabfrage im Interrupt ist - zumindest ist das die 
Meinung hier im Forum - ein großes "No Go!"

Entprellung ist hier das Stichwort (such mal im Forum nach "Entprellung 
in Software"

Das was ich alleine an Deinem Codeschnipsel sehe ist folgendes:

- Ein Interrupt wird ausgelöst, "keypressed" wird gesetzt
- Hauptschleife fragt "keypressed ab uns setzt keypressed auf 0
- Tastenprellen löst weiteren Interrupt aus und setzt keypressed wieder 
auf 1 ;-)

Ein Ansatz wäre zum Beispiel, die Tastatur regelmäßig im Timerinterupt 
abzufragen, z.B. (Pseudocode)


// Beispiel: 4 Tasten an Port D, Bit 0-3
static uint8_t keypressed[3], keydebounce[3];

ISR(...)  /* aufruf alle 10ms */
{
  uint8_t i;
  for (i=0; i<=3; i++)
  {
    if (PIND & 1<<i)
    {
      if (keydebounce[i]++ == 10)   /* nach 0.1s wird Taste erkannt */
        keypressed[i]++;
      if (keydebounce[i] > 80)
        keydebounce[i] = 0;
    }
    else
      keydebounce[i] = 0;
    /* Alternative: oder keydebounce[i] = keypressed[i] = 0 */
  }
}

hiermit wird alle 0.8+0.1 = 0.9 Sekunden ein Tastendruck erkannt 
(auto-repeat). Du könntest sogar im Hauptprogramm 5 Sekunden schlafen 
und würdest nun in keypressed[i] entsprechend der Dauer des Tastendrucks 
eine "5" vorfinden

im Hauptprogramm fragst du nun nur keypressed[x] ab:

..
if (keypressed(0)
{
   x = x + 1;    /* oder x = x + keypressed(0); */
   keypressed(0) = 0;
}

Mit dem "Alternativen" Codeschnippsel würde die Interruptroutine bei 
Loslassen auch den Taste-gedrückt-Code löschen, falls also das 
Hauptprogramm noch nicht dazu gekommen wäre keypressed[0] auszuwerten 
würde es nichts tun.

Just my 2 cent

PS: Ich kriege - auch mit 3 Glas Rotwein intus - jedes mal Augenkrebs 
wenn ich "LCD-Display" lese ;-)

von Klaus W. (mfgkw)


Lesenswert?

Dann nimm noch ein paar und es wird besser. :-)

PS: Gute Idee, prost!

von Torsten K. (ago)


Lesenswert?

Torsten K. schrieb:
> if (keypressed(0)
> {
>    x = x + 1;    /* oder x = x + keypressed(0); */
>    keypressed(0) = 0;
> }

Es muß latürnich

if (keypressed[0])
{
  x++;  /* oder: x = x + keypressed[0]; */
  keypressed[0] = 0;
}

heißen... und statt static eventuell volatile ;-)

von Klaus W. (mfgkw)


Lesenswert?

Torsten K. schrieb:
> und statt static eventuell volatile ;-)

oder beides

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.