Hallo leute fuer euch Profis wahrscheinlich ein ganz simples Problem. Ich möchte einen Taster abfragen ob er mehrmals gedrückt ist. Genauergesagt ober 5 mal gedrückt wurde. Ich hätte jetzt gedacht an eine Schleife die 20 ms Sekunden warten und so eine Zählvariable raufzähl, jedoch funktioniert nicht wirklich? Ist diese Idee von dem Grundkonzept brauchbar?, den aus dem Wiki Artikel werde ich als Laie nicht wirklich schlau daraus. Ich hoffe ich geh auch nicht allzu sehr auf die Nerven falls doch Entschuldige ich mich gleich vorwegs. mfG Lukas
Aufpassen. Taster neigen zum prellen. Dies könnte auch schon als Tastendruck gewertet werden. Sonst geht es mit einer Zählvariable.
Mehrmaliges Drücken ist dadurch gekennzeichnet, dass es Gedrückt- und Losgelassen-Phasen bestimmter Mindestdauern und im Wechsel gibt. Beides kann man schon in einer Schleife abfragen. Die Zeit 20ms für ein sicheres Erkennen eines Zustands ("gedrückt/losgelassen wird nur registriert, wenn 20ms noch gedrückt/losgelassen ist") kann man nehmen. Das läuft dann auf das Warteschleifen-Verfahren bei der Softwareentprellung von Tastern raus (Entprellung)
ich hab jz den Code :
1 | /************************************************************************/
|
2 | /* */
|
3 | /* Debouncing 8 Keys */
|
4 | /* Sampling 4 Times */
|
5 | /* With Repeat Function */
|
6 | /* */
|
7 | /* Author: Peter Dannegger */
|
8 | /* danni@specs.de */
|
9 | /* */
|
10 | /************************************************************************/
|
11 | |
12 | #include <stdint.h> |
13 | #include <avr/io.h> |
14 | #include <avr/interrupt.h> |
15 | |
16 | #ifndef F_CPU
|
17 | #define F_CPU 1000000 // processor clock frequency
|
18 | #warning kein F_CPU definiert
|
19 | #endif
|
20 | |
21 | #define KEY_DDR DDRD
|
22 | #define KEY_PORT PORTD
|
23 | #define KEY_PIN PIND
|
24 | #define KEY0 7
|
25 | #define KEY1 7
|
26 | #define KEY2 7
|
27 | #define ALL_KEYS (1<<KEY0 | 1<<KEY1 | 1<<KEY2)
|
28 | |
29 | #define REPEAT_MASK (1<<KEY1 | 1<<KEY2) // repeat: key1, key2
|
30 | #define REPEAT_START 50 // after 500ms
|
31 | #define REPEAT_NEXT 20 // every 200ms
|
32 | |
33 | #define LED_DDR DDRD
|
34 | #define LED_PORT PORTD
|
35 | #define LED0 5
|
36 | #define LED1 5
|
37 | #define LED2 5
|
38 | |
39 | volatile uint8_t key_state; // debounced and inverted key state: |
40 | // bit = 1: key pressed
|
41 | volatile uint8_t key_press; // key press detect |
42 | |
43 | volatile uint8_t key_rpt; // key long press and repeat |
44 | |
45 | |
46 | ISR( TIMER0_OVF_vect ) // every 10ms |
47 | {
|
48 | static uint8_t ct0, ct1, rpt; |
49 | uint8_t i; |
50 | |
51 | TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms |
52 | |
53 | i = key_state ^ ~KEY_PIN; // key changed ? |
54 | ct0 = ~( ct0 & i ); // reset or count ct0 |
55 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1 |
56 | i &= ct0 & ct1; // count until roll over ? |
57 | key_state ^= i; // then toggle debounced state |
58 | key_press |= key_state & i; // 0->1: key press detect |
59 | |
60 | if( (key_state & REPEAT_MASK) == 0 ) // check repeat function |
61 | rpt = REPEAT_START; // start delay |
62 | if( --rpt == 0 ){ |
63 | rpt = REPEAT_NEXT; // repeat delay |
64 | key_rpt |= key_state & REPEAT_MASK; |
65 | }
|
66 | }
|
67 | |
68 | ///////////////////////////////////////////////////////////////////
|
69 | //
|
70 | // check if a key has been pressed. Each pressed key is reported
|
71 | // only once
|
72 | //
|
73 | uint8_t get_key_press( uint8_t key_mask ) |
74 | {
|
75 | cli(); // read and clear atomic ! |
76 | key_mask &= key_press; // read key(s) |
77 | key_press ^= key_mask; // clear key(s) |
78 | sei(); |
79 | return key_mask; |
80 | }
|
81 | |
82 | ///////////////////////////////////////////////////////////////////
|
83 | //
|
84 | // check if a key has been pressed long enough such that the
|
85 | // key repeat functionality kicks in. After a small setup delay
|
86 | // the key is reported beeing pressed in subsequent calls
|
87 | // to this function. This simulates the user repeatedly
|
88 | // pressing and releasing the key.
|
89 | //
|
90 | uint8_t get_key_rpt( uint8_t key_mask ) |
91 | {
|
92 | cli(); // read and clear atomic ! |
93 | key_mask &= key_rpt; // read key(s) |
94 | key_rpt ^= key_mask; // clear key(s) |
95 | sei(); |
96 | return key_mask; |
97 | }
|
98 | |
99 | ///////////////////////////////////////////////////////////////////
|
100 | //
|
101 | uint8_t get_key_short( uint8_t key_mask ) |
102 | {
|
103 | cli(); // read key state and key press atomic ! |
104 | return get_key_press( ~key_state & key_mask ); |
105 | }
|
106 | |
107 | ///////////////////////////////////////////////////////////////////
|
108 | //
|
109 | uint8_t get_key_long( uint8_t key_mask ) |
110 | {
|
111 | return get_key_press( get_key_rpt( key_mask )); |
112 | }
|
113 | |
114 | int main( void ) |
115 | {
|
116 | KEY_DDR &= ~ALL_KEYS; // konfigure key port for input |
117 | KEY_PORT |= ALL_KEYS; // and turn on pull up resistors |
118 | |
119 | TCCR0 = (1<<CS02)|(1<<CS00); // divide by 1024 |
120 | TIMSK = 1<<TOIE0; // enable timer interrupt |
121 | |
122 | LED_PORT = 0xFF; |
123 | LED_DDR = 0xFF; |
124 | |
125 | while(1){ |
126 | if( get_key_short( 1<<KEY1 )) |
127 | LED_PORT ^= 1<<LED1; |
128 | |
129 | if( get_key_long( 1<<KEY1 )) |
130 | LED_PORT ^= 1<<LED2; |
131 | |
132 | // single press and repeat
|
133 | |
134 | if( get_key_press( 1<<KEY2 ) || get_key_rpt( 1<<KEY2 )){ |
135 | uint8_t i = LED_PORT; |
136 | |
137 | i = (i & 0x07) | ((i << 1) & 0xF0); |
138 | if( i < 0xF0 ) |
139 | i |= 0x08; |
140 | LED_PORT = i; |
141 | }
|
142 | }
|
143 | }
|
jedoch leuchtet bei Betätigung des Taster keine Led auf, die Definition meiner Ports müsste richtig sein PD7--> Taster(High Active) PD5--> Led Ich frage mich schon ne Zeit woran das liegen könnte? mfG
Lukas Migi schrieb: > PD7--> Taster(High Active) > PD5--> Led Du hast Taster und LED an ein und demselben Port
1 | TCCR0 = (1<<CS02)|(1<<CS00); // divide by 1024 |
2 | TIMSK = 1<<TOIE0; // enable timer interrupt |
3 | |
4 | LED_PORT = 0xFF; |
5 | LED_DDR = 0xFF; |
Gratuliere. Du hast soeben den komplette Port D auf Ausgang gestellt
Peinlich Peinlich :D ich hab jz den Taster auf PortB gelegt:
1 | /************************************************************************/
|
2 | /* */
|
3 | /* Debouncing 8 Keys */
|
4 | /* Sampling 4 Times */
|
5 | /* With Repeat Function */
|
6 | /* */
|
7 | /* Author: Peter Dannegger */
|
8 | /* danni@specs.de */
|
9 | /* */
|
10 | /************************************************************************/
|
11 | |
12 | #include <stdint.h> |
13 | #include <avr/io.h> |
14 | #include <avr/interrupt.h> |
15 | |
16 | #ifndef F_CPU
|
17 | #define F_CPU 1000000 // processor clock frequency
|
18 | #warning kein F_CPU definiert
|
19 | #endif
|
20 | |
21 | #define KEY_DDR DDRB
|
22 | #define KEY_PORT PORTB
|
23 | #define KEY_PIN PINB
|
24 | #define KEY0 1
|
25 | #define KEY1 1
|
26 | #define KEY2 1
|
27 | #define ALL_KEYS (1<<KEY0 | 1<<KEY1 | 1<<KEY2)
|
28 | |
29 | #define REPEAT_MASK (1<<KEY1 | 1<<KEY2) // repeat: key1, key2
|
30 | #define REPEAT_START 50 // after 500ms
|
31 | #define REPEAT_NEXT 20 // every 200ms
|
32 | |
33 | #define LED_DDR DDRD
|
34 | #define LED_PORT PORTD
|
35 | #define LED0 5
|
36 | #define LED1 5
|
37 | #define LED2 5
|
38 | |
39 | volatile uint8_t key_state; // debounced and inverted key state: |
40 | // bit = 1: key pressed
|
41 | volatile uint8_t key_press; // key press detect |
42 | |
43 | volatile uint8_t key_rpt; // key long press and repeat |
44 | |
45 | |
46 | ISR( TIMER0_OVF_vect ) // every 10ms |
47 | {
|
48 | static uint8_t ct0, ct1, rpt; |
49 | uint8_t i; |
50 | |
51 | TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms |
52 | |
53 | i = key_state ^ ~KEY_PIN; // key changed ? |
54 | ct0 = ~( ct0 & i ); // reset or count ct0 |
55 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1 |
56 | i &= ct0 & ct1; // count until roll over ? |
57 | key_state ^= i; // then toggle debounced state |
58 | key_press |= key_state & i; // 0->1: key press detect |
59 | |
60 | if( (key_state & REPEAT_MASK) == 0 ) // check repeat function |
61 | rpt = REPEAT_START; // start delay |
62 | if( --rpt == 0 ){ |
63 | rpt = REPEAT_NEXT; // repeat delay |
64 | key_rpt |= key_state & REPEAT_MASK; |
65 | }
|
66 | }
|
67 | |
68 | ///////////////////////////////////////////////////////////////////
|
69 | //
|
70 | // check if a key has been pressed. Each pressed key is reported
|
71 | // only once
|
72 | //
|
73 | uint8_t get_key_press( uint8_t key_mask ) |
74 | {
|
75 | cli(); // read and clear atomic ! |
76 | key_mask &= key_press; // read key(s) |
77 | key_press ^= key_mask; // clear key(s) |
78 | sei(); |
79 | return key_mask; |
80 | }
|
81 | |
82 | ///////////////////////////////////////////////////////////////////
|
83 | //
|
84 | // check if a key has been pressed long enough such that the
|
85 | // key repeat functionality kicks in. After a small setup delay
|
86 | // the key is reported beeing pressed in subsequent calls
|
87 | // to this function. This simulates the user repeatedly
|
88 | // pressing and releasing the key.
|
89 | //
|
90 | uint8_t get_key_rpt( uint8_t key_mask ) |
91 | {
|
92 | cli(); // read and clear atomic ! |
93 | key_mask &= key_rpt; // read key(s) |
94 | key_rpt ^= key_mask; // clear key(s) |
95 | sei(); |
96 | return key_mask; |
97 | }
|
98 | |
99 | ///////////////////////////////////////////////////////////////////
|
100 | //
|
101 | uint8_t get_key_short( uint8_t key_mask ) |
102 | {
|
103 | cli(); // read key state and key press atomic ! |
104 | return get_key_press( ~key_state & key_mask ); |
105 | }
|
106 | |
107 | ///////////////////////////////////////////////////////////////////
|
108 | //
|
109 | uint8_t get_key_long( uint8_t key_mask ) |
110 | {
|
111 | return get_key_press( get_key_rpt( key_mask )); |
112 | }
|
113 | |
114 | int main( void ) |
115 | {
|
116 | KEY_DDR &= ~ALL_KEYS; // konfigure key port for input |
117 | KEY_PORT |= ALL_KEYS; // and turn on pull up resistors |
118 | |
119 | TCCR0 = (1<<CS02)|(1<<CS00); // divide by 1024 |
120 | TIMSK = 1<<TOIE0; // enable timer interrupt |
121 | |
122 | LED_PORT = 0xFF; |
123 | LED_DDR = 0xFF; |
124 | |
125 | while(1){ |
126 | |
127 | |
128 | if( get_key_short( 1<<KEY1 )) |
129 | LED_PORT ^= 1<<LED1; |
130 | |
131 | if( get_key_long( 1<<KEY1 )) |
132 | LED_PORT ^= 1<<LED1; |
133 | |
134 | // single press and repeat
|
135 | |
136 | if( get_key_press( 1<<KEY2 ) || get_key_rpt( 1<<KEY2 )){ |
137 | uint8_t i = LED_PORT; |
138 | |
139 | i = (i & 0x07) | ((i << 1) & 0xF0); |
140 | if( i < 0xF0 ) |
141 | i |= 0x08; |
142 | LED_PORT = i; |
143 | }
|
144 | }
|
145 | }
|
jedoch ist die Situation gleich geblieben ... mfG
Überdenk das doch bitte noch mal
1 | uint8_t i = LED_PORT; |
2 | |
3 | i = (i & 0x07) | ((i << 1) & 0xF0); |
4 | if( i < 0xF0 ) |
5 | i |= 0x08; |
6 | LED_PORT = i; |
Nimm einfach mal an, so wie du das gemacht hast, dass LED_PORT am Anfang 0xFF ist. Und dann gehe einfach alles durch und sieh nach, was da am Ende dabei rauskommt und wie das deine LED am Pin 5 beeinflusst. Ich bin mir nicht ganz sicher, was da bei den Abfragen tatsächlich passiert. Aber warum teilst du den Tasten-Routinen mit, dass du 3 Tasten hättest, wenn dann alle Tasten am gleichen Pin sitzen. De Facto hast du damit ja nur 1 Taste. -> Hör auf die Routinen anzulügen und konfiguriere das richtig.
1 | #define KEY_DDR DDRB
|
2 | #define KEY_PORT PORTB
|
3 | #define KEY_PIN PINB
|
4 | #define KEY0 1
|
5 | #define ALL_KEYS (1<<KEY0)
|
6 | |
7 | #define REPEAT_MASK // kein Repeat auf irgendeiner Taste
|
Hilft auch nichts. Pull Up hab ich auch keinen Drauf da die Internen aktiv sind. Häng ich in die While (1)schleife ne Led Rein leuchtet die ohne Mucken. Irgendwie weis ich nicht woran das liegt? mfG
Du hast vergessen die Interrupts freizugeben Taster an Port B, Pin 1 LED an Port B, Pins 4, 5, 6
1 | #include <stdint.h> |
2 | #include <avr/io.h> |
3 | #include <avr/interrupt.h> |
4 | |
5 | #ifndef F_CPU
|
6 | #define F_CPU 1000000 // processor clock frequency
|
7 | #warning kein F_CPU definiert
|
8 | #endif
|
9 | |
10 | #define KEY_DDR DDRB
|
11 | #define KEY_PORT PORTB
|
12 | #define KEY_PIN PINB
|
13 | #define KEY0 1
|
14 | #define ALL_KEYS (1<<KEY0)
|
15 | |
16 | #define REPEAT_MASK 0 // repeat: key1, key2
|
17 | #define REPEAT_START 50 // after 500ms
|
18 | #define REPEAT_NEXT 20 // every 200ms
|
19 | |
20 | #define LED_DDR DDRB
|
21 | #define LED_PORT PORTB
|
22 | #define LED0 4
|
23 | #define LED1 5
|
24 | #define LED2 6
|
25 | |
26 | volatile uint8_t key_state; // debounced and inverted key state: |
27 | // bit = 1: key pressed
|
28 | volatile uint8_t key_press; // key press detect |
29 | |
30 | volatile uint8_t key_rpt; // key long press and repeat |
31 | |
32 | |
33 | ISR( TIMER0_OVF_vect ) // every 10ms |
34 | {
|
35 | static uint8_t ct0, ct1, rpt; |
36 | uint8_t i; |
37 | |
38 | TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms |
39 | |
40 | i = key_state ^ ~KEY_PIN; // key changed ? |
41 | ct0 = ~( ct0 & i ); // reset or count ct0 |
42 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1 |
43 | i &= ct0 & ct1; // count until roll over ? |
44 | key_state ^= i; // then toggle debounced state |
45 | key_press |= key_state & i; // 0->1: key press detect |
46 | |
47 | if( (key_state & REPEAT_MASK) == 0 ) // check repeat function |
48 | rpt = REPEAT_START; // start delay |
49 | if( --rpt == 0 ){ |
50 | rpt = REPEAT_NEXT; // repeat delay |
51 | key_rpt |= key_state & REPEAT_MASK; |
52 | }
|
53 | }
|
54 | |
55 | ///////////////////////////////////////////////////////////////////
|
56 | //
|
57 | // check if a key has been pressed. Each pressed key is reported
|
58 | // only once
|
59 | //
|
60 | uint8_t get_key_press( uint8_t key_mask ) |
61 | {
|
62 | cli(); // read and clear atomic ! |
63 | key_mask &= key_press; // read key(s) |
64 | key_press ^= key_mask; // clear key(s) |
65 | sei(); |
66 | return key_mask; |
67 | }
|
68 | |
69 | ///////////////////////////////////////////////////////////////////
|
70 | //
|
71 | // check if a key has been pressed long enough such that the
|
72 | // key repeat functionality kicks in. After a small setup delay
|
73 | // the key is reported beeing pressed in subsequent calls
|
74 | // to this function. This simulates the user repeatedly
|
75 | // pressing and releasing the key.
|
76 | //
|
77 | uint8_t get_key_rpt( uint8_t key_mask ) |
78 | {
|
79 | cli(); // read and clear atomic ! |
80 | key_mask &= key_rpt; // read key(s) |
81 | key_rpt ^= key_mask; // clear key(s) |
82 | sei(); |
83 | return key_mask; |
84 | }
|
85 | |
86 | ///////////////////////////////////////////////////////////////////
|
87 | //
|
88 | uint8_t get_key_short( uint8_t key_mask ) |
89 | {
|
90 | cli(); // read key state and key press atomic ! |
91 | return get_key_press( ~key_state & key_mask ); |
92 | }
|
93 | |
94 | ///////////////////////////////////////////////////////////////////
|
95 | //
|
96 | uint8_t get_key_long( uint8_t key_mask ) |
97 | {
|
98 | return get_key_press( get_key_rpt( key_mask )); |
99 | }
|
100 | |
101 | int main( void ) |
102 | {
|
103 | uint8_t cnt; |
104 | |
105 | KEY_DDR &= ~ALL_KEYS; // konfigure key port for input |
106 | KEY_PORT |= ALL_KEYS; // and turn on pull up resistors |
107 | |
108 | TCCR0 = (1<<CS02)|(1<<CS00); // divide by 1024 |
109 | TIMSK = 1<<TOIE0; // enable timer interrupt |
110 | |
111 | LED_DDR |= ( 1 << LED0 ) | (1<<LED1) | (1<<LED2); |
112 | |
113 | cnt = 0; |
114 | |
115 | sei(); |
116 | |
117 | while(1){ |
118 | |
119 | if( get_key_press( 1<<KEY0 )) { |
120 | cnt++; |
121 | LED_PORT = (cnt << 4) | ALL_KEYS; |
122 | }
|
123 | }
|
124 | }
|
tut mir Leid, dass ich immer mit so Anfängerfragen nerve, ich will jedoch nicht nur Programme abkupfern sondern die auch einigermaßen verstehen. Danke trotzdem für die hilfreichen Antworten! mfG, Lukas
Lukas Migi schrieb:
> welche Interrupts meinst du?
Die globale Interruptfreigabe mittels sei()
Ich habs jetzt nochmals getestet jedoch funktioniert das auch mit der Änderung der Interrupts nicht. Soll ich trotzdem einen externen Pullup verwenden? mfG
Jetzt leuchte auf einmal 2 Leds dauerhaft und bei der 3ten passiert nichts? Komisch irgendwie? Achja verwenden tu ich einen Mega8 mfG
Benutze das Programm, das ich weiter oben gepostet habe. Taster und Led so verdrahten wie angegeben. Das wurde auf einem Mega16 getestet und läuft definitiv. Bei jedem Tastendruck wird ein Zähler hochgezählt und der aktuelle Zählerstand an den 3 Led ausgegeben -> mit jedem Tastendruck ändert sich das Muster und du kannst die Binärzahlen an den Led erkennen.
>Soll ich trotzdem einen externen Pullup verwenden? Das ist schnurz, weil es höchstwahrscheinlich nicht am Pullup liegt, und auch nicht daran, dass der Controller defekt ist, und Dein Compiler hat auch keinen Bug. Es liegt schlicht an Deinem Programm. Projektvorschlag: Eine LED + ein Taster. Sonst nix. Die LED geht beim Drücken (und Loslassen) der Taste an, und beim nächsten Drücken wieder aus, und immer so weiter. "Ist ja voll easy" mag man glauben, aber das Gegenteil trifft zu: Dies so zu realisieren, dass es einwandfrei und zuverlässig funktioniert ist eine erstaunlich anspruchsvolle Aufgabenstellung, denn dazu muss der Taster ordentlich entprellt werden. Versuch, erstmal das hinzubekommen. Solange das nicht hundertpro klappt, kann auch alles weitere nicht richtig funzen. Step by Step heißt die Devise. Viel Erfolg.
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.