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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Pappsack (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
nur key_press bleibt bis zur Abfrage gespeichert...

von Theor (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
2 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.