Hallo alle,
ich habe ich mich gerade etwas festgefahren und dachte, dass vielleicht
von euch jemand eine Idee hat.
Für mein aktuelles Projekt (Wetterstation) habe ich ein OLED Display mit
4 darunter sitzenden Tastern [MENU] [UP] [DOWN] [ENTER].
Diese 4 Taster werden über die "Komfort" Methode von Peter Danneger
entprellt und gelesen
(https://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29)
Einziger Unterschied zur Vorlage:
Der Code in der ISR wurde bei mir als normale Funktion (updateButtons())
implementiert und wird alle 10ms aus main() heraus aufgerufen.
Alles funktioniert einwandfrei: get_key_short, get_key_long - super
easy!
Vielen Dank an dieser Stelle.
Dennoch habe ich ein Problem.
Nehmen wir mal an, ich habe einen Standby-Bildschirm, auf dem einfach
nur die Temperatur dargestellt wird. Drückt man nun auf die Menütaste,
so wird vom Standbymodus in den Menümodus gewechselt und man kann sich
mit den Up/Down/Enter Buttons durch das Menü hangeln.
Wenn ich im Standbymodus aber nicht die Menütaste, sondern bspw. die
ENTER Taste drücke, so passiert dort erstmal gar nix - die Entertaste
wird ja auch im Standby-Modus nicht gelesen/ausgewertet.
Betätige ich dann korrekterweise die Menütaste, so wird erwartungsgemäß
das Menü aufgerufen. Allerdings wird dort sofort auch die Enter-Taste
von vorhin erkannt, weshalb ich dann sofort im ersten Untermenü lande.
Es scheint also, dass ein Tastendruck nicht verfällt, bis er irgendwann
gelesen wird.
Nun möchte ich mir gerne eine clearButtons(uint8_t) Funktion schreiben,
mit der ich gezielt einzelne oder mehrere Tasten zurücksetzen kann, z.B.
so:
1 | clearButtons( (1<<BTN_ENTER) | (1<<BTN_UP) |(1<<BTN_DOWN));
|
Allerdings verstehe ich Peters Code nicht so recht:
1 | volatile uint8_t key_state; // debounced and inverted key state:
|
2 | // bit = 1: key pressed
|
3 | volatile uint8_t key_press; // key press detect
|
4 | volatile uint8_t key_rpt; // key long press and repeat
|
5 |
|
6 |
|
7 | ISR( TIMER0_OVF_vect ) // every 10ms
|
8 | {
|
9 | static uint8_t ct0 = 0xFF, ct1 = 0xFF, rpt;
|
10 | uint8_t i;
|
11 |
|
12 | TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms
|
13 |
|
14 | i = key_state ^ ~KEY_PIN; // key changed ?
|
15 | ct0 = ~( ct0 & i ); // reset or count ct0
|
16 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1
|
17 | i &= ct0 & ct1; // count until roll over ?
|
18 | key_state ^= i; // then toggle debounced state
|
19 | key_press |= key_state & i; // 0->1: key press detect
|
20 |
|
21 | if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
|
22 | rpt = REPEAT_START; // start delay
|
23 | if( --rpt == 0 ){
|
24 | rpt = REPEAT_NEXT; // repeat delay
|
25 | key_rpt |= key_state & REPEAT_MASK;
|
26 | }
|
27 | }
|
Wo wird sich denn hier letztlich ein Tastendruck gemerkt? In key_state?
Wenn ich die in clearButtons() alle 0 setze, ergibt sich keine Änderung.
get_key_short() sieht immer noch eine gedrückte Enter-Taste...