Taster an µC anschließen
Typischerweise werden Taster mit einem PullUp Widerstand an den Eingang eines µC angeschlossen. Dabei fällt besonders bei Anwendungen, die Tastendrücke zählen sollen auf, dass bei einem Tastendruck oft mehr als ein Impuls erzeugt wird. Die Ursache ist das Tastenprellen, Kontaktprellen. Beim Schließen des Kontaktes wird die Verbindung noch mehrmals unterbrochen durch das Nachfedern der Kontake.
Nebenstehend ein Timingdiagramm für das Prellen eines Drehwellen-Schnappschalters der Firma Marquardt der im Münzprüfer eines Kunstautomaten verbaut wurde. Bei diesem Schalter ist das Prellen nach 1,2 ms vorbei und ein konstanter Pegel erreicht. Es gibt mehrere Lösungsansätze dem Prellen zu begegnen.
Hier sollen softwarebasierte Lösungen mit Warteschleifen vorgestellt werden.
Noch ein paar Gedanken zur Größe des PullUp-Widerstands. Sei der µC in einem Fahrradtacho eingesetzt und der Schalter sei der Reedkontakt an der Gabel, der durch einen Magneten an einer Speiche geschlossen wird. Die Batterie sei eine LR2032 3V mit 40mAh Kapazität:
- Bei einem kleinen Widerstand z.B. R=100Ω fließt während der Schalter geschlossen ist ein nicht unbedeutender Querstrom: 3V/100Ω=30mA . Befindet sich der Magnet an der Speiche dauerhaft über dem Reedkontakt, ist mir schon beim Abstellen des Fahrrads schon passiert, wäre die Batterie in etwas über einer Stunde leer!
- Bei einem großen Widerstand z.B. R=1MΩ können elektrische Einstreuungen (z.B. durch Dynamo) in die Sensorleitung bei offenem Reedkontakt bereits zu Fehlsignalen führen.
- Typische Werte für PullUp Widerstände bei µC liegen in der Praxis zwischen 4,7kΩ-10kΩ.
Zähler für Tastendrücke
.include "tn2313def.inc"
.def tmp= R16
.def zaehler = R17
.def wi = R18 ; Warteschleife innen
.def wa = R19 ; Warteschleife aussen
init:
ldi tmp, low(RAMEND) ; Stackpointer initialisieren
out SPL, tmp
ldi tmp,$ff
out PORTB,tmp ; Ausgaenge auf 1 setzen damit nix leuchtet
out DDRB,tmp ; PB aus Ausgang
main:
sbic PIND,0 ; ist PD0 = 1
rjmp main ; dann weiter abfragen
rcall warte ; Prellen abwarten
inc zaheler ; zaehler++
mov tmp,zaehler ; zaehler ausgeben
com tmp ; invertieren wegen neg. Logik
out PORTB,tmp
solangeGedrueckt:
sbis PIND,0 ; ist PD0 = 0
rjmp solangeGedrueckt ; dann weiter abfragen
rcall warte ; evtl. Prellen abfragen
rjmp main
warte: ; rcall 3 Takte
ldi wa, 5 ; Wartezeit in ms @ 1MHz (+7 Takte Unterprogrammaufruf und ret)
warteaussen:
ldi wi,249 ; (249 * 4) + 4 = 1000 Takte
nop
warteinnen:
nop
dec wi
brne warteinnen
dec wa
brne warteaussen
ret ; 4 Takte
Die Idee ist einfach -nach dem ersten Impuls so lange warten, bis das Prellen vorbei ist. Dazu muss die Wartezeit warte1 länger als die Prellzeit des Tasters sein. Sollte der Taster beim Loslassen auch prellen muss dafür eine Wartezeit warte2 eingebaut werden. Versuchsweise können die Unterprogrammaufrufe rcall warte auskommentiert werden um die Auswirkung des Prellens zu studieren.
Abfrage, Maskierung und Entprellen mehrerer Tasten
Ein Unterprogramm für eine recht störresistente entprellte Tastaturabfrage. Neu gedürchte Tasten werden in keyenter und losgelassene Tasten in keyexit erfasst..
[keycheck.asm] | [keycheck_c.c] |
---|---|
.def keyold = R21 ;Taster die gedrueckt waren |
unsigned char keyOld = 0; // alter Tasten-Zustand |