Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Rasenmaehroboter fuer schwierige und grosse Gaerten im Test

Interface

Funktionen

void get_taster (const unsigned char num, unsigned char tast)
Diese Funktion muss in regelmässigen Abständen aufgerufen werden; sinnvoller Weise durch eine Interrupt Service Routine, die Funktion ist kurz genug dafür. Die Zeit zwischen zwei aufeinanderfolgenden Aufrufen von get_taster für die gleiche Tastennummer num wird unten auch als Tick bezeichnet.

Als Richtwert für die Dauer eines Ticks kann man sich an 10ms orientieren.

Datenstrukturen

taster

volatile signed char taster;

Über diese Variable wird ein erfolgter Tastendruck mitgeteilt.

  • Gab es keinen Tastendruck, dann hat taster den Wert NO_TASTER.
  • Gab es einen (kurzen) Tastendruck, dann wird hier die Nummer der gedrückten Taste gespeichert.
  • Gab es einen langen Tastendruck – was nur sein kann, wenn der Mode des entsprechenden Tasters TM_LONG ist –, dann wird hier die Nummer der gedrückten Taste plus TASTER_LONG gespeichert.
  • Solange taster ungleich NO_TASTER ist, wird kein neuer Tastendruck entgegen genommen. Nach Verarbeitung eines Taster-Wertes muss daher taster wieder auf NO_TASTER zurückgesetzt werden! taster funktioniert also wie ein Tastaturpuffer, in welchen nur ein einziges Zeichen hineinpasst.

taste_t

typedef struct 
{
    ...

    /* Mode des Tasters aus: TM_SHORT, TM_LONG, TM_REPEAT */
    unsigned char mode;
} taste_t;

Jeder Taster wird im Array tasten durch einen Eintrag repräsentiert. Die einzige interessante Komponente in dieser Struktur ist mode. Indem man dieser Komponente einen der Werte TM_SHORT, TM_LONG oder TM_REPEAT zuordnet, kann man das Verhalten der einzelnen Taster steuern:

tasten[n].mode = KM_SHORT;
Taster n reagiert auf Druck. Bevor er erneut reagiert, muss er losgelassen werden. taster wird auf n gesetzt.
tasten[n].mode = KM_LONG;
Der Taster reagiert auf kurzen/langen Druck. Wird er nur kurz gedrückt, wird taster=n gesetzt; wird er lange gedrückt, wird taster=n+TASTER_LONG gesetzt. Die Zeitdauer, ab der ein Druck als lange angesehen wird, kann mir TASTER_DELAY_LONG eingestellt werden.
tasten[n].mode = KM_REPEAT;
Der Taster hat eine auto-repeate Funktion, d.h. bei dauernd gedrücktem Taster wird in bestimmten Zeitabständen immer wieder taster=n gesetzt. Das Wiederholdauer und Erstverzögerung können mit TASTER_REPEAT resp. TASTER_REPEAT_DELAY angepasst werden.

tasten

taste_t tasten[NUM_TASTER];

tasten ist ein Array der Länge NUM_TASTEN. Jedes Array-Element ist vom Typ taste_t. Dadurch kann wie oben gezeigt der Betriebsmodus eines Tasters eingestellt werden, z.B. für Taster 2:

tasten[2].mode = KM_REPEAT;

Defines

Defines (Input)

Input Defines dienen dazu, den Code bzw. die Funktionalität den eigenen Bedürfnissen anzupassen. Nach ihrer Änderung muss der Code neu übersetzt werden.

NUM_TASTER
Die Anzahl der Taster, die man behandeln möchte. Das Array tasten hat NUM_TASTEN Elemente (jedes vom Typ taste_t).
TASTER_LONG
Wird eine Taste kurz gedrückt, dann wird deren Nummer in taster gespeichert. Wird die Taste lange gedrückt, dann wird deren Nummer plus TASTER_LONG in taster gespeichert. Voreinstellung ist 16. Wird z.B. Taste No. 1 kurz gedrückt, wird taster auf 1 gesetzt. Wird sie lange gedrückt und ist tasten[1].mode = TM_LONG, dann wird in taster eine  17 gespeichert.
TASTER_REPEAT_DELAY
Für .mode=TM_REPEAT: Erstverzögerung in Ticks, nach der bei Dauerdruck eines Tasters der auto-repeate einsetzt.
TASTER_REPEAT
Für .mode=TM_REPEAT: Zeitspanne in Ticks zwischen zwei auto-repeats.
TASTER_DELAY_LONG
Für .mode=TM_LONG: Wird ein Taster gedrückt und erst wieder losgelassen, nachdem mindestens TASTER_DELAY_LONG Ticks verstrichen sind, ist der Tastendruck "lang". Ansonsten ist er "kurz".

