Forum: Mikrocontroller und Digitale Elektronik Tastendrücke einlesen


von Birgit Egger (Gast)


Lesenswert?

Hallo,

ich möchte mit einer Taste eine LED (beim ersten mal drücken) 
einschalten und dann (beim zweiten mal drücken) wieder ausschalten.
Mit dem unteren Code funktioniert es, dass ich die LED mit dem 
Tastendruck einschalte aber ich kann die LED (mit dem selben) Taster 
nicht wieder ausschalten.
Weiß jemand wie ich das machen kann?
Vielen Dank.

lg
Birgit Egger
1
switch(P2 & 0x400) {
2
    case 0x400: P2_9 = (P2_9 | 0x00);
3
          break; 
4
    case 0x0: P2_9 = (P2_9 | 0x01);
5
          break;
6
    default:  i = 0;
7
  }    
8
// P2_9  ... LED output
9
// P2_10 ... Taster input  -> bei /Key angeschlossen -> wenn ich den Taster wieder auslasse dann wird die LED erst eingeschalten.

von Eumel (Gast)


Lesenswert?

Taster müssen entprellt werden.

von Karl H. (kbuchegg)


Lesenswert?

Da sind gleich ein paar Probleme

Zum einen

  P2_9 = (P2_9 | 0x00);


du kannst mit 0 verodern soviel du willst. Ein einmal auf 1 gesetztes 
Bit lässt sich davon nicht beeindrucken. Denn ( 1 ODER 0 ) ergiebt 
wieder 1. D.h. das bereits auf 1 gesetzte Bit sorgt dafür, dass das 
Ergebnis auf jeden Fall wieder 1 ist.

Bitmanipulation

von HildeK (Gast)


Lesenswert?

Birgit Egger schrieb:
> P2_9 = (P2_9 | 0x00);

Wenn ich das richtig sehe, dann ändert sich durch diesen Befehl P2_9 
niemals. Eine Oder-Verknüpfung mit 0 kann man weglassen.

Du willst vermutlich hier Bit 0 löschen und das ginge dann so
 P2_9 = (P2_9 & 0xFE);

Ich bin aber in keinster Weise Programmier-Profi!

von Karl H. (kbuchegg)


Lesenswert?

Zum anderen.
Dein Code versucht die LED einzuschalten, SOLANGE die Taste gedrückt 
IST.
Das ist aber etwas anderes als: Erkenne den Übergang von gedrückt zu 
nicht gedrückt und wenn das festgestellt wird, dann schalte die Led um.

Für den letzten Fall brauchst du also eine Erkennung der Veränderung des 
Zustands! Wenn du ins Badezimmer schaust und siehst, dass dort Licht 
brennt, kannst du nicht sagen, ob das jetzt gerade eingeschaltet wurde 
oder nicht. Das kannst du erst dann sagen, wenn du dir gemerkt hast, 
dass 10 Minuten vorher das Licht noch nicht gebrannt hat.

Du musst also in deiner Hauptschleife dir den Zustand merken und dann im 
nächsten Durchgang durch die Hauptschleife einen Vergleich durchführen. 
Hat sich der Zustand verändert, dann ist etwas passiert. Die Taste ist 
entweder gedrückt oder losgelassen worden. Hat sich nichts verändert, 
dann ist die Taste immer noch so wie vorher entweder gedrückt oder nicht 
gedrückt. Das interessiert dich aber nicht, denn du willst ja nur dann, 
wenn die Taste niedergedrückt wird etwas tun. zb die Led ein oder 
ausschalten.


Und dann gibt es da noch ein Problem. Tasten prellen
Entprellung

Die Problemstellung "mache etwas bei einem Tastendruck" ist 
komplizierter als es auf den ersten Blick aussieht. "Mache etwas, 
solange eine Taste gedrückt ist", ist meist deutlich einfacher.

von Werner (Gast)


Lesenswert?

HildeK schrieb:
> Du willst vermutlich hier Bit 0 löschen und das ginge dann so
>  P2_9 = (P2_9 & 0xFE);

... und damit das irgenwie lesbar ist, verwendet man zum Löschen
1
P2_9 = P2_9 & ~0x01;
oder kurz
1
P2_9 &= ~0x01;
oder besser natürlich direkt mit der Bitnummer
1
P2_9 &= ~(1 << BitNr);

von Markus F. (affe55)


Lesenswert?

Einfacher ist sowas über eine Flankenerkennung zu realisieren, da hätte 
man zum einen das Entprellen berücksichtigt und zum anderen die Aufgabe 
mit wenig Code gelöst. Siehe auch 
Beitrag "Flankenerkennung ohne Interrupts":
1
unsigned char neuerZustand=0;
2
unsigned char alterZustand=0;
3
4
neuerZustand=!P2_10;
5
if(!alterZustand&&neuerZustand)  {
6
    // Flanke erkannt, nun LED an-/ausmachen
7
    P2_9=!P2_9;
8
}
9
alterZustand=neuerZustand;

Spiegelt ausserdem das wieder, was Karl Heinz Buchegger schrieb im 
Beitrag #2727705:
> [...]
> Du musst also in deiner Hauptschleife dir den Zustand merken und dann im
> nächsten Durchgang durch die Hauptschleife einen Vergleich durchführen.
> Hat sich der Zustand verändert, dann ist etwas passiert. Die Taste ist
> entweder gedrückt oder losgelassen worden. Hat sich nichts verändert,
> dann ist die Taste immer noch so wie vorher entweder gedrückt oder nicht
> gedrückt. Das interessiert dich aber nicht, denn du willst ja nur dann,
> wenn die Taste niedergedrückt wird etwas tun. zb die Led ein oder
> ausschalten.
> [...]

meinte. Gruß

von HildeK (Gast)


Lesenswert?

Werner schrieb:
> ... und damit das irgenwie lesbar ist, verwendet man zum Löschen

Klar, ich wollte nur bei ihrer Nomenklatur bleiben. Auf das Thema 
Bitmanipulation wurde ja auch von anderer Stelle verwiesen.

von Peter D. (peda)


Lesenswert?

Geht natürlich auch für 8051.
Den Timerinterrupt muß man noch anpassen.


http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29

Peter

von Birgit Egger (Gast)


Lesenswert?

Markus Fab. schrieb:

> unsigned char neuerZustand=0;
> unsigned char alterZustand=0;
>
> neuerZustand=!P2_10;
> if(!alterZustand&&neuerZustand)  {
>     // Flanke erkannt, nun LED an-/ausmachen
>     P2_9=!P2_9;
> }
> alterZustand=neuerZustand;


Klappt hervorragend! Besten Dank,

Das einzige was ich jetzt komisch fand ist, dass wenn ich das untere 
umdrehe (also zuerst die Direction der Ports definiere und dann erst den 
alten und den neuen Zustand) dann bekomm ich einen haufen errors.
Warum kann ich das nicht umdrehen?
Besten Dank!!

1
unsigned char neuerZustand = 0;
2
  unsigned char alterZustand = 0;
3
4
  DP2_9 = 1;                           /* init direction to output            */
5
  DP2_10 = 0;

von Markus F. (affe55)


Lesenswert?

Für eine Antwort braucht man schon den beteiligten Quellcode und die 
genaue Fehlerbeschreibung.

Gruß

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.