Hallo!
In diesem Beitrag möchte ich auf die Möglichkeit eingehen, einen Taster softwareseitig zu entprellen. Also als Ersatz für den, in früheren Beiträgen, eingeführten Keramikkondensator, den man parallel zum Schalter löten kann.
Der Kondensator ist eine feine Sache und oft gibt es auch keine andere Möglichkeit um zu einem sauberen Signal zu kommen. Aber manchmal möchte man Bauteile sparen oder man hat zu wenig Platz für die zusätzlichen Kondensatoren oder man hat einfach keine Lust, sich einen Kondensator raus zu suchen. ;-) Für diese Fälle gibt es eine in Bascom eingebaute High-Level-Prozedur: DEBOUNCE
Bascom Hilfe zu DEBOUNCE: http://avrhelp.mcselec.com/index.html?debounce.htm
An DEBOUNCE übergibt man als Parameter den Pin an dem der Taster hängt. Dann kann man noch angeben, ob bei einer HIGH-LOW-Flanke (0) oder bei einer LOW-HIGH-Flanke (1) die Taste als gedrückt gilt. Als dritten Parameter gibt man an, wohin das Programm springen soll, wenn ein Tastendruck erkannt wurde. Und als vierten Parameter kann man mit dem Wort "SUB" angeben ob für den Sprung zum Label der Befehl GOTO oder GOSUB verwendet werden soll. Lässt man "SUB" weg, dann wird GOTO verwendet. Fügt man "SUB" an, dann wird GOSUB verwendet. Bei Verwendung von GOSUB wird das Programm bei einem RETURN wieder an der ursprünglichen Position fortgesetzt.
DEBOUCE ist ein Befehl den man in einer Schleife benutzt. Es wird also nicht wie beim Interrupt alles der Hardware überlassen. DEBOUNCE merkt sich im Hintergrund den aktuellen Status des zu überwachenden Pins und wird aktiv wenn sich das Signal geändert hat. Ändert sich das Signal nicht, dann wird ganz normal mit dem nächsten Befehl fortgefahren. Hat sich das Signal geändert, dann wartet DEBOUNCE 25 Millisekunden und prüft dann den Pin noch einmal ab. Ist der Pin nach 25 Millisekunden immer noch im Schaltzustand, dann springt DEBOUNCE zum angegebenen Label. Mit CONFIG DEBOUNCE
kann man diese Wartezeit einstellen.
$regfile = "M8def.dat"
$crystal = 1000000
$hwstack = 100
$swstack = 100
$framesize = 100
'LED1 an PD7
Led1 Alias Portd.7
Config Led1 = Output
'LED2 an PD6
Led2 Alias Portd.6
Config Led2 = Output
'LED3 an PD5
Led3 Alias Portd.5
Config Led3 = Output
'TASTER1 an PD2
Taster1 Alias Pind.2
Config Taster1 = Input
Portd.2 = 1 'PullUp-Widerstand einschalten
Do
Debounce Taster1 , 0 , On_taster1 , Sub
Loop
End
On_taster1:
If Led1 = 0 Then
Led1 = 1
Led2 = 0
Else
Led1 = 0
Led2 = 1
End If
Return
DEBOUNCE hat auch seine Nachteile, die ich hier nicht verschweigen möchte. Am Einfachsten ist es, wenn man zum Demonstrieren ein Beispiel heran zieht.
Tausche den Code der MainLoop
Do
Debounce Taster1 , 0 , On_taster1 , Sub
Loop
durch diesen Code aus
Do
Debounce Taster1 , 0 , On_taster1 , Sub
Toggle Led3
Loop
Damit wird LED3 in der MainLoop ständig ein- und ausgeschaltet. Das geht so schnell, dass das Auge das nicht mehr mitbekommt. Für uns leuchtet die LED ständig. Wenn man jetzt den Taster mehrmals hintereinander drückt, dann flackert die LED3 jedes mal ein wenig. Das kommt daher, weil beim Erkennen eines Tastendrucks von DEBOUNCE 25 ms gewartet wird. Wärend dieser 25 ms wird die LED nicht mehr getoggelt und das ist dieses Flackern. Das Programm wird bei Tastendruck für 25 ms angehalten.
Tausche den Code der MainLoop jetzt durch diesen Code aus:
Do
Debounce Taster1 , 0 , On_taster1 , Sub
Waitms 400
Toggle Led3
Loop
Was passiert hier? LED3 blinkt. Zwischen jedem Toggeln der LED3 werden im Programm 400 Millisekunden gewartet. Während dieser 400 Millisekunden hat DEBOUNCE keine Chance einen Tastendruck zu ermitteln, da es schlicht und einfach viel zu wenig oft ausgeführt wird um eine Änderung zu erkennen. Ganz langsame Tastenanschläge werden erkannt. Aber je schneller man die Taste drückt desto mehr Anschläge gehen verloren.
Wird es als Störung empfunden wenn DEBOUNCE das Programm 25 ms lahm legt, oder ist der µC sehr ausgelastet und wird ständig am Limit betrieben, oder wird öfter im Programm mit WAIT oder WAITMS gewartet, dann ist DEBOUNCE nicht geeignet um einen Tastendruck zu erkennen. In solchen Fällen sollte man auf einen der beiden Interrupts (INT0, INT1) oder eine andere Möglichkeit ausweichen.
mfg Gerold :-)
Den zugehörigen Original-Beitrag findest du im Loetstelle-Forum.
Ich programmiere Progressive Web Applications, Mobile Apps, Desktop-Programme und noch vieles mehr. Falls es dich interessiert, findest du mehr Informationen darüber auf meiner Business-Website.