1 sec Tastendruck - Code OK?

Gast #788276
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
}
Gast #788300
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...
Gast #788305
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
Gast #788307
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
Gast #788312
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?
Gast #788317
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.
Gast #788332
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...
Gast #788339
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 ?!
Gast #788350
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!
Gast #788464
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
}
#788640
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
Gast #789029
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren