Arduino

Democode Tastenentprellung (Arduino)

Tastatureingaben wird man immer brauchen. Hier eine universelle Routine zur Entprelllung. Als Zusatzfunktion können lange und kurze Tastendrücke erkannt werden. Diese Routine läuft auf gängigen Arduinos. Für den Mikro C Compiler gibt es hier eine angepasste Version.

Link: http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten

Keys.c

// ———————- Debounced Keys ————————
// Idee: Peter Dannegger, überarbeitet A. Bieri
// einlesen von allen 8 Tasten eines Ports gleichzeitig (active low), interruptgesteuerte Entprellung
// Es können kurze und lange Tastendrücke unterschieden werden, optional mit Repeat Funktion
// mit Bitmasken wird das Verhalten definiert
// Jede Taste wird immer nur einmal ausgelesen, muss aber auch manuell gelöscht werden, sonst bleibt der Tastendruck
// gespeichert (reset_all_keys)
//
// Anpassungen: Frequenz, Zeiten, Tastenmaske, Port, Interrupt-Timer, Interruptroutine in Hauptprogramm kopieren

// ***************** ARDUINO VERSION ************************

#include "Keys.h"
volatile uint8_t key_state;                       // debounced and noninverted key state:
                                                  // bit = 0: key pressed
volatile uint8_t key_press;                       // key press detect
volatile uint8_t key_rpt;                         // key long press and repeat
volatile uint8_t key_long;                        // key long press no repeat
//
// check if a key has been pressed. Each pressed key is reported only once
//
uint8_t get_key_press( uint8_t key_mask )
{
  CLI                                         // interrupt disable
  key_mask &= key_press;                          // read key(s)
  key_press ^= key_mask;                          // clear key(s)
  SEI
  return key_mask;
}
//
// check if a key has been pressed long enough such that the
// key repeat functionality kicks in. After a small setup delay
// the key is reported beeing pressed in subsequent calls
// to this function. This simulates the user repeatedly
// pressing and releasing the key.
//
uint8_t get_key_rpt( uint8_t key_mask )
{
  CLI;                                       // read and clear atomic !
  key_mask &= key_rpt;                       // read key(s)
  key_rpt ^= key_mask;                       // clear key(s)
  SEI;
  return key_mask;
}
//
// check if a key has been pressed long enough such that the
// secondary functionality kicks in.
//
uint8_t get_key_long( uint8_t key_mask )
{
  CLI;                                          // read and clear atomic !
  key_mask &= key_long;                         // read key(s)
  key_long ^= key_mask;                         // clear key(s)
  SEI;
  return key_mask;
}
//
// read key state and key press atomic !
//
uint8_t get_key_short( uint8_t key_mask )
{
  CLI;
  return get_key_press( ~key_state & key_mask );
}
//
// reset all key states
//
void reset_all_keys( void )
{
  get_key_short(ALL_KEYS); get_key_long(ALL_KEYS); get_key_rpt(ALL_KEYS);
}
// in Hauptprogramm kopieren und Timer anpassen
// --------------------------------------------------------------------------
/*void timerinterrupt( void )  org IVT_ADDR_TIMER0_OVF         // every 10ms
{
  static uint8_t ct0, ct1, rpt, secac;
  volatile uint8_t i;
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
  i = key_state ^ KEY_PIN;                        // key changed ?
  ct0 = ~( ct0 & i );                             // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
  i &= ct0 & ct1;                                 // count until roll over ?
  key_state ^= i;                                 // then toggle debounced state
  key_press |= key_state & i;                     // 0->1: key press detect
                                                  // missing: reset key repeat when key is released
  if( (key_state & LONG_MASK) == 0 )              // check secondary function
     secac = LONG_START;                          // start delay
  if( --secac == 0 ){
    key_long |= key_state & LONG_MASK;
  }
  if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
     rpt = REPEAT_START;                          // start delay
  if( --rpt == 0 ){
    rpt = REPEAT_NEXT;                            // repeat delay
    key_rpt |= key_state & REPEAT_MASK;
  }
}*/

Keys.h

#ifndef Keys
#define Keys

#ifndef F_CPU
#define F_CPU 8000000 // processor clock frequency
#endif
#define KEY_DDR DDRB // alle Tasten am Port B gleichzeitig auslesbar
#define KEY_PORT PORTB
#define KEY_PIN PINB
#define KEY0 0
#define KEY1 1
#define KEY2 2
#define KEY3 3
#define ALL_KEYS (1<<KEY0 | 1<<KEY1 | 1<<KEY2) // where keys are connected
#define REPEAT_MASK (1<<KEY0 | 1<<KEY2) // repeat: key2
#define REPEAT_START 100 // after 1000ms
#define REPEAT_NEXT 10 // every 100ms
#define LONG_MASK (1<<KEY1) // secondary action on long press: key1
#define LONG_START 100 // after 1000ms
#define LONG_NEXT 10 // every 100ms
#define CLI SREG_I_bit = 0;
#define SEI SREG_I_bit = 1;

typedef unsigned short uint8_t;
typedef signed int int16_t;

extern volatile uint8_t key_state; // debounced and noninverted key state:
 // bit = 0: key pressed
extern volatile uint8_t key_press; // key press detect
extern volatile uint8_t key_rpt; // key long press and repeat
extern volatile uint8_t key_long;

uint8_t get_key_press(uint8_t);
uint8_t get_key_rpt(uint8_t);
uint8_t get_key_long(uint8_t);
uint8_t get_key_short(uint8_t);
void reset_all_keys( void );
//void timerinterrupt( void ) org IVT_ADDR_TIMER0_OVF;
#endif

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.