Hallo, ich habe ein Problem bei dem ich über eine elegante Lösung nachdenke. Ich habe einen ATTiny an dem 2 Taster nach Masse angeschlossen sind. Ausserdem sich noch 3 LED verbunden. Habe das im Anhang mal schnell visualisiert. Nun soll wenn innerhalb von 3 sekunden eine Tastenkombination gedrückt wird eine LED nach folgendem Schema leuchten. Taste1 Taste1 Taste1 Led1 Taste1 Taste1 Taste2 Led2 Taste1 Taste2 Taste1 Led3 Wie ich eine Taste abfrage und entprelle oder die Led ein- und ausschalte weiss ich und soll hier nicht berücksichtigt werden. Es geht sich nur um eine elegante Lösung des Problems das unterschiedliche Tasten innerhalb einer bestimmten Zeit gedrückt und ausgewertet werden müssen. Warscheinlich sehe ich gerade den Wald vor lauter Bäumen nicht. ;-) Gruß Rene
Rückfragen: Ab wann sollen die 3 Sekunden zu laufen anfangen. Mit dem ersten Tastendruck, oder ist das so zu verstehen, dass ich nach jedem Tastendruck weitere 3 Sekunden Zeit bekomme um die nächste Taste zu drücken. (und wenn ich die Zeit verstreichen lasse, dann ist die komplette bisherige Eingabe hinfällig)? Was ist wenn ich innerhalb der 3 Sekunden 4 mal auf die Taste drücke? 2 1 1 2 die ersten 3 tastendrücke sind keine zulässige Kombination, aber wenn man den ersten Druck ignoriert, dann wäre 1 1 2 zulässig. Warum ich frage: Weil es viel einfacher ist, wenn ich sage: Nach jedem Tastendruck beginnt ein Timer zu laufen, der nach 3 Sekunden die bisherige Eingabe löscht. Jeder Tastendruck wird einfach in ein Array 'eingeschoben' und nach jedem Tastendruck wird nachgesehen ob eine zulässige Lösung vorliegt. Bsp 0 ist keine Taste 1 ist Taste 1 2 ist Taste 2 3 ist Taste 3 Ausgangssituation +---+---+---+ | 0 | 0 | 0 | Grundzustand +---+---+---+ Taste 2 gedrückt +---+---+---+ | 0 | 0 | 2 | +---+---+---+ keine zulässige Lösung Taste 1 gedrückt +---+---+---+ | 0 | 2 | 1 | +---+---+---+ keine zulässige Lösung Taste 1 gedrückt +---+---+---+ | 2 | 1 | 1 | +---+---+---+ keine zulässige Lösung Taste 3 gedrückt +---+---+---+ | 1 | 1 | 3 | +---+---+---+ zulässige Lösung, Led 3 an und wieder Grundzustand +---+---+---+ | 0 | 0 | 0 | Grundzustand +---+---+---+ Taste 3 gedrückt +---+---+---+ | 0 | 0 | 3 | +---+---+---+ Taste 2 gedrückt +---+---+---+ | 0 | 3 | 2 | +---+---+---+ (3 Sekunden verstreichen lassen -> Timer kickt ein und setzt alles auf Grundzustand +---+---+---+ | 0 | 0 | 0 | +---+---+---+ (der Timer wird mit jedem Tastendruck wieder neu gestartet)
Na das ging ja mal schnell. Also, gültig sollen immer nur Eingaben innerhalb von 3 Sekunden sein. Werden mehr Tasten betätigt so ist die erste gültige Reihenfolge abzuarbeiten. Werden innerhalb von 3 Sekunden keine 3 gültigen Eingabe erkannt so ist nichts zu unternehmen. P.S. Es gibt keine Taste 3. ;-))))) Gruß Rene
ok. Dann würde ich das so modifizieren, dass der Timer gestartet wird, wenn das "System" aus dem Grundzustand heraus kommt. Alles andere bleibt gleich
Ok, meiner Meinung nach habe ich es so gemacht. ;-) Wäre es möglich das da noch mal ein paar Augen draufschauen? Würde mich echt freuen. Die Tastenentprellung ist hier bewusst noch nicht berücksichtigt. Verbesserungsvorschläge sind herzlich Willkommen.
1 | #include <stdio.h> |
2 | #include <avr/io.h> |
3 | #include <avr/interrupt.h> |
4 | |
5 | #define Taste_DDR DDRB
|
6 | #define Taste_PIN PINB
|
7 | #define Taste_PORT PORTB
|
8 | #define Taste1 PB4
|
9 | #define Taste2 PB3
|
10 | |
11 | #define Led_DDR DDRB
|
12 | #define Led_PORT PORTB
|
13 | #define Led1 PB2
|
14 | #define Led2 PB1
|
15 | #define Led3 PB0
|
16 | |
17 | #define Led1_an Led_PORT &= ~(1<<Led1)
|
18 | #define Led1_aus Led_PORT |= (1<<Led1)
|
19 | #define Led2_an Led_PORT &= ~(1<<Led2)
|
20 | #define Led2_aus Led_PORT |= (1<<Led2)
|
21 | #define Led3_an Led_PORT &= ~(1<<Led3)
|
22 | #define Led3_aus Led_PORT |= (1<<Led3)
|
23 | |
24 | #define Timer0_Reload 255 - 43 // 1,1 ms bei 11,0592 MHz
|
25 | |
26 | #define max_Buffer_len 3 // max. 3 Tasten speichern
|
27 | |
28 | uint8_t Buffer[max_Buffer_len]; // Buffer für Tasten |
29 | |
30 | //GPIOR sollte schneller sein als volatile auf Ram, ist das so ?????? Ich denke ja. Muß ich noch prüfen !!!!!!
|
31 | |
32 | #define Zeiger GPIOR0 // Zeiger für Bufferposition
|
33 | #define Zeit GPIOR1 // Zeitzähler
|
34 | #define Zeit_mul GPIOR2 // Zeitmultiplikator für Interrupt
|
35 | |
36 | ISR(TIMER0_OVF_vect){ // Timer0 Overflow alle 1,1 ms, 1,1 ms ist fest da |
37 | // noch für andere Sachen gebraucht, leider !!!!
|
38 | TCNT0 = Timer0_Reload; // Reloadwert laden |
39 | if (Zeit_mul > 90){ // alle 91 ms x 1,1 ms = 100,1 ms |
40 | Zeit++; // Zeit in 1/10 sec weiterzählen |
41 | Zeit_mul = 0; // Zeitmultiplikator zurücksetzten |
42 | }
|
43 | }
|
44 | |
45 | void Buffer_Init(void){ |
46 | Zeiger = 0; // Bufferzeiger auf Anfang |
47 | Buffer[0] = 0; // Buffer löschen |
48 | Buffer[1] = 0; // Buffer löschen |
49 | Buffer[2] = 0; // Buffer löschen |
50 | }
|
51 | |
52 | inline void Init(void){ |
53 | // Tasten
|
54 | Taste_DDR &= ~(1<<Taste1)|(1<<Taste2); // Taste1 & Taste2 Eingang |
55 | Taste_PORT |= (1<<Taste1)|(1<<Taste2); // Taste1 & Taste2 Pullup an |
56 | // Led
|
57 | Led_DDR |= (1<<Led1)|(1<<Led2)|(1<<Led3); // Led1 & Led2 & Led3 Ausgang |
58 | Led_PORT |= (1<<Led1)|(1<<Led2)|(1<<Led3); // Led1 & Led2 & Led3 aus |
59 | // Timer 0
|
60 | TCCR0A = 0; // Timer Normal Mode |
61 | TCCR0B = (1<<CS02); // clkI/O / 256 (From prescaler) |
62 | TIMSK |= (1<<TOIE0); // Timer/Counter0 Overflow Interrupt an |
63 | // Buffer
|
64 | Buffer_Init(); // Bufferspeicher initialisieren |
65 | }
|
66 | |
67 | int main(void){ |
68 | Init(); // alles Initialisieren |
69 | sei(); // Interrupt Global ein |
70 | while(1){ // Endlosschleife |
71 | |
72 | if (Zeit > 30){ // wenn ca. 30 1/10 sec = 3 sec um sind |
73 | Buffer_Init(); // Bufferspeicher initialisieren |
74 | }
|
75 | |
76 | if(Taste_PIN & (1<<Taste1)){ // ist Taste1 gedrückt? |
77 | if (Zeiger == 0){ // erste Taste gedrückt |
78 | Zeit = 0; // Zeit zurücksetzen |
79 | }
|
80 | if (Zeiger < max_Buffer_len - 1){ // wenn noch keine 3 Tasten gespeichert sind |
81 | Buffer[Zeiger] = 1; // Tastendruck merken |
82 | Zeiger++; // Zeiger weitersetzen |
83 | }
|
84 | else{ // es sind schon 3 Tasten gespeichert |
85 | Buffer[0] = Buffer[1]; // Bufferdaten Byteweise 1x links schieben, Byte 1 |
86 | Buffer[1] = Buffer[2]; // Bufferdaten Byteweise 1x links schieben, Byte 2 |
87 | Buffer[2] = 1; // Tastendruck in Byte 2 merken |
88 | }
|
89 | }
|
90 | else if(Taste_PIN & (1<<Taste2)){ // ist Taste2 gedrückt? |
91 | if (Zeiger == 0){ // erste Taste gedrückt |
92 | Zeit = 0; // Zeit zurücksetzen |
93 | }
|
94 | if (Zeiger < max_Buffer_len - 1){ // wenn noch keine 3 Tasten gespeichert sind |
95 | Buffer[Zeiger] = 2; // Tastendruck merken |
96 | Zeiger++; // Zeiger weitersetzen |
97 | }
|
98 | else{ // es sind schon 3 Tasten gespeichert |
99 | Buffer[0] = Buffer[1]; // Bufferdaten Byteweise 1x links schieben, Byte 1 |
100 | Buffer[1] = Buffer[2]; // Bufferdaten Byteweise 1x links schieben, Byte 2 |
101 | Buffer[2] = 2; // Tastendruck in Byte 2 merken |
102 | }
|
103 | }
|
104 | |
105 | if (Buffer[0] == 1 && Buffer[1] == 1 && Buffer[2] == 1){// gedrückt Taste1 + Taste1 + Taste1 |
106 | Led1_an; |
107 | Led2_aus; |
108 | Led3_aus; |
109 | Buffer_Init(); // Bufferspeicher initialisieren |
110 | }
|
111 | if (Buffer[0] == 1 && Buffer[1] == 1 && Buffer[2] == 2){// gedrückt Taste1 + Taste1 + Taste2 |
112 | Led1_aus; |
113 | Led2_an; |
114 | Led3_aus; |
115 | Buffer_Init(); // Bufferspeicher initialisieren |
116 | }
|
117 | if (Buffer[0] == 1 && Buffer[1] == 2 && Buffer[2] == 1){// gedrückt Taste1 + Taste2 + Taste1 |
118 | Led1_aus; |
119 | Led2_aus; |
120 | Led3_an; |
121 | Buffer_Init(); // Bufferspeicher initialisieren |
122 | }
|
123 | }
|
124 | }
|
Gruß Rene
Rene Zimmermann schrieb: > Würde mich echt freuen. Die Tastenentprellung ist hier bewusst > noch nicht berücksichtigt. Dann mach das mal zusammen mit einer vernünftigen Auswertung eines Tasten-DRUCKS was glaubst/schätzt du, wie oft wird wohl dein µC diese 'Basisschleife'
1 | while(1){ // Endlosschleife |
2 | |
3 | ...
|
4 | |
5 | if(Taste_PIN & (1<<Taste1)){ // ist Taste1 gedrückt? |
6 | ...
|
7 | }
|
8 | else if(Taste_PIN & (1<<Taste2)){ // ist Taste2 gedrückt? |
9 | ...
|
10 | }
|
11 | ...
|
12 | }
|
ausführen, während du eine Taste deinem Gefühl nach ganz kurz drückst. 10000 mal, vielleicht sogar 15000 mal. Irgend sowas in der Gegend wird es wohl sein.
Hi, danke für die Antwort. Das ich das auf einem MC nicht laufen lassen kann war mir klar. Mir ging es nur um die Umsetzung des eigentlichen Problems. Aber kein Thema habe die Entprellung eingebaut und mich bei Peter Dannegger bedient. Anbei der geänderte Quellcode:
1 | // Tasten Entprellroutine von Peter Dannegger: danni@specs.de
|
2 | |
3 | #include <stdio.h> |
4 | #include <avr/io.h> |
5 | #include <avr/interrupt.h> |
6 | |
7 | #define Taste_DDR DDRB
|
8 | #define Taste_PIN PINB
|
9 | #define Taste_PORT PORTB
|
10 | #define Taste1 PB4
|
11 | #define Taste2 PB3
|
12 | |
13 | #define Led_DDR DDRB
|
14 | #define Led_PORT PORTB
|
15 | #define Led1 PB2
|
16 | #define Led2 PB1
|
17 | #define Led3 PB0
|
18 | |
19 | #define KEY_DDR Taste_DDR
|
20 | #define KEY_PORT Taste_PORT
|
21 | #define KEY_PIN Taste_PIN
|
22 | #define KEY0 Taste1
|
23 | #define KEY1 Taste2
|
24 | #define ALL_KEYS (1<<KEY0 | 1<<KEY1)
|
25 | |
26 | #define Led1_an Led_PORT &= ~(1<<Led1)
|
27 | #define Led1_aus Led_PORT |= (1<<Led1)
|
28 | #define Led2_an Led_PORT &= ~(1<<Led2)
|
29 | #define Led2_aus Led_PORT |= (1<<Led2)
|
30 | #define Led3_an Led_PORT &= ~(1<<Led3)
|
31 | #define Led3_aus Led_PORT |= (1<<Led3)
|
32 | |
33 | #define Timer0_Reload 255 - 43 // 1,1 ms bei 11,0592 MHz
|
34 | |
35 | #define max_Buffer_len 3 // max. 3 Tasten speichern
|
36 | |
37 | uint8_t Buffer[max_Buffer_len]; // Buffer für Tasten |
38 | |
39 | //GPIOR sollte schneller sein als volatile auf Ram, ist das so ?????? Ich denke ja. Muß ich noch prüfen !!!!!!
|
40 | |
41 | #define Zeiger GPIOR0 // Zeiger für Bufferposition
|
42 | #define Zeit GPIOR1 // Zeitzähler
|
43 | #define Zeit_mul GPIOR2 // Zeitmultiplikator für Interrupt
|
44 | |
45 | volatile uint8_t Zeit_Entprellen; |
46 | volatile uint8_t key_state; // debounced and inverted key state: |
47 | volatile uint8_t key_press; // key press detect |
48 | |
49 | |
50 | uint8_t get_key_press( uint8_t key_mask ){ |
51 | cli(); // read and clear atomic ! |
52 | key_mask &= key_press; // read key(s) |
53 | key_press ^= key_mask; // clear key(s) |
54 | sei(); |
55 | return key_mask; |
56 | }
|
57 | |
58 | |
59 | |
60 | ISR(TIMER0_OVF_vect){ // Timer0 Overflow alle 1,1 ms, 1,1 ms ist fest da |
61 | // noch für andere Sachen gebraucht, leider !!!!
|
62 | static uint8_t ct0, ct1; |
63 | uint8_t i; |
64 | |
65 | TCNT0 = Timer0_Reload; // Reloadwert laden |
66 | |
67 | if (Zeit_Entprellen > 10){ // alle 10 ms x 1,1 ms = 11 ms |
68 | i = key_state ^ ~KEY_PIN; // key changed ? |
69 | ct0 = ~( ct0 & i ); // reset or count ct0 |
70 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1 |
71 | i &= ct0 & ct1; // count until roll over ? |
72 | key_state ^= i; // then toggle debounced state |
73 | key_press |= key_state & i; // 0->1: key press detect |
74 | Zeit_Entprellen = 0; // Entprellmultiplikator zurücksetzen |
75 | }
|
76 | if (Zeit_mul > 90){ // alle 91 ms x 1,1 ms = 100,1 ms |
77 | Zeit++; // Zeit in 1/10 sec weiterzählen |
78 | Zeit_mul = 0; // Zeitmultiplikator zurücksetzten |
79 | }
|
80 | }
|
81 | |
82 | void Buffer_Init(void){ |
83 | Zeiger = 0; // Bufferzeiger auf Anfang |
84 | Buffer[0] = 0; // Buffer löschen |
85 | Buffer[1] = 0; // Buffer löschen |
86 | Buffer[2] = 0; // Buffer löschen |
87 | }
|
88 | |
89 | inline void Init(void){ |
90 | // Tasten
|
91 | Taste_DDR &= ~(1<<Taste1)|(1<<Taste2); // Taste1 & Taste2 Eingang |
92 | Taste_PORT |= (1<<Taste1)|(1<<Taste2); // Taste1 & Taste2 Pullup an |
93 | // Led
|
94 | Led_DDR |= (1<<Led1)|(1<<Led2)|(1<<Led3); // Led1 & Led2 & Led3 Ausgang |
95 | Led_PORT |= (1<<Led1)|(1<<Led2)|(1<<Led3); // Led1 & Led2 & Led3 aus |
96 | // Timer 0
|
97 | TCCR0A = 0; // Timer Normal Mode |
98 | TCCR0B = (1<<CS02); // clkI/O / 256 (From prescaler) |
99 | TIMSK |= (1<<TOIE0); // Timer/Counter0 Overflow Interrupt an |
100 | // Buffer
|
101 | Buffer_Init(); // Bufferspeicher initialisieren |
102 | }
|
103 | |
104 | int main(void){ |
105 | Init(); // alles Initialisieren |
106 | sei(); // Interrupt Global ein |
107 | while(1){ // Endlosschleife |
108 | |
109 | if (Zeit > 30){ // wenn ca. 30 1/10 sec = 3 sec um sind |
110 | Buffer_Init(); // Bufferspeicher initialisieren |
111 | }
|
112 | |
113 | if(get_key_press(1<<Taste1)){ // ist Taste1 gedrückt? |
114 | if (Zeiger == 0){ // erste Taste gedrückt |
115 | Zeit = 0; // Zeit zurücksetzen |
116 | }
|
117 | if (Zeiger < max_Buffer_len - 1){ // wenn noch keine 3 Tasten gespeichert sind |
118 | Buffer[Zeiger] = 1; // Tastendruck merken |
119 | Zeiger++; // Zeiger weitersetzen |
120 | }
|
121 | else{ // es sind schon 3 Tasten gespeichert |
122 | Buffer[0] = Buffer[1]; // Bufferdaten Byteweise 1x links schieben, Byte 1 |
123 | Buffer[1] = Buffer[2]; // Bufferdaten Byteweise 1x links schieben, Byte 2 |
124 | Buffer[2] = 1; // Tastendruck in Byte 2 merken |
125 | }
|
126 | }
|
127 | else if(get_key_press(1<<Taste2)){ // ist Taste2 gedrückt? |
128 | if (Zeiger == 0){ // erste Taste gedrückt |
129 | Zeit = 0; // Zeit zurücksetzen |
130 | }
|
131 | if (Zeiger < max_Buffer_len - 1){ // wenn noch keine 3 Tasten gespeichert sind |
132 | Buffer[Zeiger] = 2; // Tastendruck merken |
133 | Zeiger++; // Zeiger weitersetzen |
134 | }
|
135 | else{ // es sind schon 3 Tasten gespeichert |
136 | Buffer[0] = Buffer[1]; // Bufferdaten Byteweise 1x links schieben, Byte 1 |
137 | Buffer[1] = Buffer[2]; // Bufferdaten Byteweise 1x links schieben, Byte 2 |
138 | Buffer[2] = 2; // Tastendruck in Byte 2 merken |
139 | }
|
140 | }
|
141 | |
142 | if (Buffer[0] == 1 && Buffer[1] == 1 && Buffer[2] == 1){// gedrückt Taste1 + Taste1 + Taste1 |
143 | Led1_an; |
144 | Led2_aus; |
145 | Led3_aus; |
146 | Buffer_Init(); // Bufferspeicher initialisieren |
147 | }
|
148 | if (Buffer[0] == 1 && Buffer[1] == 1 && Buffer[2] == 2){// gedrückt Taste1 + Taste1 + Taste2 |
149 | Led1_aus; |
150 | Led2_an; |
151 | Led3_aus; |
152 | Buffer_Init(); // Bufferspeicher initialisieren |
153 | }
|
154 | if (Buffer[0] == 1 && Buffer[1] == 2 && Buffer[2] == 1){// gedrückt Taste1 + Taste2 + Taste1 |
155 | Led1_aus; |
156 | Led2_aus; |
157 | Led3_an; |
158 | Buffer_Init(); // Bufferspeicher initialisieren |
159 | }
|
160 | }
|
161 | }
|
Gruß Rene
Rene Zimmermann schrieb: Das hier > if(get_key_press(1<<Taste1)){ // ist Taste1 gedrückt? > if (Zeiger == 0){ // erste Taste gedrückt > Zeit = 0; // Zeit zurücksetzen > } > if (Zeiger < max_Buffer_len - 1){ // wenn noch keine 3 > Tasten gespeichert sind > Buffer[Zeiger] = 1; // Tastendruck merken > Zeiger++; // Zeiger weitersetzen > } > else{ // es sind schon 3 Tasten > gespeichert > Buffer[0] = Buffer[1]; // Bufferdaten Byteweise > 1x links schieben, Byte 1 > Buffer[1] = Buffer[2]; // Bufferdaten Byteweise > 1x links schieben, Byte 2 > Buffer[2] = 1; // Tastendruck in Byte 2 > merken > } > } > else if(get_key_press(1<<Taste2)){ // ist Taste2 > gedrückt? > if (Zeiger == 0){ // erste Taste gedrückt > Zeit = 0; // Zeit zurücksetzen > } > if (Zeiger < max_Buffer_len - 1){ // wenn noch keine 3 > Tasten gespeichert sind > Buffer[Zeiger] = 2; // Tastendruck merken > Zeiger++; // Zeiger weitersetzen > } > else{ // es sind schon 3 Tasten > gespeichert > Buffer[0] = Buffer[1]; // Bufferdaten Byteweise > 1x links schieben, Byte 1 > Buffer[1] = Buffer[2]; // Bufferdaten Byteweise > 1x links schieben, Byte 2 > Buffer[2] = 2; // Tastendruck in Byte 2 > merken > } > } kannst du vereinfachen. ISt doch jedesmal derselbe Code, nur eine einzige Zahl (nämlich die Tastennummer) ist anders. Also könnte man zb
1 | nextTaste = 0; |
2 | |
3 | if( get_key_press(1<<Taste1) ) |
4 | nextTaste = 1; |
5 | |
6 | if( get_key_press(1<<Taste2) ) |
7 | nextTaste = 2; |
8 | |
9 | if( nextTaste != 0 ) { // eine Taste wurd egedrückt, füge sie ein |
10 | |
11 | if (Zeiger == 0){ // erste Taste gedrückt |
12 | Zeit = 0; // Zeit zurücksetzen |
13 | }
|
14 | if (Zeiger < max_Buffer_len - 1){ // wenn noch keine 3 Tasten gespeichert sind |
15 | Buffer[Zeiger] = nextTaste; // Tastendruck merken |
16 | Zeiger++; // Zeiger weitersetzen |
17 | }
|
18 | else{ // es sind schon 3 Tasten gespeichert |
19 | Buffer[0] = Buffer[1]; // Bufferdaten Byteweise 1x links schieben, Byte 1 |
20 | Buffer[1] = Buffer[2]; // Bufferdaten Byteweise 1x links schieben, Byte 2 |
21 | Buffer[2] = nextTaste; // Tastendruck in Byte 2 merken |
22 | }
|
23 | }
|
und schon fällt die Hälfte von diesem Code weg. Und noch besser, bei Änderungen am Verhalten kann man nicht vergessen, das für beide Tasten gleich zu ändern. Und da dein Programm sowieso schon optisch relativ lang ist, bietet es sich an, den Akt des Einfügens in eine Funktion auszulagern
1 | void insertTaste( uint8_t nextTaste ) |
2 | {
|
3 | if (Zeiger == 0){ // erste Taste gedrückt |
4 | Zeit = 0; // Zeit zurücksetzen |
5 | }
|
6 | |
7 | if (Zeiger < max_Buffer_len - 1) { // wenn noch keine 3 Tasten gespeichert sind |
8 | Buffer[Zeiger] = nextTaste; // Tastendruck merken |
9 | Zeiger++; // Zeiger weitersetzen |
10 | }
|
11 | else { // es sind schon 3 Tasten gespeichert |
12 | Buffer[0] = Buffer[1]; // Bufferdaten Byteweise 1x links schieben, Byte 1 |
13 | Buffer[1] = Buffer[2]; // Bufferdaten Byteweise 1x links schieben, Byte 2 |
14 | Buffer[2] = nextTaste; // Tastendruck in Byte 2 merken |
15 | }
|
16 | }
|
17 | |
18 | |
19 | int main() |
20 | {
|
21 | ....
|
22 | |
23 | while( 1 ) { |
24 | |
25 | if (Zeit > 30){ // wenn ca. 30 1/10 sec = 3 sec um sind |
26 | Buffer_Init(); // Bufferspeicher initialisieren |
27 | }
|
28 | |
29 | if( get_key_press(1<<Taste1) ) // ist Taste1 gedrückt? |
30 | insertTaste( 1 ); |
31 | |
32 | else if( get_key_press(1<<Taste2) ) // ist Taste2 gedrückt? |
33 | insertTaste( 2 ); |
34 | |
35 | // die empfangene Sequenz auswerten, ob es eine Übereinstimmung gibt
|
36 | |
37 | if (Buffer[0] == 1 && Buffer[1] == 1 && Buffer[2] == 1){// gedrückt Taste1 + Taste1 + Taste1 |
38 | Led1_an; |
39 | Led2_aus; |
40 | ....
|
und du bist am Weg, deinen Code selbstdokumentierend zu machen.
1 | if( get_key_press( 1<<Taste1 ) ) // ist Taste1 gedrückt? |
2 | insertTaste( 1 ); |
Da erzählt der Code schon die ganze Geschichte. Da braucht es keinen zusätzlichen Kommentar. Im Code steht mehr oder weniger im Klartext: Wenn Taste 1 gedrückt, dann füge eine 1 zum Tastenbuffer hinzu. Jede Codeänderung, die es dir ermöglicht einen Kommentar loszuwerden, ist eine gute Änderung. Entgegen landläufiger Meinung ist ein Programm nicht dann besonders gut, wenn es viele Kommentare enthält, sondern dasjenige ist gut, welches keine Kommentare braucht, weil alles Wissenswerte schon im Programmtext selber steht. Kommentare beschränken sich dann auf die Dinge, die man eben nicht im Code sieht. Was zb. erzählt mir hier
1 | Buffer[2] = nextTaste; // Tastendruck in Byte 2 merken |
der Kommentar, was ich nicht auch schon im Code sehe. Das ist ein unnützer Kommentar, der im besten Fall einfach nur nichtssagend ist, im schlimmsten Fall aber falsch ist (weil er nach Codeänderungen nicht an die Änderung angepasst wurde) Für die Auswertung kann man sich dann auch noch was überlegen, bzw. diese zb in eine eigene Funktion auslagern. Dein Hauptschleife wird dann
1 | while( 1 ) { |
2 | |
3 | if (Zeit > 30){ // wenn ca. 30 1/10 sec = 3 sec um sind |
4 | Buffer_Init(); // Bufferspeicher initialisieren |
5 | }
|
6 | |
7 | if( get_key_press(1<<Taste1) ) // ist Taste1 gedrückt? |
8 | insertTaste( 1 ); |
9 | |
10 | else if( get_key_press(1<<Taste2) ) // ist Taste2 gedrückt? |
11 | insertTaste( 2 ); |
12 | |
13 | checkForSequences(); |
14 | }
|
(und die Funktion checkForSequences überprüft, ob es eine Sequenz im Buffer gibt). Schöne kurze Hauptschleife, die man mit einem Blick überschauen kann und bei der man sofort erkennt, was das Programm im wesentlichen macht. Wenn man an den Details interessiert ist, wie genau zb das Hinzufügen zum Buffer funktioniert, dann hat man die Funktion, in der nur dieses 1 Detail konzentriert ist.
Woooo! Und ich habe mir Gedanken gemacht ob das byteweise Linksschieben im Buffer noch besser zu lösen ist. Oh je, ich gehe mal meinen Verstand suchen. "grins" Ich habe es jetzt mal schnell auf folgenden Code gebracht:
1 | // Tasten Entprellroutine von Peter Dannegger: danni@specs.de
|
2 | |
3 | #include <stdio.h> |
4 | #include <avr/io.h> |
5 | #include <avr/interrupt.h> |
6 | |
7 | #define Taste_DDR DDRB
|
8 | #define Taste_PIN PINB
|
9 | #define Taste_PORT PORTB
|
10 | #define Taste1 PB4
|
11 | #define Taste2 PB3
|
12 | |
13 | #define Led_DDR DDRB
|
14 | #define Led_PORT PORTB
|
15 | #define Led1 PB2
|
16 | #define Led2 PB1
|
17 | #define Led3 PB0
|
18 | |
19 | #define KEY_DDR Taste_DDR
|
20 | #define KEY_PORT Taste_PORT
|
21 | #define KEY_PIN Taste_PIN
|
22 | #define KEY0 Taste1
|
23 | #define KEY1 Taste2
|
24 | #define ALL_KEYS (1<<KEY0 | 1<<KEY1)
|
25 | |
26 | #define Led1_an Led_PORT &= ~(1<<Led1)
|
27 | #define Led1_aus Led_PORT |= (1<<Led1)
|
28 | #define Led2_an Led_PORT &= ~(1<<Led2)
|
29 | #define Led2_aus Led_PORT |= (1<<Led2)
|
30 | #define Led3_an Led_PORT &= ~(1<<Led3)
|
31 | #define Led3_aus Led_PORT |= (1<<Led3)
|
32 | |
33 | #define Timer0_Reload 255 - 43 // 1,1 ms bei 11,0592 MHz
|
34 | |
35 | #define max_Buffer_len 3 // max. 3 Tasten speichern
|
36 | |
37 | uint8_t Buffer[max_Buffer_len]; // Buffer für Tasten |
38 | |
39 | //GPIOR sollte schneller sein als volatile auf Ram, ist das so ?????? Ich denke ja. Muß ich noch prüfen !!!!!!
|
40 | |
41 | #define Zeiger GPIOR0 // Zeiger für Bufferposition
|
42 | #define Zeit GPIOR1 // Zeitzähler
|
43 | #define Zeit_mul GPIOR2 // Zeitmultiplikator für Interrupt
|
44 | |
45 | volatile uint8_t Zeit_Entprellen; |
46 | volatile uint8_t key_state; // debounced and inverted key state: |
47 | volatile uint8_t key_press; // key press detect |
48 | |
49 | |
50 | uint8_t get_key_press(uint8_t key_mask){ |
51 | cli(); // read and clear atomic ! |
52 | key_mask &= key_press; // read key(s) |
53 | key_press ^= key_mask; // clear key(s) |
54 | sei(); |
55 | return key_mask; |
56 | }
|
57 | |
58 | void insertTaste(uint8_t nextTaste){ |
59 | if (Zeiger == 0){ // erste Taste gedrückt |
60 | Zeit = 0; // Zeit zurücksetzen |
61 | }
|
62 | |
63 | if (Zeiger < max_Buffer_len - 1){ // wenn noch keine 3 Tasten gespeichert sind |
64 | Buffer[Zeiger] = nextTaste; // Tastendruck merken |
65 | Zeiger++; // Zeiger weitersetzen |
66 | }
|
67 | else { // es sind schon 3 Tasten gespeichert |
68 | Buffer[0] = Buffer[1]; // Bufferdaten Byteweise 1x links schieben, Byte 1 |
69 | Buffer[1] = Buffer[2]; // Bufferdaten Byteweise 1x links schieben, Byte 2 |
70 | Buffer[2] = nextTaste; // Tastendruck in Byte 2 merken |
71 | }
|
72 | }
|
73 | |
74 | ISR(TIMER0_OVF_vect){ // Timer0 Overflow alle 1,1 ms, 1,1 ms ist fest da |
75 | // noch für andere Sachen gebraucht, leider !!!!
|
76 | static uint8_t ct0, ct1; |
77 | uint8_t i; |
78 | |
79 | TCNT0 = Timer0_Reload; // Reloadwert laden |
80 | |
81 | if (Zeit_Entprellen > 9){ // alle 10 ms x 1,1 ms = 11 ms |
82 | i = key_state ^ ~KEY_PIN; // key changed ? |
83 | ct0 = ~( ct0 & i ); // reset or count ct0 |
84 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1 |
85 | i &= ct0 & ct1; // count until roll over ? |
86 | key_state ^= i; // then toggle debounced state |
87 | key_press |= key_state & i; // 0->1: key press detect |
88 | Zeit_Entprellen = 0; // Entprellmultiplikator zurücksetzen |
89 | }
|
90 | if (Zeit_mul > 90){ // alle 91 ms x 1,1 ms = 100,1 ms |
91 | Zeit++; // Zeit in 1/10 sec weiterzählen |
92 | Zeit_mul = 0; // Zeitmultiplikator zurücksetzten |
93 | }
|
94 | }
|
95 | |
96 | void Buffer_Init(void){ |
97 | Zeiger = 0; // Bufferzeiger auf Anfang |
98 | Buffer[0] = 0; // Buffer löschen |
99 | Buffer[1] = 0; // Buffer löschen |
100 | Buffer[2] = 0; // Buffer löschen |
101 | }
|
102 | |
103 | inline void Init(void){ |
104 | // Tasten
|
105 | Taste_DDR &= ~(1<<Taste1)|(1<<Taste2); // Taste1 & Taste2 Eingang |
106 | Taste_PORT |= (1<<Taste1)|(1<<Taste2); // Taste1 & Taste2 Pullup an |
107 | // Led
|
108 | Led_DDR |= (1<<Led1)|(1<<Led2)|(1<<Led3); // Led1 & Led2 & Led3 Ausgang |
109 | Led_PORT |= (1<<Led1)|(1<<Led2)|(1<<Led3); // Led1 & Led2 & Led3 aus |
110 | // Timer 0
|
111 | TCCR0A = 0; // Timer Normal Mode |
112 | TCCR0B = (1<<CS02); // clkI/O / 256 (From prescaler) |
113 | TIMSK |= (1<<TOIE0); // Timer/Counter0 Overflow Interrupt an |
114 | // Buffer
|
115 | Buffer_Init(); // Bufferspeicher initialisieren |
116 | }
|
117 | |
118 | void checkForSequences(void){ |
119 | if (Buffer[0] == 1 && Buffer[1] == 1 && Buffer[2] == 1){ // gedrückt Taste1 + Taste1 + Taste1 |
120 | Led1_an; |
121 | Led2_aus; |
122 | Led3_aus; |
123 | Buffer_Init(); // Bufferspeicher initialisieren |
124 | }
|
125 | if (Buffer[0] == 1 && Buffer[1] == 1 && Buffer[2] == 2){ // gedrückt Taste1 + Taste1 + Taste2 |
126 | Led1_aus; |
127 | Led2_an; |
128 | Led3_aus; |
129 | Buffer_Init(); // Bufferspeicher initialisieren |
130 | }
|
131 | if (Buffer[0] == 1 && Buffer[1] == 2 && Buffer[2] == 1){ // gedrückt Taste1 + Taste2 + Taste1 |
132 | Led1_aus; |
133 | Led2_aus; |
134 | Led3_an; |
135 | Buffer_Init(); // Bufferspeicher initialisieren |
136 | }
|
137 | }
|
138 | |
139 | int main(void){ |
140 | Init(); // alles Initialisieren |
141 | sei(); // Interrupt Global ein |
142 | while(1){ // Endlosschleife |
143 | |
144 | if (Zeit > 30){ // wenn ca. 30 1/10 sec = 3 sec um sind |
145 | Buffer_Init(); // Bufferspeicher initialisieren |
146 | }
|
147 | |
148 | if(get_key_press(1<<Taste1)){ // ist Taste1 gedrückt? |
149 | insertTaste(1); // Taste1 zum Buffer hinzufügen |
150 | }
|
151 | else if(get_key_press(1<<Taste2)){ // ist Taste2 gedrückt? |
152 | insertTaste(2); // Taste2 zum Buffer hinzufügen |
153 | }
|
154 | |
155 | checkForSequences(); // prüfe auf gültige Tastenkombination |
156 | |
157 | }
|
158 | }
|
Muß das morgen mal auf das Steckbrett bringen und testen. Gruß Rene
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.