Forum: Mikrocontroller und Digitale Elektronik Tastendruck detektieren


von Gecko (Gast)


Lesenswert?

Guten Abend

Ich habe ein kleines Projekt am laufen und steh seit längerem auf der 
Leitung.
Und zwar habe ich an meinem uC zwei Taster angeschlossen. Ich will nun 
detektieren, ob einer der beiden oder beide zusammen gedrückt werden.

Dafür habe ich erst mal einen Flankendetektor geschrieben. Nur kann man 
so nur einen Tastendruck detektieren.
Kann mir jemand sagen, wie ich das "eleganter" realisieren kann?

Hier mein Code:
1
unsigned char button1_pressed = 1;
2
unsigned char button2_pressed = 1;
3
4
unsigned char button1(void)        
5
{
6
  unsigned char return_value = 0;            
7
  
8
  if(GPIO_PinInGet(Button1_PORT,Button1_BIT) == 0) 
9
  {      
10
    if(button1_pressed == 0)                        
11
    {
12
      button1_pressed = 1;                          
13
      return_value = 1;
14
    }  
15
  }
16
  else                                                         
17
  {
18
    button1_pressed = 0;                          
19
  }
20
     
21
  return return_value;                 
22
}
23
24
unsigned char button2(void)        
25
{
26
  unsigned char return_value = 0;            
27
  
28
  if(GPIO_PinInGet(Button2_PORT,Button2_BIT) == 0) 
29
  {      
30
    if(button2_pressed == 0)                        
31
    {
32
      button2_pressed = 1;                          
33
      return_value = 1;
34
    }  
35
  }
36
  else                                                         
37
  {
38
    button2_pressed = 0;                          
39
  }
40
     
41
  return return_value;                 
42
}

Vielen Dank
MFG

von Karl H. (kbuchegg)


Lesenswert?

Gecko schrieb:

> Dafür habe ich erst mal einen Flankendetektor geschrieben. Nur kann man
> so nur einen Tastendruck detektieren.

Das Problem ist reichlich knifflig. Denn als Mensch wirst du es niemals 
schaffen, die beiden Tasten 100% exakt gleichzeitig zu drücken.

Was du aber tun kannst:
Wenn du einen Tastendruck feststellst, kannst du kurz einen Blick auf 
den anderen Portpin werfen, ob dort die Taste gerade gedrückt ist. Wenn 
ja, dann sind somit beide Tasten gedrückt.

von Lutz H. (luhe)


Lesenswert?

Gecko schrieb:
> unsigned char button1_pressed = 1;

Warum nicht
bool button1_pressed = false;

von Gecko (Gast)


Lesenswert?

Ok jetzt habe ich es geschaft. Scheint mir aber ziemlich aufwendig 3 
Unterprogramme zu schreiben, um 3 Fälle zu überprüfen. Mir fällt 
allerdings keine einfachere Alternative ein. Tipp? :)
1
unsigned char button12(void)        
2
{
3
  unsigned char return_value = 0;            
4
  
5
  if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 0)&&(GPIO_PinInGet(Button2_PORT,Button2_BIT) == 0))
6
  {      
7
    if(button12_pressed == 0)                        
8
    {
9
      button12_pressed = 1;                          
10
      return_value = 1;
11
    }  
12
  }
13
  else                                                         
14
  {
15
    button12_pressed = 0;                          
16
  }
17
     
18
  return return_value;                 
19
}
20
21
unsigned char button1(void)        
22
{
23
  unsigned char return_value = 0;            
24
  
25
  if(GPIO_PinInGet(Button1_PORT,Button1_BIT) == 0) 
26
  {      
27
    if(button1_pressed == 0)                        
28
    {
29
      button1_pressed = 1;                          
30
      return_value = 1;
31
    }  
32
  }
33
  else                                                         
34
  {
35
    button1_pressed = 0;                          
36
  }
37
     
38
  return return_value;                 
39
}
40
41
unsigned char button2(void)        
42
{
43
  unsigned char return_value = 0;            
44
  
45
  if(GPIO_PinInGet(Button2_PORT,Button2_BIT) == 0) 
46
  {      
47
    if(button2_pressed == 0)                        
48
    {
49
      button2_pressed = 1;                          
50
      return_value = 1;
51
    }  
52
  }
53
  else                                                         
54
  {
55
    button2_pressed = 0;                          
56
  }
57
     
58
  return return_value;                 
59
}

