Folgende Entprellung verwende ich für den Zeit- und Datums-Einstellmodus
einer Echtzeituhr. Das ganze läuft auf einem ATmega8 als Datalogger.
Im Wartungsmodus (Uhr einstellen) läuft der Log nicht weiter. Dies aber
nur am Rande.
Meine Entprell-Methode ist wohl nur für wenige Tasten Interessant. Was
mich aber nicht weiter stört, da ich ja nur Mode (PORT C.0) und Set
(Port C.1) für die Uhr brauche. Weiterhin ist die Anwendung nicht
zeitkritisch, also brauche ich nicht auf Interrupts und Timer
zurückzugreifen.
Als erstes braucht man eine Warterotine:
1 | #define F_CPU 3686400
|
2 |
|
3 |
|
4 | //Includes
|
5 | #include <avr\io.h>
|
6 | #include <util\delay.h>
|
7 |
|
8 | // Wartefunktionen
|
9 | void wait_ms(int miliSec) {
|
10 | _delay_loop_2(1*(F_CPU/(1000/4))*miliSec); //Schleifen-Funktion aus delay.h
|
11 | }
|
Falls man das Include delay.h nicht verwenden möchte/kann oder eine
andere Prozessorfamilie benutzt, kann man sich auch selber was basteln.
Nun die Entprell-Funktion:
1 | int PINC_clean(){
|
2 | int tmp;
|
3 | if (!(PINC &0x00)) { // falls C.0 und C.1 nicht betätigt
|
4 | wait_ms(20); //warte 20 ms (je nach Schalter)
|
5 | tmp=PINC; //Ist-Zustand zwischenspeichern
|
6 | while (!(PINC &0x00)) //Warte bis beide Tasten nicht betätigt
|
7 | return PINC; //Ist-Zustand zurückgeben und Schleife verlassen
|
8 | }
|
9 | if (!(PINC &0x01)) { // falls C.0 gedrückt C.1 nicht betätigt
|
10 | wait_ms(20);
|
11 | tmp=PINC;
|
12 | while (!(PINC &0x00))
|
13 | return PINC;
|
14 | }
|
15 | if (!(PINC &0x02)) { // falls C.1 gedrückt C.0 nicht betätigt
|
16 | wait_ms(20);
|
17 | tmp=PINC;
|
18 | while (!(PINC &0x00))
|
19 | return PINC;
|
20 | }
|
21 | if (!(PINC &0x03)) { // falls C.0 und C.1 betätigt
|
22 | wait_ms(20);
|
23 | tmp=PINC;
|
24 | while (!(PINC &0x00))
|
25 | return PINC;
|
26 | }
|
27 | }
|
Die Tasten erfüllen ihre jeweilige Funktion allerdings erst beim
loslassen!
Die Tastenabfrage kann dann so aussehen:
1 | int Clock_DigitSet (int Digit, int MaxValue, int Line, int Row){
|
2 | lcd_goto( Line, Row);
|
3 | while (PINC_clean() & 0x01){ //Solange Mode (C.0) nicht gedrückt
|
4 | if (!(PINC_clean() & 0x02)) { //Kann man mit Set (C.1) das Digit erhöhen
|
5 | if (Digit<MaxValue){
|
6 | Digit++;
|
7 | } else if (Digit>=MaxValue) {
|
8 | Digit=0x00;
|
9 | }
|
10 | Digit+=0x30;
|
11 | lcd_goto ( Line, Row);
|
12 | lcd_write (Digit);
|
13 | lcd_goto ( Line, Row);
|
14 | Digit-=0x30;
|
15 | while (!(PINC_clean() & 0x02)); //Das nächste Digit kann man erst erhöhen,
|
16 | //wenn man die Taste (entprellt) losgelassen hat
|
17 | }
|
18 |
|
19 | }
|
20 | while (!(PINC_clean() & 0x01)); //Nach dem Drücken auf Mode Taste loslassen
|
21 | //und man kommt zum nächsten Digit der Uhr
|
22 | return Digit;
|
23 | }
|
Das die Taste erst beum Loslassen reagiert ist zwar nicht sehr
Benutzerfreundlich, aber da nur ich die Uhr bediene stört es niemanden
=D
1 | if (!(PINC &0x00)) { // falls C.0 und C.1 nicht betätigt
|
2 | wait_ms(20); //warte 20 ms (je nach Schalter)
|
3 | tmp=PINC; //Ist-Zustand zwischenspeichern
|
4 | //while-Schleife entfernt//
|
5 | return PINC; //Ist-Zustand zurückgeben und
|
6 | }
|
So geht es bei mir auch mit Reaktion, beim drücken Taste. Aber ich trau
der Sache nicht!
Es läuft Prima, bin aber für Vorschläge und Kritik immer offen!