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


von Tasti (Gast)


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
1
bool A1_value=0;
2
3
A1_value = A1_GetVal(); //Wert am Port A1 abfragen
4
if(A1_value) //wenn die Taste gedrückt ist A1_value->TRUE
5
{
6
  Cpu_Delay100US(1); //wegen Entprellung 100us delay
7
8
  A1_value &= A1_GetVal(); //Wert am Port A1 mit altem Wert UND-Verknüpfen
9
10
  if( A1_value ) // Taste gedrückt ->TRUE, sont FALSE
11
  {
12
    Cpu_Delay100US(10); //1sec warten und noch mal Wert am Port A1 abfragen
13
    A2_value &= A1_GetVal();
14
15
    if(A1_value) //wenn nach 1sec immer noch gedrückt A1_value->TRUE, sonst FALSE
16
    {
17
      modus=Mod_Transmission;
18
    }
19
  }
20
}

von Matthias L. (Gast)


Lesenswert?

>Cpu_Delay100US(1); //wegen Entprellung 100us delay


Sawas ist schonmal Mist.

von Tasti (Gast)


Lesenswert?

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

von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

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

Weil der Controller in der Zeit nichts anderes machen kann.

von Matthias L. (Gast)


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

von Tasti (Gast)


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

von Gast (Gast)


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

von Tasti (Gast)


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?

von Matthias L. (Gast)


Lesenswert?

Mach das ordentlich, sonst wird das nie richtig funktionieren.

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

von Tasti (Gast)


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.

von Matthias L. (Gast)


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

von Tasti (Gast)


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 ?!

von Matthias L. (Gast)


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!

von Tasti (Gast)


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

von Tasti (Gast)


Lesenswert?

und so sieht mein neues Programm aus:

ich prüfe 2 Taster und nur ein Taster muss gedrückt sein
1
#pragma interrupt called 
2
3
//ISR Timer alle 11 ms
4
5
void Timer_Taste_OnInterrupt(void)
6
{
7
  static word zaehler_a1=0;
8
  static word zaehler_a2=0;
9
  byte a1_taste;
10
  byte a2_taste;
11
  
12
  a1_taste=A1_GetVal();
13
  a2_taste=A2_GetVal();
14
  
15
  if( !a1_taste && a2_taste ) //ist Taster A1 gedrückt und A2 nicht
16
  {
17
    zaehler_a1++;
18
  }
19
  else if( a1_taste && !a2_taste ) //ist Taster A2 gedrückt und A1 nicht
20
  {
21
    zaehler_a2++;
22
  }
23
  else // entweder kein Taster gedrückt oder Taster losgelesen
24
  {
25
    if(zaehler_a1>70 && zaehler_a1<140) //wenn 1 Sec lang Taste gedrückt, wird zaehler bei 90 liegen
26
    {
27
      a1_taste_1sec = TRUE;
28
      zaehler_a1=0;
29
    }
30
    else if(zaehler_a2>70 && zaehler_a2<140)
31
    {
32
      a2_taste_1sec = TRUE;
33
      zaehler_a2=0;
34
    }
35
    
36
    a1_taste_1sec=FALSE;
37
    a2_taste_1sec=FALSE;
38
    zaehler_a2=0;
39
    zaehler_a1=0;
40
  }
41
}

von Peter D. (peda)


Lesenswert?


von Cimbom G. (cimbomgs)


Lesenswert?

1
  else // entweder kein Taster gedrückt oder Taster losgelesen
2
  {
3
    if(zaehler_a1>70 && zaehler_a1<140) //wenn 1 Sec lang Taste gedrückt, wird zaehler bei 90 liegen
4
    {
5
      a1_taste_1sec = TRUE; <-------------------------------.
6
      zaehler_a1=0;                                         .
7
    }                                                       .
8
    else if(zaehler_a2>70 && zaehler_a2<140)                .
9
    {                                                       .
10
      a2_taste_1sec = TRUE; <-------------------------------.
11
      zaehler_a2=0;                                         .
12
    }                                                       .
13
                                                            .
14
    a1_taste_1sec=FALSE; <----------------------------------.
15
    a2_taste_1sec=FALSE; <----------------------------------.
16
    zaehler_a2=0;                                           das ist Mist
17
    zaehler_a1=0;                                           
18
  }

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

wie wäre es mit
1
    if(zaehler_a1>70 && zaehler_a1<140) //wenn 1 Sec lang Taste gedrückt, wird zaehler bei 90 liegen
2
    {
3
      a1_taste_1sec = TRUE;
4
      zaehler_a1=0;
5
      break;
6
    }
7
    else if(zaehler_a2>70 && zaehler_a2<140)
8
    {
9
      a2_taste_1sec = TRUE;
10
      zaehler_a2=0;
11
      break;
12
    }

Gruß
Cimbom

von Tasti (Gast)


Lesenswert?

danke für die Info...

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

;-)

mfg
Tasti

von Matthias L. (Gast)


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?

von Tasti (Gast)


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

von Sven (Gast)


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

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.