mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Tastenabfrage mit Interrupts


Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich möchte mir eine Schaltung basteln die Abfragt ob eine Taste kurz 
oder länger gedrückt wurde.
Bei kurzem druck soll eine Variable erhöt werden
Bei Langem Druck der Wert ins EEPROM gespeichert werden.

Bisher hab ich mir folgendes zusammengestrickt:

//----------------------------------------
// Titel  : Arcade Tastenprogrammierung
//----------------------------------------
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>

typedef unsigned char BYTE;
typedef unsigned int WORD;

BYTE bPortB;
BYTE nKeyPress;

const unsigned char Tabelle[] PROGMEM = {249, 164, 176, 153, 146, 130, 248, 128, 144};

#define CNTDEBOUNCE 10
#define CNTREPEAT 200

#define KEY_PIN  PINB
#define KEY_PINNO PB6

uint8_t eeFooByte;
volatile uint8_t gKeyCounter;


ISR(TIMER1_COMPA_vect)
{
   uint8_t tmp_kc;
 
   tmp_kc = gKeyCounter;
 
   if (!(KEY_PIN & (1<<KEY_PINNO)))
   {
      if (tmp_kc < CNTREPEAT)
    {
         tmp_kc++;
      }
   }
   else
   {
      tmp_kc = 0;
   }
   gKeyCounter = tmp_kc;
}

void init(void)
{
  PORTB |= _BV(6);  // Pull-Up Port B6 aktivieren
    DDRB = 0xFF;    // Port B als Eingang
  DDRD = 0xFF;    // Port D als Ausgang
  TIMSK |= (1<<TOIE1); //Timer1 Interrupt aktiviert
  TCCR1B = 1;     //Prescaler 1
  TCNT1 = 65535-3600; //Preloader 3600
}

int main (void)
{
  init();
  sei();

    bPortB = 1;
  nKeyPress = eeprom_read_byte(&eeFooByte);

    while(1)
  {


        if ( gKeyCounter > CNTDEBOUNCE )
        {
          if (gKeyCounter == CNTREPEAT)  // Code fuer "Taste lange gedrueckt"
          {
            eeprom_write_byte(&eeFooByte, nKeyPress);
          }
               else               // Code fuer "Taste kurz gedrueckt"
          {
            PORTD = pgm_read_byte(&Tabelle[nKeyPress]);
            if (nKeyPress < 8)
            {
              nKeyPress++;

            }
            else
            {
              nKeyPress = 0;

            }
          }
        }

  }
  return 0;
}

Jedoch ist da noch irgendwo ein hund begraben.
Mit den Interrupts tu ich mir etwas schwer. Ich bin sicher das da der 
Fehler drinn steckt.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, die Entprellung hatte ich sogar vor kurzem noch drinn.
Sah dann so aus:

while(1)
  {
    if (bit_is_clear (PINB, 6))
    {
          if (bPortB)
      {
        if ( gKeyCounter > CNTDEBOUNCE )
        {
          if (gKeyCounter == CNTREPEAT)  // Code fuer "Taste lange gedrueckt"
          {
            eeprom_write_byte(&eeFooByte, nKeyPress);
          }
               else               // Code fuer "Taste kurz gedrueckt"
          {
            PORTD = pgm_read_byte(&Tabelle[nKeyPress]);
            if (nKeyPress < 8)
            {
              nKeyPress++;
              bPortB = 0;
            }
            else
            {
              nKeyPress = 0;
              bPortB = 0;
            }
          }
        }
          }
      }
      else
    {
          bPortB = 1;
      }
  }

Hatte ich aber wieder rausgenommen, weil ich dachte das die hier nicht 
von nöten wäre.
Das alleine dürfte aber nicht das Problem sein glaub ich.
Ich möchte gerne eine Tastenabfrage haben die prüft ob diese kürzer als 
2 Sekunden gedrückt wurde und dann dementsprechend den Code für Kurz und 
für langen Tastendruck ausführt.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manfred W. schrieb:
> Ja, die Entprellung hatte ich sogar vor kurzem noch drinn.
> Sah dann so aus:
> ...

Hat ja überhaupt keine Ähnlichkeit mit der Eiwomisa:

http://www.mikrocontroller.net/articles/Entprellun...


> Hatte ich aber wieder rausgenommen, weil ich dachte das die hier nicht
> von nöten wäre.

Das denken leider auch viele professionelle Entwickler.
Entprellen ist der Grundstein für sauberes Programmieren und macht 
vieles einfacher.


Peter

Autor: DerSchatten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Hat ja überhaupt keine Ähnlichkeit mit der Eiwomisa:

Ich weiß. Das ist ja auch ein komplett anderes Beispiel.
Das ich übrigens auch schon ausprobiert hatte.
Leider funktioniert das bei mir irgendwie nicht.

Es leuchten nach dem Einschalten nur alle LEDs, mehr tut sich nicht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DerSchatten schrieb:
> Peter Dannegger schrieb:
>> Hat ja überhaupt keine Ähnlichkeit mit der Eiwomisa:
>
> Ich weiß. Das ist ja auch ein komplett anderes Beispiel.
> Das ich übrigens auch schon ausprobiert hatte.
> Leider funktioniert das bei mir irgendwie nicht.

Dann solltest du dem nachgehen.
Die Funktionen funktionieren 1A

Autor: DerSchatten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, hast recht.
Funktioniert.
Ausschlaggebend ist Taste Key1 auf B.1

Bei mir soll ja als Ausgabe eine 7-Segment Anzeige verbaut werden 
anstelle der LED's

Wieso wird denn die while-Schleife permanent wiederholt? Auch wenn keine 
taste gedrückt ist.

Das macht es für mein Vorhaben etwas unbrauchbar, weil ich dort meine 
Variable nicht einbaun kann:
  while(1){
    if( get_key_short( 1<<KEY1 ))
      LED_PORT ^= 1<<LED1;
    PORTD = pgm_read_byte(&Tabelle[nKeyPress]);
    if (nKeyPress < 8)
    {
      nKeyPress++;
    }
      else
      {
      nKeyPress = 0;
      }
 
    if( get_key_long( 1<<KEY1 ))
      LED_PORT ^= 1<<LED2;
    eeprom_write_byte(&eeFooByte, nKeyPress);
   }

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da fehlen wohl nur ein paar {}:

  while(1){
    if( get_key_short( 1<<KEY1 )){
      LED_PORT ^= 1<<LED1;
      PORTD = pgm_read_byte(&Tabelle[nKeyPress]);
      if (nKeyPress < 8){
        nKeyPress++;
      }else{
        nKeyPress = 0;
      }
    }
    if( get_key_long( 1<<KEY1 )){
      LED_PORT ^= 1<<LED2;
      eeprom_write_byte(&eeFooByte, nKeyPress);
    }
  }


Peter

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin mal neugierig und ich frag mich, wozu ihr im Programm das EEPROM 
beschreibt?

Autor: Di Pi (drpepper) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann auch hardwareseitig entprellen (hier aber nicht gern gesehn ;)

duckundweg

Autor: Stephan Henning (stephan-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Flo,

irgendwie muss der ja mal kapuut zu kriegen sein.  :-))

Autor: DerSchatten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan Henning schrieb:
> irgendwie muss der ja mal kapuut zu kriegen sein.  :-))

Keine Sorge, das ist mir bereits gelungen... :)

Aber immerhin, das ganze funktioniert nun wunderbar. Einfach nur Geil! 
:)

Wozu das ins EEPROM schreiben?
Ganz einfach, ich möchte die Einstellung nach einem Reset (bzw. EIN/AUS) 
wieder hergestellt haben.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.