Taster-Entprellung per Software
Wie bereits im vorherigen Kapitel erwähnt, ist es möglich eine Taster Entprellung auch per Software zu realisieren. Zum softwaretechnischen Entprellen kommt außer dem Taster keine zusätzliche Hardware zum Einsatz. Diese Variante ist also kostengünstiger. Je nach Realisierung kann es jedoch zu anderen Nachteilen kommen, die eine Hardwareentprellung nicht beinhaltet.
Im folgenden Beispiel ist einer dieser Nachteile, dass der Mikrocontroller nach jedem Tastendruck 200ms wartet. Bei Zeitkritischen Anwendungen sollte deshalb auf andere Verfahren zurückgegriffen werden (z.B. Abfragen der Zustände mittels Timer-Interrupt-Service-Routine).
Beispiel für eine Taster Entprellung mittels Software:
Wie auch schon im vorherigen Kapitel soll eine 7-Segment Anzeige bei jeder Taster Betätigung hochzählen. Diesmal entfallen Kondensator und Widerstand aufgrund des Software entprellens und der Nutzung interner Pull-Up-Widerstände.
Abb.: Tastendruckauswertung mittels Softwareentprellung; Quelle: BBS2 Wolfsburg
Beim folgenden Quellecode realisiert die Funktion "debounce" das Entprellen:
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
/* Einfache Funktion zum Entprellen eines Tasters */
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
if ( !(*port & (1 << pin)) )
{
_delay_ms(100); // Taster wurde betaetigt, 100 ms warten
if ( *port & (1 << pin) )
{
_delay_ms(100); // Anwender Zeit zum Loslassen des Tasters geben
return 1;
}
}
return 0;
}
int main(void)
{
DDRD &= ~( 1 << PD3 ); // PIN 3 auf Eingang -> Taster)
PORTD |= ( 1 << PD3 ); // Pull-Up-Widerstand aktivieren
DDRD |= (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0); // Ausgaenge für die 7 Segmentanzeige
int zaehler = 0; // Zaehlervariable, zählt Tasterbeaetigung
while(1)
{
if (debounce(&PIND, PD3)) // Ruft Funktion zum Entprellen auf
{
zaehler++; // Liefert die Entprellfunktion eine 1 als Return, wird der Zaehlerstand erhoeht
}
switch(zaehler)
{
case 0:
PORTD = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 3);
break;
case 1:
PORTD = (1 << 1) | (1 << 2 ) | (1 << 3);
break;
case 2:
PORTD = (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 3);
break;
case 3:
PORTD = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (0 << 5) | (1 << 6) | (0 << 7) | (1 << 3);
break;
case 4:
PORTD = (1 << 1) | (1 << 2) | (1 << 7) | ( 1 << 6) | (1 << 3);
break;
case 5:
PORTD = (1 << 0) | (1 << 2) | (1 << 4) | (1 << 7) | ( 1 << 6) | (1 << 3);
break;
case 6:
PORTD = (1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 7) | ( 1 << 6) | (1 << 3);
break;
case 7:
PORTD = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
break;
case 8:
PORTD = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 7) | ( 1 << 6) | (1 << 3);
break;
case 9:
PORTD = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 7) | ( 1 << 6) | (1 << 3);
break;
default:
zaehler = 0;
break;
}
}
}
Abblauf des Entprellens:
Abb.: Ablauf des Entprellens; Quelle: BBS2 Wolfsburg
Die Funktion "debounce" im Quellcode realisiert die Überbrückung der Schwingzeit der Taster. Das vorangestellte Attribut "inline" vor der Funktion sorgt bei zeitkritischen Anwendungen für eine schnellere Abarbeitung der Funktion. Dabei ersetzt der Compiler den Funktionsaufruf durch den Funktionsinhalt. Es entfällt somit neben dem Hin- und Rückspringen zur Funktion auch das Übergeben von Parameter, sodass gegenüber dem herkömmlichen Funktionsaufruf eine Zeitersparnis zu Stande kommt. Statt unit8_t (unsigned char) kann auch char verwendet werden.
Die Totzeitfunktion muss an dieser Stelle nicht vollständig verstanden werden, da sie tiefere Kenntnisse der C-Programmierung erfordert (Pointer und Referenzen). Sie kann zunächst ohne weiteres verwendet werden, um die Tasterentprellung durch Totzeiten zu realisieren.
Das Ergebnis ist im folgenden Video zu sehen: