www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 1 sec Tastendruck - Code OK?


Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich möchte ein Tastendruck, was länger als 1 sec dauert, erkennen und 
danach einen Parameter ändern.

Folgendes:
1. ich prüfe ob eine Taste gedrückt wurde
2. wenn Taste gedrückt wurde, wegen Prellung warte ich 100usec und prüfe 
noch mal den Tastendruck
3. ist die Taste nach immer noch gedrückt, warte ich 1sec lang
4. nach 1sec schaue ich, ob immer noch die Taste gedrückt ist
5. ist nach 1 sec immer noch die Taste gedrückt, wird der Parameter 
geändert

Ist das eine gute Lösung? Bitte sagt mir, wie ihr es besser machen 
würdet

Vielen Dank
bool A1_value=0;

A1_value = A1_GetVal(); //Wert am Port A1 abfragen
if(A1_value) //wenn die Taste gedrückt ist A1_value->TRUE
{
  Cpu_Delay100US(1); //wegen Entprellung 100us delay

  A1_value &= A1_GetVal(); //Wert am Port A1 mit altem Wert UND-Verknüpfen

  if( A1_value ) // Taste gedrückt ->TRUE, sont FALSE
  {
    Cpu_Delay100US(10); //1sec warten und noch mal Wert am Port A1 abfragen
    A2_value &= A1_GetVal();

    if(A1_value) //wenn nach 1sec immer noch gedrückt A1_value->TRUE, sonst FALSE
    {
      modus=Mod_Transmission;
    }
  }
}

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Cpu_Delay100US(1); //wegen Entprellung 100us delay


Sawas ist schonmal Mist.

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eine Erklärung warum das "Mist" ist würde weiterhelfen :-)

Autor: Thomas Finke (thomas-hn) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> eine Erklärung warum das "Mist" ist würde weiterhelfen :-)

Weil der Controller in der Zeit nichts anderes machen kann.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun, sowas ist keine Entprellung. zumal 100µs doch sehr kurz ist.

Mache das am Besten in einem Timerinterrupt nach folgendem Ablauf:

(pseudocode)

Timerinterrupt alle zB 1ms.
{
  if (Taste nicht gedrückt)
  {
    Zähler = 0;
  }
  else
  {
    Zähler = Zähler + 1;
  }

  if (Zähler > 100)
 {
    Taste_gedrückt = 1;
    Zähler = Zahler - 30;
 }
}

--------------
main
{
..
 if ( Taste_gedrückt = 1 )
 {
    Taste_gedrückt = 0;
    .. mach was..
 }
..
}

Die Taste muss 100ms gedrückt sein, dann wird das mit dem Flag 
"Taste_gedrückt" gespeichert. Wird die Taste weeiterhin gedrückt 
gehalten, dann wird das alle 30ms wieder erkannt (repeat-funktion)
Das hauptprogramm muss natürlich schneller als diese 100ms sein, und 
kann dann drauf reagieren...

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja natürlich kann er in der Zeit nichts machen, weil es ja entprellt 
werden muss. Wie soll es sonst gehen?

wenn ich andere Lösung hätte, würde ich eher sagen dass 
"Cpu_Delay100US(10); //1sec warten und noch mal Wert am Port A1 
abfragen" Mist ist. Aber ich kenne keine bessere Lösung, daher bitte ich 
euch um Hilfe

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ja natürlich kann er in der Zeit nichts machen, weil es ja entprellt
>werden muss. Wie soll es sonst gehen?

Siehe Beitrag von Lippy von 16:53.

Das Zauberwort heisst Interrupt

Dafür gibt es auch ein nettes Kapitel im GCC-Tutorial

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Nun, sowas ist keine Entprellung. zumal 100µs doch sehr kurz ist.

>Mache das am Besten in einem Timerinterrupt nach folgendem Ablauf:

und wenn ich den Tastendruck NUR am Ende vom Programm abfrage, damit 
bevor es wieder zum Anfang sprint, ich weiss welcher Modus aktiviert 
werden soll?

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach das ordentlich, sonst wird das nie richtig funktionieren.

Es sei denn, du willst nach der Trial&Error Methode die 
Wollknäulprogrammierung betreiben..

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das Zauberwort heisst Interrupt

>Dafür gibt es auch ein nettes Kapitel im GCC-Tutorial

ein Interrupt kann ich nicht einsetzten, weil ich nicht Mitten im 
Programm in die ISR springe will und den Parameter ändere, was aber im 
Laufe des Programms ständig geändert wird.

D.h. den Tastendruck kann ich nur am Ende vom Programm abfragen, damit 
der richtige Modus eingstellt wird, wenn die Taste gedrückt ist.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ISR springe will und den Parameter ändere

Lies richtig! Im ISR wird auch nur der Tastendruck ausgewertet und 
gemerkt.

Wenn du unsere Tipps nict willst, dann erhöhe einfach das delay auf eine 
Sekunde und fertig.

