Forum: Mikrocontroller und Digitale Elektronik Frage zu Entprell-Routine von Peter Dannegger


von Pappsack (Gast)


Lesenswert?

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...

von Denis (Gast)


Lesenswert?

nur key_press bleibt bis zur Abfrage gespeichert...

von Theor (Gast)


Lesenswert?

An sich werden die erkannten Tasten mit einem get_key_press gelöscht.

[c]
uint8_t get_key_press( uint8_t key_mask )
{
  cli();                                          // read and clear 
atomic !
  key_mask &= key_press;                          // read key(s)

  key_press ^= key_mask;                          // CLEAR KEY(S)
  sei();
  return key_mask;
}
[\c]

Du brauchst sie also nicht selbst löschen, sondern im Deinem 
"Stand-By-Modus" nur die Taste(n) auswerten, die relevant ist bzw. sind.
Das wäre mein Vorschlag.

Umgekehrt, kann man nur vermuten, - wir kennen ja Deinen Code nicht -, 
dass Du den Tastenzustand speicherst, den Stand-By-Zustand aufgrund 
einer Menuetaste verlässt und dann den, in Deinem Code gespeicherten 
Zustand,  nicht löschst bzw. nicht ignorierst.

Es handelst sich, mit Verlaub und wenn meine Annahme stimmt, also eher 
ein Problem mit Deinem Code.

Glaub mir - lach -, wenn man in Peters Code einen Fehler findet, dann 
hat man einen Fehler gemacht. Ging mir selbst auch schon so. :-)

von Peter D. (peda)


Lesenswert?

Du must keine neue Funktion schreiben. Du kannst an der Stelle, wo der 
Menüwechsel erfolgt, get_key_short bzw. get_key_long einfach aufrufen, 
ohne das Ergebnis zu benutzen.

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
Noch kein Account? Hier anmelden.