Tastendruck detektieren

Gast #3411626
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
#3411630
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.
Gast #3411672
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
}
#3411678
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.
#3411708
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;
}
#3411723
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.
#3411728
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.
#3411742
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.
#3411747
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.
#3411757
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.

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