Das ist zwar gebastel, aber was solls...

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn du den Code anschaust, ist auch eine 1sec delay enthalten. Aber wo 
ich jetzt
>Im ISR wird auch nur der Tastendruck ausgewertet und gemerkt
gelesen habe, ist mir was anderes eingefallen.

wenn Taste gedrückt ist, setzte ich eine globale Variable im ISR auf 
TRUE (oder so ähnlich) :-). Ist doch viel besser oder ?!

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>wenn Taste gedrückt ist, setzte ich eine globale Variable im ISR auf
>TRUE (oder so ähnlich) :-). Ist doch viel besser oder ?!

Wenn meinen Pseudocode gelesen (und verstanden) hättest, hättest du 
erkannt, dass genau das dort gemacht wird!

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
du hast ja ganz recht, meine Gedanken waren wo anders. Erst druch
>Im ISR wird auch nur der Tastendruck ausgewertet und gemerkt
wurde mir alles klar :-)

Dankeschön

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und so sieht mein neues Programm aus:

ich prüfe 2 Taster und nur ein Taster muss gedrückt sein
#pragma interrupt called 

//ISR Timer alle 11 ms

void Timer_Taste_OnInterrupt(void)
{
  static word zaehler_a1=0;
  static word zaehler_a2=0;
  byte a1_taste;
  byte a2_taste;
  
  a1_taste=A1_GetVal();
  a2_taste=A2_GetVal();
  
  if( !a1_taste && a2_taste ) //ist Taster A1 gedrückt und A2 nicht
  {
    zaehler_a1++;
  }
  else if( a1_taste && !a2_taste ) //ist Taster A2 gedrückt und A1 nicht
  {
    zaehler_a2++;
  }
  else // entweder kein Taster gedrückt oder Taster losgelesen
  {
    if(zaehler_a1>70 && zaehler_a1<140) //wenn 1 Sec lang Taste gedrückt, wird zaehler bei 90 liegen
    {
      a1_taste_1sec = TRUE;
      zaehler_a1=0;
    }
    else if(zaehler_a2>70 && zaehler_a2<140)
    {
      a2_taste_1sec = TRUE;
      zaehler_a2=0;
    }
    
    a1_taste_1sec=FALSE;
    a2_taste_1sec=FALSE;
    zaehler_a2=0;
    zaehler_a1=0;
  }
}


Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Cimbom Gs (cimbomgs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  else // entweder kein Taster gedrückt oder Taster losgelesen
  {
    if(zaehler_a1>70 && zaehler_a1<140) //wenn 1 Sec lang Taste gedrückt, wird zaehler bei 90 liegen
    {
      a1_taste_1sec = TRUE; <-------------------------------.
      zaehler_a1=0;                                         .
    }                                                       .
    else if(zaehler_a2>70 && zaehler_a2<140)                .
    {                                                       .
      a2_taste_1sec = TRUE; <-------------------------------.
      zaehler_a2=0;                                         .
    }                                                       .
                                                            .
    a1_taste_1sec=FALSE; <----------------------------------.
    a2_taste_1sec=FALSE; <----------------------------------.
    zaehler_a2=0;                                           das ist Mist
    zaehler_a1=0;                                           
  }

du kannst nicht erst auf TRUE setzen und gleich danach werden sie wieder 
zu FALSE..

wie wäre es mit
    if(zaehler_a1>70 && zaehler_a1<140) //wenn 1 Sec lang Taste gedrückt, wird zaehler bei 90 liegen
    {
      a1_taste_1sec = TRUE;
      zaehler_a1=0;
      break;
    }
    else if(zaehler_a2>70 && zaehler_a2<140)
    {
      a2_taste_1sec = TRUE;
      zaehler_a2=0;
      break;
    }

Gruß
Cimbom

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die Info...

naja BREAK; ist schön und gut  aber ich nehme lieber RETURN;

;-)

mfg
Tasti

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>naja BREAK; ist schön und gut  aber ich nehme lieber RETURN;

Aber dir ist schon klar, dass das überhaupt NICHT im Entferntesten 
dasselbe ist?

Autor: Tasti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja natürlich weiß ich das.

was Cimbom vorgeschlagen hat, ist auch gar nicht möglich.
BREAK ist NUR in einer Schleife möglich und darf nicht in einer 
if-Anweisung benutzt werden (wenn es sich nicht in einer Schleife 
befindet). Daher gehört ein RETURN dort hin, um an das Ende der Funktion 
zu springen

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Tasti:

Bevor Du jetzt wieder schreibst: isch weissssss,

erstmal Tutorial lesen !
Da haben sich nämlich Menschen Gedanken gemacht,
damit man sehr schnell ein ordentliches Programm
für Tastenabfrage bekommt.

http://www.mikrocontroller.net/articles/Entprellung

Siehe ->  Komfortroutine (C für AVR)

Gruß Sven

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.