Defines (Output)

Output Defines dienen dazu, "magische Zahlen" aus dem Code heraus zu halten und ihn lesbarer zu machen. Output Defines müssen so bleiben wie sie sind und dürfen nicht verändert werden.

NO_TASTER
Wert, den taster hat, wenn keine Taste gedrückt wurde.

Werte für Komponente .mode:

TM_SHORT
Taster reagiert auf Tastendruck.
TM_LONG
Taster unterscheidet zwischen auf kurzem und langem Tastendruck.
TM_REPEAT
Taster reagiert auf kurzen Tastendruck. Bei langem Tastendruck auto-repeate.

Quellcode

taster.c

#include "taster.h"

volatile signed char taster = NO_TASTER;

taste_t tasten[NUM_TASTER];

/*
 * Aktualisiert 'taster', falls taster==NO_TASTER
 * num:  Nummer des Tasters von 0...NUM_TASTER-1
 * tast:  =0 falls der Taster gerade nicht gedrückt wird
 * tast: !=0 falls der Taster gerade gedrückt wird
 */
void get_taster (const unsigned char num, unsigned char tast) 
{
    const taste_t * const ptast = & tasten[num];
    const unsigned char taster_old = ptast->old;
    unsigned char pressed, press, release, mode, delay;
    if (tast)
        tast = 1;
 
    /* Was wurde gedrückt/losgelassen...? */
 
    /* Taster bleibt gedrückt */
    pressed =  taster_old &  tast;
    /* Taster neu gedrückt */
    press   = ~taster_old &  tast;
    /* Taster losgelassen */
    release =  taster_old & ~tast;

    /* ptast->old = tast;
     * Der Cast dient zum Wegwerfen des 'const' Qualifiers. 
     * Die Komponente wurde als 'const' qualifiziert, 
     * damit es einen Fehler gibt, wenn versucht wird,
     * ihren Wert von aussen zu ändern (private). */
    *((unsigned char *) & ptast->old) = tast;
 
    tast = 0;
 
    mode  = ptast->mode;
    delay = ptast->delay;
 
    if (press)
    {
        if (mode != TM_LONG)
            tast = num;
   
        delay = 0;
    }
    else if (pressed)
    {
        if (delay < 0xfe)
            delay++;
    }
    else if (release)
    {
        if (mode == TM_LONG && delay != 0xff)
            tast = num;
    }
 
    if (mode == TM_LONG)
    {
        if (delay == TASTER_DELAY_LONG)
        {
            tast = TASTER_LONG + num;
            delay = 0xff;
        }
    }
    else if (mode == TM_REPEAT)
    {
        if (delay == TASTER_REPEAT_DELAY)
        {
            tast = num;
            delay = TASTER_REPEAT_DELAY - TASTER_REPEAT;
        }
    }

    if (taster == NO_TASTER)
        taster = tast;
  
    /* siehe oben */ 
    *((unsigned char *) & ptast->delay) = delay;
}

taster.h

#ifndef _TASTER_H_
#define _TASTER_H_

/* Wert für taster, wenn nichts gedrückt wurde */
#define NO_TASTER (-1)

/* Maximale Anzzhl der Taster */
#define NUM_TASTER 4

/* Dieser Offset wird zur Tasten-Nummer addiert,
 * wenn eine Taste lange gedrückt wurde */
#define TASTER_LONG 16

/* Zeitverzögerung (in ticks), bis zum Beginn von auto-repeate */
#define TASTER_REPEAT_DELAY (60)

/* Zeitverzögerung (in ticks), bis zum nächsten auto-repeate */
#define TASTER_REPEAT       (15)

/* Ab dieser Dauer wird der Tastendruck 'lange' */
#define TASTER_DELAY_LONG   (80)

typedef struct 
{
    /* private */
    const unsigned char delay, old;

    /* Mode des Tasters aus: TM_SHORT, TM_LONG, TM_REPEAT */
    unsigned char mode;
} taste_t;

extern taste_t tasten[];

/* In dieser Variable kann abgefragt werden, welche Taste gedrückt wurde.
   --> NO_TASTER:
       es wurde nichts gedrückt
   --> 0..NUM_TASTER-1:
       Taster Numero 'taster' wurde (kurz) gedrückt
   --> TASTER_LONG ... TASTER_LONG + NUM_TASTER-1:
       Taster Numero 'taster-TASTER_LONG' wurde lange gedrückt
*/   
extern volatile signed char taster;

extern void get_taster (const unsigned char num, unsigned char tast);

enum
{
    TM_SHORT,
    TM_LONG,
    TM_REPEAT
};

#endif /* _TASTER_H_ */


Siehe auch


LiFePO4 Speicher Test