Hallo, ich möchte gerne eine gemeinsame Tastenabfrage in der folgenden Schleife einbauen.... if (!(PORTD.IN & 0b00000001) && (...) && (...)) { Tu was.... } ...bis jetzt wird nur der Tastenzustand am PIN0 abgefragt mit PORTD.IN & 0b00000001 Was muss ich ändern wenn ich irgendeine Taste am Port abfragen möchte? Es sind 8 Tasten an einem Port angeschlossen und sowie eine aber auch nur eine gedrückt wird soll ein Befehl ausgeführt werden. Sämtliche Versuche mit dem Befehl PORT.IN scheiterten bisher. Gruß Daniel
Daniel schrieb: > if (!(PORTD.IN & 0b00000001) && (...) && (...)) ... > Was muss ich ändern wenn ich irgendeine Taste am Port abfragen möchte? Wenn do "oder" meinst, mußt du auch "||" schreiben. Erste Frage wäre, wie deine Tasten angeschlossen sind, d.g. ob sie beim Drücken L oder H liefern. Dann kannst du mit "&" eine Maske auf die erforderlichen Tasten legen und prüfst ober das Ergebnis bzw. das Inverse == 0 ist.
Werner schrieb: > enn do "oder" meinst, mußt du auch "||" schreiben. > > Erste Frage wäre, wie deine Tasten angeschlossen sind, d.g. ob sie beim > Drücken L oder H liefern. Dann kannst du mit "&" eine Maske auf die > erforderlichen Tasten legen und prüfst ober das Ergebnis bzw. das > Inverse == 0 ist. Also der Port D wurde als Eingang festgelegt Mit der Maskenfunktion PORTCFG.MPCMASK |=(1<<PIN0_bp) | (1<<PIN1_bp) | (1<<PIN2_bp) | (1<<PIN3_bp) | (1<<PIN4_bp) | (1<<PIN5_bp) | (1<<PIN6_bp) | (1<<PIN7_bp); wurden die PINS am Port D maskiert anschließend wurden mit der Gruppenfunktion PORTD.PIN0CTRL = PORT_OPC_PULLUP_gc; die Pullups aktiviert. Mit anderen Worten wenn eine Taste gedrückt wird, liegt am Porteingang eine 0 an. Daher die verneinte Abfrage !(PORTD.IN & 0b00000001) if (!(PORTD.IN & 0b00000001) && (Bedingung1==TRUE) && (Bedingung2==TRUE)) { Tu was.... } Die Verknüpfung && hat bisher noch nichts mit den anderen Tasten zu tun und soll nur prüfen ob die Bedingung1 und Bedingung2 aus dem übrigen Code auch TRUE ist. Wie genau muss jetzt die Codezeile aussehen wenn ich alle 8 Tasten auf Low-Zustand abfragen will? Folgendes funktioniert leider nicht : if (!(PORTD.IN & ((0b00000001)||(0b00000010))) && (Bedingung1==TRUE) && (Bedingung2==TRUE)) { Tu was.... }
Wie wäre es mit switch..case?
1 | void button_interpreter(void) { |
2 | switch(PORTD.IN) { |
3 | case 0xFE : // Taste an Bit0 gedrückt |
4 | // Tu was
|
5 | break; |
6 | case 0xFD : // Taste auf Bit1 |
7 | break; |
8 | // usw.
|
9 | case default : // alle nicht behandelten Tastendruckkombinationen |
10 | }
|
11 | }
|
Verstehe ich Dich richtig? Am Port liegt 0b11111111 an, wenn keine Taste gedrückt wird und etwas anderes, wenn eine gedrückt wird? Wenn das stimmt, dann gibt diese Umformulierung ja schon die Antwort. Einfach auf PORTD.IN != 0b11111111 testen, um zu sehen ob irgendeine Taste gedrückt ist.
Ups, habe im case default das break vergessen...
> und sowie eine aber auch nur eine gedrückt wird
Ach, Du willst die Aktion nicht machen, wenn zwei Tasten gleichzeitig
gedrückt werden?
Na dann musst Du die Maskierungen wie in (PORTD.IN & 0b00000001)
weglassen, weil eine Maskierung gerade macht, dass die anderen Bits egal
sind. Teste also einfach auf alle 8 Zustände, die Du haben willst
(PORT.IN == 0b11111110) || (PORT.IN == 0b11111101) || ...
Matthias Sch. schrieb: > Ups, habe im case default das break vergessen... Wieso? Es schadet zwar nicht, das dort zu haben, aber notwendig ist es nicht.
M. H. schrieb: >> Ups, habe im case default das break vergessen... > > Wieso? Es schadet zwar nicht, das dort zu haben, aber notwendig ist es > nicht. Ich habs halt gerne strukturiert :-). Aber klar, ist überflüssig. Compiler würde es eh wegrationalisieren.
M. H. schrieb: > Ach, Du willst die Aktion nicht machen, wenn zwei Tasten gleichzeitig > gedrückt werden? > > Na dann musst Du die Maskierungen wie in (PORTD.IN & 0b00000001) > weglassen, weil eine Maskierung gerade macht, dass die anderen Bits egal > sind. Teste also einfach auf alle 8 Zustände, die Du haben willst > (PORT.IN == 0b11111110) || (PORT.IN == 0b11111101) || ... Also die Aktion soll gemacht werden wenn irgendeine Taste von den 8 Tasten gedrückt wird. Vorzugsweise soll nichts passieren wenn mehrere Tasten gleichzeitig gedrückt werden. Muss ich jedesmal PORTd.IN schreiben oder kann ich das noch verkürzen? Dann liegt mein Fehler also bei der and & Operation richtig? Sprich aus dem & muss ein == werden...
Daniel schrieb: > Muss ich jedesmal PORTd.IN schreiben oder kann ich das noch verkürzen? Schreib ich eigentlich chinesisch? In meinem Codefragment wird genau einmal PORTD.IN abgefragt. Wenns dir nur darum geht, irgendeine einzelne taste abzufragen:
1 | void button_interpreter(void) { |
2 | switch(PORTD.IN) { |
3 | case 0xFE : // Taste an Bit0 gedrückt |
4 | case 0xFD : // Taste auf Bit1 |
5 | case 0xFB : |
6 | case 0xF7 : |
7 | case 0xEF : |
8 | case 0xDF : |
9 | case 0xBF : |
10 | case 0x7F : // hier tu ich was |
11 | break; |
12 | // usw.
|
13 | case default : // alle nicht behandelten Tastendruckkombinationen |
14 | }
|
15 | }
|
Matthias Sch. schrieb: > Schreib ich eigentlich chinesisch? In meinem Codefragment wird genau > einmal PORTD.IN abgefragt. Chinesisch nicht aber du schreibst eine CASE.. und meine Frage war ob man in der if() nur einmal PORTD.IN schreiben kann und dahinter eine || oder Abfrage machen kann...
Daniel schrieb: > Vorzugsweise soll nichts passieren wenn mehrere > Tasten gleichzeitig gedrückt werden. Darum brauchst Du Dir keine Sorgen zu machen. Kein Mensch kann 2 Tasten innerhalb weniger ns zusammen drücken. Es wird immer eine Taste zuerst gedrückt werden. Peter
Daniel schrieb: > meine Frage war ob man in der if() nur einmal PORTD.IN schreiben > kann und dahinter eine || oder Abfrage machen kann... Nein, das geht nicht. Für den Fall, dass das Auslesen besonders lange dauert oder es problematisch wäre wenn sich der Port während der Abarbeitung des if-Statements ändert (beides sehe ich hier nicht), kann man die Portabfrage natürlich auch in eine Variable schreiben und die dann testen. Aber auch dann muss man diese mehrmals ins if() schreiben. Dieses Zwischenspeichern gänge natürlich auch mit einem Funktionsaufruf if(nur_eine_Taste_gedrückt(PORTD.IN)). Ich bin zwar kein Freund von case-Anweisungen, aber in diesem speziellen Fall finde ich sie die bessere Lösung, weil besser lesbar.
M. H. schrieb: > Ich bin zwar kein Freund von > case-Anweisungen Sag mal warum, würde mich interessieren. Hab hier gerade einen kleinen Frequenzumrichter (700Watt) mit Mega88, LCD und drei Tasten gebaut, und die Tastenabfrage mit switch und case ist prima, da ich eben auch zwei gleichzeitig gedrückte Tasten auswerten und für Sonderfunktionen benutzen kann. Bei den verschachtelten if's und else's verliert man m.E. viel schneller den Überblick und verbaut sich die Erweiterbarkeit. Ich könnte mir nämlich vorstellen, das der TO irgenwann doch mal zwischen den Buttons unterscheiden will und dann die if's wieder auseinanderdröseln muss. Bei meinem Konstrukt hingegen schreibste im case dann deine gewünschte Funktion und fertig.
Matthias Sch. schrieb: > die Tastenabfrage mit switch und case ist prima Ist sie nicht. Man muß erst alle anderen Tasten ausmaskieren. Und es kommen ja noch weitere Probleme hinzu, wie Entprellung und Flankenerkennung. Man schreibt sich daher am besten eine Funktion dafür:
1 | uint8_t get_key_common( uint8_t key_mask ) |
2 | {
|
3 | return get_key_press((key_press & key_mask) == key_mask ? key_mask : 0); |
4 | }
|
Beitrag "Universelle Tastenabfrage mit 2 Tastenerkennung" Peter
Matthias Sch. schrieb: > Sag mal warum, würde mich interessieren. Wie gesagt: In diesem Fall finde ich Case sehr elegant und würde es auch so nutzen. Aber so grundsätzlich nutze ich Case nicht gern. Eher aus dem Bauch heraus als mit harten Fakten belegbar. Liegt wohl eher daran, dass ich nicht nur in C programmiere, sondern auch in anderen Sprachen (in denen es ein Case nicht gibt). Außerdem ist Case nicht (nachträglich) um zusätzliche Bedingungen (auf andere Variablen) erweiterbar und nicht so mächtig wie ifs. (Du schreibst oben etwas von verschachtelten if-else. Solche Dinge sind inhaltlich doch überhaupt nicht mit Cases abzubilden?) Zu guter letzt: Die Case-Anwendung ist syntaktisch ein Fremdkörper in C. Überall gibt es Code-Blöcke, die mit geschweiften Klammern zusammengehalten werden. Nur an einer Stelle muss man die gleiche Sache anders notieren: bei Cases. Peter Dannegger schrieb: > Matthias Sch. schrieb: >> die Tastenabfrage mit switch und case ist prima > > Ist sie nicht. > Man muß erst alle anderen Tasten ausmaskieren. Sorry, aber auch Leute, die exzellente Algorithmen für die Tastenerkennung geschrieben haben, sollten einen Thread lesen und die Anforderungen verstehen bevor sie antworten. Mit der Frage nach Flankenerkennung und Entprellung hast Du allerdings recht. Was sagt Daniel (OP) dazu? Hast Du Dir darüber schon Gedanken gemacht? Dein jetziger Ansatz wird den entsprechenden Code hunderte oder tausende Male durchlaufen solange eine Taste auch nur kurz gedrückt wird. Wäre das okay?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.