Meine Digitaluhr nimmt langsam Form an. Doch eine Uhr die man nicht stellen kann ist nichts wert. Schnell stellte ich fest dass das ohne eine Entprellung nichts wird. Nun habe ich es einmal mit dem einfachsten der Codebeispiele veruscht (im Tutorial der erste Code im Absatz Softwareentprellung). Dieser Code entprellt die Schalter tatsächlich sehr gut, doch seltsamerweise geht die Uhr damit nur manchmal überhaupt zu stellen. Ca. in 2 von 3 Fällen läuft sie zwar, reagiert aber gar nicht auf die Inputs die ich fürs Stellen verwende. In den restlichen Fällen läuft sie und lässt sich auch stellen wie ich es mir vorstelle. Es entscheidet sich immer beim Einschalten, was von beiden nun Sache ist, und bis man sie wieder ausmacht bleibt es auch so. Alternativ habe ich Flankenerkennung über Flags versucht (P2IFG). Die geht zu 100%, aber nicht so gut wie die erste Entprellung: teilweise wird doppelt geschaltet oder auch auf der "falschen" Flanke. Hier mal der Code zu den beiden Lösungen. 1. Version aus Tutorial, für meine Zwecke leicht abgewandelt:
1 | void staster(void) |
2 | {
|
3 | static unsigned char zustand; |
4 | |
5 | if(zustand == 0 && !(P2IN & BIT0) ) //Taster wird gedrueckt (steigende Flanke) |
6 | {
|
7 | zustand = 1; |
8 | s = 0; |
9 | ts = 0; |
10 | }
|
11 | else if (zustand == 1 && !(P2IN & BIT0) ) //Taster wird gehalten |
12 | {
|
13 | zustand = 2; |
14 | }
|
15 | else if (zustand == 2 && (P2IN & BIT0) ) //Taster wird losgelassen (fallende Flanke) |
16 | {
|
17 | zustand = 3; |
18 | }
|
19 | else if (zustand == 3 && (P2IN & BIT0) ) //Taster losgelassen |
20 | {
|
21 | zustand = 0; |
22 | }
|
23 | }
|
24 | |
25 | void mintaster(void) |
26 | {
|
27 | static unsigned char zustand; |
28 | |
29 | if(zustand == 0 && !(P2IN & BIT1) ) //Taster wird gedrueckt (steigende Flanke) |
30 | {
|
31 | zustand = 1; |
32 | if(min==9) |
33 | {
|
34 | min = 0; |
35 | tmin++; |
36 | }
|
37 | else
|
38 | min++; |
39 | }
|
40 | else if (zustand == 1 && !(P2IN & BIT1) ) //Taster wird gehalten |
41 | {
|
42 | zustand = 2; |
43 | }
|
44 | else if (zustand == 2 && (P2IN & BIT1) ) //Taster wird losgelassen (fallende Flanke) |
45 | {
|
46 | zustand = 3; |
47 | }
|
48 | else if (zustand == 3 && (P2IN & BIT1) ) //Taster losgelassen |
49 | {
|
50 | zustand = 0; |
51 | }
|
52 | }
|
53 | |
54 | void htaster(void) |
55 | {
|
56 | static unsigned char zustand; |
57 | |
58 | if(zustand == 0 && !(P2IN & BIT2) ) //Taster wird gedrueckt (steigende Flanke) |
59 | {
|
60 | zustand = 1; |
61 | if(h==9) |
62 | {
|
63 | h = 0; |
64 | th++; |
65 | }
|
66 | else
|
67 | h++; |
68 | }
|
69 | else if (zustand == 1 && !(P2IN & BIT2) ) //Taster wird gehalten |
70 | {
|
71 | zustand = 2; |
72 | }
|
73 | else if (zustand == 2 && (P2IN & BIT2) ) //Taster wird losgelassen (fallende Flanke) |
74 | {
|
75 | zustand = 3; |
76 | }
|
77 | else if (zustand == 3 && (P2IN & BIT2) ) //Taster losgelassen |
78 | {
|
79 | zustand = 0; |
80 | }
|
81 | }
|
82 | |
83 | ...
|
84 | |
85 | void main (void) |
86 | {
|
87 | WDTCTL = WDTPW + WDTHOLD; //Watchdog stoppen |
88 | |
89 | P1DIR = 255; //127d = 1111111b -> 7 aktive Outputs an P1 |
90 | P1OUT = 0; //Voreinstellung: Null, alle Segmente außer g (0tes Bit) |
91 | |
92 | P2SEL &= ~63; //Funktionsauswahl P2: Input/Output |
93 | P2DIR = 248; //P2 komplett als Input |
94 | P2REN = 7; |
95 | |
96 | BCSCTL1 &= ~XTS; // Low Frequency Mode für den externen Quarzeingang setzen |
97 | BCSCTL3 &= ~(LFXT1S0 | LFXT1S1);// 32768 Hz Modus einstellen |
98 | BCSCTL3 |= XCAP1; // 12.5 pF einstellen |
99 | |
100 | TACCTL0 = 0; // zunächst ggf. aktiven Capture/Compare Interrupt für |
101 | |
102 | TACCR0 = 32767; //Obere Zählgrenze für Timer |
103 | TACTL = MC_1|TASSEL_1|TACLR; //Timer einstellen und starten |
104 | //Bedeutung: MC=Modus, hier 1=Aufwärtszählen
|
105 | //TASSEL=Clock source select, hier: 1 = ACLK
|
106 | //TACLR=Timer A clear= Zähler zurücksetzen
|
107 | |
108 | |
109 | while(1) //Immerwährender Zählprozess |
110 | {
|
111 | while((TACTL & 1)==0) //TAIFG (Timer A Interrupt Flag) checken |
112 | {
|
113 | staster(); |
114 | mintaster(); |
115 | htaster(); |
116 | |
117 | shows(); |
118 | showts(); |
119 | showmin(); |
120 | showtmin(); |
121 | showh(); |
122 | showth(); |
123 | } //nach 1s Schleife verlassen |
124 | TACTL &= ~1; //TAIFG nullen |
125 | s++; |
126 | clockwork(); |
127 | |
128 | }
|
129 | |
130 | }
|
2. Version mit P2IFG:
1 | void main (void) |
2 | {
|
3 | WDTCTL = WDTPW + WDTHOLD; //Watchdog stoppen |
4 | |
5 | P1DIR = 255; //127d = 1111111b -> 7 aktive Outputs an P1 |
6 | P1OUT = 0; //Voreinstellung: Null, alle Segmente außer g (0tes Bit) |
7 | |
8 | P2SEL &= ~63; //Funktionsauswahl P2: Input/Output |
9 | P2DIR = 248; //P2 komplett als Input |
10 | P2REN = 7; |
11 | |
12 | P2IE = 7; |
13 | P2IES = 0; |
14 | |
15 | BCSCTL1 &= ~XTS; // Low Frequency Mode für den externen Quarzeingang setzen |
16 | BCSCTL3 &= ~(LFXT1S0 | LFXT1S1);// 32768 Hz Modus einstellen |
17 | BCSCTL3 |= XCAP1; // 12.5 pF einstellen |
18 | |
19 | TACCTL0 = 0; // zunächst ggf. aktiven Capture/Compare Interrupt für |
20 | |
21 | TACCR0 = 32767; //Obere Zählgrenze für Timer |
22 | TACTL = MC_1|TASSEL_1|TACLR; //Timer einstellen und starten |
23 | //Bedeutung: MC=Modus, hier 1=Aufwärtszählen
|
24 | //TASSEL=Clock source select, hier: 1 = ACLK
|
25 | //TACLR=Timer A clear= Zähler zurücksetzen
|
26 | |
27 | |
28 | while(1) //Immerwährender Zählprozess |
29 | {
|
30 | while((TACTL & 1)==0) //TAIFG (Timer A Interrupt Flag) checken |
31 | {
|
32 | if(P2IFG & BIT0) |
33 | {
|
34 | P2IFG &= ~BIT0; |
35 | s = 0; |
36 | ts = 0; |
37 | }
|
38 | |
39 | if(P2IFG & BIT1) |
40 | {
|
41 | P2IFG &= ~BIT1; |
42 | min++; |
43 | }
|
44 | |
45 | if(P2IFG & BIT2) |
46 | {
|
47 | P2IFG &= ~BIT2; |
48 | h++; |
49 | }
|
50 | |
51 | shows(); |
52 | showts(); |
53 | showmin(); |
54 | showtmin(); |
55 | showh(); |
56 | showth(); |
57 | } //nach 1s Schleife verlassen |
58 | TACTL &= ~1; //TAIFG nullen |
59 | s++; |
60 | clockwork(); |
61 | |
62 | }
|
63 | |
64 | }
|
Die Variablen für die Zeit sind global deklariert.