von Karl H. (kbuchegg)


Lesenswert?

Hast du das schon in einem Testprogramm verifiziert?

> Scheint mir aber ziemlich aufwendig 3 Unterprogramme zu schreiben
Na, ja.
Wenn du dir die Funktionen ansiehst, dann ist das immer die im Prinzip 
gleiche Funktion, nur die Variablen sind andere. Genau dafür gibt es 
Funktionsargumente, damit man einer Funktion Werte übergeben kann, mit 
denen sie dann operiert.

Dein C-Buch weiß zu dem Thema näheres.

von Lutz H. (luhe)


Lesenswert?

Was soll Funktion zurückgeben: wenn kein Taster gedrückt 0
sonst 1?

 gibt es 4 Zustände:  kein Taster, Taster 1, Taster 2 , Taster 1 und 2
gedrückt.

von F. F. (foldi)


Lesenswert?

lutz h. schrieb:
> Was soll Funktion zurückgeben: wenn kein Taster gedrückt 0
> sonst 1?
>
>  gibt es 4 Zustände:  kein Taster, Taster 1, Taster 2 , Taster 1 und 2
> gedrückt.

Ist das nicht schon die Antwort auf deine Frage?

von Lutz H. (luhe)


Lesenswert?

unsigned char button12(void)
{
  unsigned char return_value = 0;

//  if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 0)&& 
//(GPIO_PinInGet(Button2_PORT,Button2_BIT) == 0)) {return_value = 0;}
  if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 1)&& 
(GPIO_PinInGet(Button2_PORT,Button2_BIT) == 0)) {return_value = 1;}
  if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 0)&& 
(GPIO_PinInGet(Button2_PORT,Button2_BIT) == 1)) {return_value = 2;}
  if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 1)&& 
(GPIO_PinInGet(Button2_PORT,Button2_BIT) == 1)) {return_value = 3;}
  return return_value;
}

von Max H. (hartl192)


Lesenswert?

So würde eine Flankenerkennung (fallen) für einen Gnazen Port gehen. Ist 
zwar für PIC, dürfte sich aber leicht auf einen AVR übertragen lassen.
1
PORTBnew=PORTB;
2
flankeB=~PORTBnew;
3
flankeB=flankeB&PORTBold;
4
PORTBold=PORTBnew;

von F. F. (foldi)


Lesenswert?

M. H. schrieb:
> So würde eine Flankenerkennung (fallen) für einen Gnazen Port gehen. Ist
> zwar für PIC, dürfte sich aber leicht auf einen AVR übertragen lassen.
>
>
1
> PORTBnew=PORTB;
2
> flankeB=~PORTBnew;
3
> flankeB=flankeB&PORTBold;
4
> PORTBold=PORTBnew;
5
>

Sicher schön kurz, aber wenn er nur die zwei Taster auswerten will und 
muss, den Rest des Ports noch braucht, dann muss er eh noch was 
anhängen.

Der letze Code war doch schon recht kurz.

von F. F. (foldi)


Lesenswert?

lutz h. schrieb:
> unsigned char button12(void)
> {
>   unsigned char return_value = 0;
>
> //  if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 0)&&
> //(GPIO_PinInGet(Button2_PORT,Button2_BIT) == 0)) {return_value = 0;}
>   if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 1)&&
> (GPIO_PinInGet(Button2_PORT,Button2_BIT) == 0)) {return_value = 1;}
>   if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 0)&&
> (GPIO_PinInGet(Button2_PORT,Button2_BIT) == 1)) {return_value = 2;}
>   if((GPIO_PinInGet(Button1_PORT,Button1_BIT) == 1)&&
> (GPIO_PinInGet(Button2_PORT,Button2_BIT) == 1)) {return_value = 3;}
>   return return_value;
> }

Jetzt noch ein kurzes delay dazwischen und du kannst wirklich erkennen, 
ob da jemand beide Tasten gedrückt hat.

von Karl H. (kbuchegg)


Lesenswert?

F. Fo schrieb:

> Sicher schön kurz, aber wenn er nur die zwei Taster auswerten will

schlimmer.

Er hat 2 physikalische Taster, will aber 3 logische Taster.

von Max H. (hartl192)


Lesenswert?

Die Pins werden nur eingelesen und nicht beschreiben. Wenn man wie ich 
nur 3 Tasten auswerten will werden die andern Bits der Variable flanke 
einfach ignoriert.
1
if(flankeB&(1<<1))      
2
{
3
4
}  
5
if(flankeB&(1<<2))      
6
{
7
8
}    
9
if(flankeB&(1<<4))      
10
{
11
12
}

von Karl H. (kbuchegg)


Lesenswert?

M. H. schrieb:
> Die Pins werden nur eingelesen und nicht beschreiben. Wenn man wie ich
> nur 3 Tasten auswerten will

Nochmal.
Er hat keine 3 Taster.
Er hat nur 2 real vorhandene.

Er will aber im Programm 3 Tastenzustände unterscheiden:
A gedrückt
B gedrückt
A + B gedrückt.

von Max H. (hartl192)


Lesenswert?

Karl Heinz schrieb:
> M. H. schrieb:
>> Die Pins werden nur eingelesen und nicht beschreiben. Wenn man wie ich
>> nur 3 Tasten auswerten will
>
> Nochmal.
> Er hat keine 3 Taster.

Ich habe die 3 Tasten nur als Beispiel genommen weil ich das in meinem 
Code so hatte.
Und um das mit den 2 gleichzeitigen Tasten zu erkennen muss man ein 
längeres delay in die schleife einbauen und das 3. if so machen:

if(flankeB&(1<<1)&&flankeB&(1<<2))

Oder man merkt sich die Flanke für ein paar Schleifendurchläufe.

von F. F. (foldi)


Lesenswert?

Karl Heinz schrieb:
> M. H. schrieb:
>> Die Pins werden nur eingelesen und nicht beschreiben. Wenn man wie ich
>> nur 3 Tasten auswerten will
>
> Nochmal.
> Er hat keine 3 Taster.
> Er hat nur 2 real vorhandene.
>
> Er will aber im Programm 3 Tastenzustände unterscheiden:
> A gedrückt
> B gedrückt
> A + B gedrückt.

Das geht nur, wie du schon angedeutet hast, wenn er die "menschliche 
Komponente" mit einbezieht. Also muss er den Zeitrahmen vorgeben und 
auch in der Abfrage erfassen, dazu noch ein Sicherheitsmechanismus, der 
alle Abweichungen als ungültig erklärt.
Da ist die länge des Codes eher Nebensache.

von Max H. (hartl192)


Lesenswert?

1
while(1)
2
{
3
  PORTBnew=PORTB;
4
  flankeB=~PORTBnew;
5
  flankeB=flankeB&PORTBold;
6
  PORTBold=PORTBnew;
7
8
  if(flankeB&(1<<1))      
9
  {
10
     zaeler1=20;
11
  }  
12
  if(flankeB&(1<<2))      
13
  {
14
     zaeler2=20;
15
  }
16
  if(zaeler1&&zaeler2)
17
  {
18
     //beide gedrückt
19
  }
20
  if(zaeler1>0)
21
     zaeler1--;
22
  if(zaeler2>0)
23
     zaeler2--;
24
  
25
  Delay_ms(10);  
26
}
Das wäre eine mögliche Lösung. Wenn man die schleife z.B. alle 10ms 
ausführt dann kann man erkennen ob innerhalb von 200ms beide Tasten 
gedrückt wurden. Ich persönlich würde den Code nicht als schleife 
sondern in einem Timer Interrupt ausführen.
Die variable zaeler merkt sich 200ms lang ob eine Taste gedrückt wurde. 
Wurden beide Tasten einmal in den letzten 200ms gedrückt ist die 
Bedingung "zaeler1&&zaeler2" wahr.

: Bearbeitet durch User
von Martin V. (oldmax)


Angehängte Dateien:

Lesenswert?

Hi
Immer, wenn's etwas kompliziert erscheint, hilft eine Skizze. In diesem 
Fall ein Signalbild. Ich denke, das sagt mehr als tausend Worte.
Gruß oldmax

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?


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.