NAbend,
ich habe einen Taster an einem externen Interrupt Pin des uc (Interrupt
0) angebunden. Den Pin habe ich als digitalen Eingang deklariert.
Ich habe den Interrupt 0 aktiviert und er soll auf der steigenden Flanke
Triggern.
Der Interrupt wird jetzt (vermutlich durch das Prellen) laufend
aufgerufen, ganz egal ob der Button auf High oder Low gelegt wird.
Ist es durch das Prellen überhaupt eine sinnvolle Lösung einen Taster
über einen externen Interrupt abzufragen oder mache ich etwas
grundsätzliches falsch?
Frank Sinatra schrieb:> Der Interrupt wird jetzt (vermutlich durch das Prellen) laufend> aufgerufen, ganz egal ob der Button auf High oder Low gelegt wird.
Das ist völlig normal.
> Ist es durch das Prellen überhaupt eine sinnvolle Lösung einen Taster> über einen externen Interrupt abzufragen
Das kommt allein auf die Anwendung an.
Wenn der Taster einen einmaligen Vorgang startet, dann geht's. Also
sowas wie "Not-AUS" etwa.
Wenn der Taster einen langen (deutlich länger als die Prellzeit)
dauernden Vorgang startet, dann geht's auch. Die Entprellung kann hier
durch die Laufzeit des Vorgangs selber erfolgen.
Wenn der Taster eine Zustandsänderung bewirkt und der Zielzustand nur
durch die Betätigung eines anderen Tasters wieder verlassen werden kann,
dann geht's auch. Hier erfolgt die Entprellung nach dem RS-Prinzip.
In allen anderen Fällen geht's nicht oder zumindest nicht ohne
komplexere Klimmzüge, die sinnlos sind, weil sie gegenüber den üblichen
Designmustern zur Entprellung keinerlei Vorteile bringen.
Da ist er ja wieder. Der wöchentliche Taster-Interrupt-Thread.
Wer Taster per Interrupt abfragt, statt die PeDa-Entprellung mit
timergesteuertem Polling zu benutzen, gilt hier allgemein als halbgarer
Vollpfosten.
Frank Sinatra schrieb:> Ist es durch das Prellen überhaupt eine sinnvolle Lösung einen Taster> über einen externen Interrupt abzufragen oder mache ich etwas> grundsätzliches falsch?
Nein, das ist wirklich keine gute Idee.
Da musst du jetzt durch:
http://www.mikrocontroller.net/articles/Entprellung
Aber erstens ist das nicht so schlimm, wie es auf den ersten Blick
aussieht. Zweitens hast du damit ein für alle Mal alle Probleme, die
jetzt oder irgendwann mit Tastern, Relais oder anderem Klapperkram
auftreten können, gelöst.
mfg.
Hallo Herr Eckmann,
vielen Dank für den Link.
Habe die "PeDa" Enprellung implementiert. Die gute Nachricht: Es
funktioniert. Die schlechte Nachricht: So ganz blicke ich den Code und
die Anwendung noch nicht. Werde da wohl mal Zeile für Zeile durchgehen
müßen.
Eine Frage habe ich aber noch:
get_key_long reagiert bei mir genauso schnell wie get_key_short obwohl
ich den Taster in der KEY Maske eingetragen habe. Was muss ich noch
beachten.
Kann mir Jemand kurz in eigenen Worte erklären was die get_key_rpt
Funktion macht? Klar ist es ausführlich dokumentiert, mir aber trotzdem
nicht ganz ersichtlich.
Ich bedanke mich
Frank Sinatra schrieb:> get_key_long reagiert bei mir genauso schnell wie get_key_short
Zeig mal einen Testcode.
Quellcode läßt sich nur äußerst schlecht in Prosa darstellen.
Thomas Eckmann schrieb:> Da ist er ja wieder. Der wöchentliche Taster-Interrupt-Thread.
Starte eine Petition, daß ein absolutes Verbot dieses Vorgehens
beschlossen und in Gesetzesform gegossen wird.
Deine Meinung verprellt die Leser...
;-)
halbgarer Vollpfosten schrieb:> Thomas Eckmann schrieb:>> Wer Taster per Interrupt abfragt, statt die PeDa-Entprellung mit>> timergesteuertem Polling zu benutzen, gilt hier allgemein als halbgarer>> Vollpfosten.>> Dann wollen wir doch nicht verschweigen, was Du meinst:> Beitrag "EIN-AUS mit Taster per Interrupt, ATtiny25 o.ä."> ;-)
Dann solltest du hier aber auch nicht verschweigen, dass die Beschaltung
an PB4 ein ganz wesentlicher Bestandteil der Entprellung ist. Ohne diese
Beschaltung gehts nicht.
Karl Heinz schrieb:> Dann solltest du hier aber auch nicht verschweigen, dass die Beschaltung> an PB4 ein ganz wesentlicher Bestandteil der Entprellung ist. Ohne diese> Beschaltung gehts nicht.
Na und? Ist das nicht in der Schaltung gezeigt und beschrieben?
Oder wollen wir etwa die 1/10 Cent für R+C auf Millionenstückzahlen
umrechnen?
Luxus hat seinen Preis! ;-)
Also es scheint ne Runde Sache zu sein. Vielen Dank schon einmal dafür!
Habe es jetzt erstmal implementiert und mache mich nun ans Verständnis.
Andersrum wäre vermutlich der sinnvollere Weg :)
was genau ist jetzt der Unterschied zwischen den 3 Funktionen.
get_key_press
get_key_short
get_key_long
Die bewirken bei mir genau das gleiche.
Was sie bewirken SOLLTEN ist natürlich klar.
Beispiel:
1
#define REPEAT_MASK (1<<KEY_RUCK)
2
if(get_key_press(1<<KEY_RUCK))
3
...
4
if(get_key_short(1<<KEY_RUCK))
5
...
6
if(get_key_long(1<<KEY_RUCK))
7
...
reagiert nicht anderes auf längeren Tastendruck etc.
Wie kann ich überprüfen ob 2 Taster gleichzeitig angesprochen werden?
In etwa so?
Frank Sinatra schrieb:> get_key_press> get_key_short> get_key_long>> Die bewirken bei mir genau das gleiche.> Was sie bewirken SOLLTEN ist natürlich klar.
Vermutlich nicht.
Du kannst gleichzeitig nur 2 Sachen unterscheiden und nicht 3!
get_key_short, get_key_long müssen zusammen verwendet werden und
schließen get_key_press aus.
Also entweder kurz/lang erkennen oder nur drücken.
hmm angenommen ich möchte die eine Funktion nur ausführen wenn KEY0 und
KEY1 gleichzeitig gedrückt sind, also:
1
if(get_key_common(1<<KEY0|1<<KEY1))
2
LED_PORT^=1<<LED2;
wie genau muss dann
[c]
#define REPEAT_MASK
[/c)
definiert sein.
So wie ich es jetzt nutze, löst der Taster NICHT bei KEY1 aus, aber bei
KEY0 und wenn KEY1 und KEY0 gleichzeitig gedrückt.
Frank Sinatra schrieb:> hmm angenommen ich möchte die eine Funktion nur ausführen wenn KEY0 und> KEY1 gleichzeitig gedrückt sind, also:>>
1
>if(get_key_common(1<<KEY0|1<<KEY1))
2
>LED_PORT^=1<<LED2;
3
>
4
>
>> wie genau muss dann>> [c]> #define REPEAT_MASK> [/c)>> definiert sein.
REPEAT_MASK fungiert in den PeDa Routinen auf 2 Arten.
Zum einen legt es fest, auf welchen Tasten überhaupt ein Autoreapeat
möglich ist, zum anderen legt es fest, bei welchen Tasten überhaupt eine
Unterscheidung 'kurz' 'lang' gemacht werden kann.
Das hat historische Ursachen. Ganz ganz früher mal, gab es dieses
kurz/lang noch nicht. Da konnten Tasten nur eine zusätzlichen
Autorepeat. Die kurz/lang Unterscheidung ist erst später hinzugekommen
und es zeigte sich, dass für beides derselbe Basismechanismus benutzt
werden kann: eine zeitliche Steuerung. Das eine mal ist das die Zeit die
verstreichen muss, bis der Autorrepeat einsetzt, das andere mal ist es
die Zeit, ab der ein Tastendruck seinen Status von kurz auf lang ändert.
> So wie ich es jetzt nutze, löst der Taster NICHT bei KEY1 aus, aber bei> KEY0 und wenn KEY1 und KEY0 gleichzeitig gedrückt.
Ich schätze mal, du hast KEY1 dann nicht in der Repeat Mask mit drinnen.
Stör dich nicht am Namen 'REPEAT'. Der hat historische Gründe. Die Maske
legt fest, welche Tasten eine zeitliche Sonderfunktion haben können.
Im Grunde könnte man diese Maske auch komplett aus dem Code rauswerfen,
weil man ja sowieso durch den Funktionsaufruf festlegt, was man haben
möchte.
hmm, also in der Repeat Maske habe ich es definit mit drin, es
funktioniert aber leider immer noch nur wie oben gesagt. Ich poste mal
eben die dafür wichtigen Code Zeilen:
Wie gesagt wird tewas() auch bei alleinigen Drücken von Next ausgelöst
und nicht nur bei Drücken von NEXT UND BACK.
Vielen Dank noch für die Erläuterungen bzgl. der REPEATMASKE.
> Wer Taster per Interrupt abfragt, statt die PeDa-Entprellung mit> timergesteuertem Polling zu benutzen, gilt hier allgemein als halbgarer> Vollpfosten.
Warum musst du gleich beleidigend werden? Zwangscharakter? Schreibe
bitte in Zukunft nicht solche Unwahrheiten, wie " ... gilt hier ...",
sondern schreibe nur in deinem Namen. Oder fehlt es dir an
Selbstbewusstsein, dass du dich hinter der Allgemeinheit verstecken
musst?
Mit deinen Kenntnissen ist auch nicht weit her, sonst wüsstest du, dass
es mehr als eine Methode der Entprellung gibt.
Frank Sinatra schrieb:> Wie gesagt wird tewas() auch bei alleinigen Drücken von Next ausgelöst> und nicht nur bei Drücken von NEXT UND BACK.>
Bist du sicher, dass du vorher nicht sowas stehen hast
1
if(get_key_press(1<<KEY_BACK))
2
tuewas();
3
4
if(get_key_common(1<<KEY_BACK|1<<KEY_NEXT))
5
{
6
tuewas();
7
}
Denn DAS geht so nicht. Wenn ein get_key_press erst mal einen
Tastendruck geliefert hat, dann ist der sozusagen ausgeliefert und steht
beim nächsten get_key_irgendwas nicht mehr zur Verfügung.
Wie schon gesagt: Gleichzeitiges Drücken von Tasten zu erkennen ist
schweirig, weil es dir als Benutzer nicht gelingt, beide Tasten wirklich
in derselben Millisekunde zu drücken. Für deinen µC ist es aber
überhaupt kein Problem. Nur erkennt der eben, dass zuerst die eine Taste
und dann erst die andere Taste gedrückt wurde. Wenn daher das Drücken
der einen Taste bereits im Programm ausgewertet wurde, dann ist es Essig
mit dem Erkennen von 2 'gleichzeitigen' Tastendrücken. Für dein Programm
präsentiert sich das als Nacheinander Drücken von 2 Tasten. Selbst wenn
dein Benutzer meint, er drückt die beiden "gleichzeitig".
Jochen schrieb:>> Wer Taster per Interrupt abfragt, statt die PeDa-Entprellung mit>> timergesteuertem Polling zu benutzen, gilt hier allgemein als halbgarer>> Vollpfosten.>> Warum musst du gleich beleidigend werden?
Weil dieses Thema jede Woche 5 mal aufkommt. Mit dem immer gleichen
Ergebnis.
> Mit deinen Kenntnissen ist auch nicht weit her, sonst wüsstest du, dass> es mehr als eine Methode der Entprellung gibt.
Natürlich gibts die.
Aber die eine Methode 'externer Interrupt' hat keine Vorteile, ausser
das man den µC damit aus dem Sleep holen kann und man mit externer
Hardware nachhelfen muss, wenn man kein komplizierten Codemonster
produzieren will.
Karl Heinz schrieb:> Frank Sinatra schrieb:>>> Wie gesagt wird tewas() auch bei alleinigen Drücken von Next ausgelöst>> und nicht nur bei Drücken von NEXT UND BACK.>>>> Bist du sicher, dass du vorher nicht sowas stehen hast if(> get_key_press( 1 << KEY_BACK ) )> tuewas();>> if(get_key_common( 1 << KEY_BACK | 1 << KEY_NEXT ))> {> tuewas();> }
Es ist die allererste Tasterabfrage überhaupt!
nochmal überdenken. (Ich geh davon aus, dass du den Code aus dem von
PeDa angegebenen Link korrekt übernommen hast)
Denn hier gibt es ein potentielles Problem.
Dieses get_key_press
1
unsignedintget_key_press(unsignedintkey_mask){
2
3
INTDisableInterrupts();
4
key_mask&=key_press;// Read key(s)
5
key_press^=key_mask;// Clear key(s)
6
INTEnableInterrupts();
7
returnkey_mask;
8
}
löscht die Drück-Information der ausmaskierten Tasten, selbst wenn nicht
alle Tasten wirklich gleichzeitig gedrückt sind.
Richtig, der Code ist nur angepasst, aber freundlicherweise aus dem
angepassten Link übernommen. Wie gesagt fehlt mir noch das Verständnis
des kompletten Codes. Ich habe ihn einfach implementiert und hoffe auf
ein wenig Learning by doing.
Die Abfrage 2er Tasten gleichzeitig wäre schon toll. Ansonsten bin ich
begeistert von der gegebenen Funktionalität!
Daumen Hoch dafür.
Ich weiß nicht, warum alle so scharf auf 2-Tastenbedienung sind.
2
Man muß einfach nur logisch denken, wie ein MC das erkennen soll,
3
ohne Hellseherei.
4
Man kann es mit meinen Funktionen erreichen. Gleichzeitig bedeutet
5
dann, innerhalb der Zeit zur Langdruckerkennung. Man kann also
6
einen Einzeldruck nicht mehr sofort erkennen.
7
8
9
for(;;){ // main loop
10
switch( get_key_long( 1<<KEY0 | 1<<KEY1 )
11
get_key_short( 1<<KEY0 | 1<<KEY1 )){
(ein paar Postings über dem Verlinkten) ist der richtige Weg. Der ist
auch logisch. Denn get_key_press detektiert einen Tastendruck sofort
beim Niederdrücken. Genau das kann man hier aber nicht brauchen. Um
gleichzeitiges Drücken zu erkennen, muss man schon eine zeitlang warten,
ehe feststeht, dass die minimale Wartezeit, in der eine 2.te Taste
gedrückt werden könnte, verstrichen ist. Das leistet aber get_key_press
nicht.
Frank Sinatra schrieb:> Richtig, der Code ist nur angepasst, aber freundlicherweise aus dem> angepassten Link übernommen. Wie gesagt fehlt mir noch das Verständnis> des kompletten Codes.
Den brauchst du auch nicht wirklich.
Du musst nur wissen, dass in der Variablen key_press für jede Taste 1
Bit auf 1 geht, wenn der Tastendruck beim Ändern das Portpins als
zulässig erkannt wurde.
Die 'Black Magic' innerhalb der ISR muss man dazu nicht verstehen. Es
genügt zu wissen, wie und wann die Bits in den globalen Variablen ihre
Werte ändern.
> Die Abfrage 2er Tasten gleichzeitig wäre schon toll.
Persönlich bin ich kein Fan davon. Denn das bedeutet automatisch, dass
der µC nicht mehr beim Niederdrücken einer Taste auf etwas reagieren
kann, sondern erst beim Loslassen (oder nach einer angemessenen
Wartezeit). Genau das Problem gibt es in Windows ja auch: wie
unterscheidet man einen einfachen Mausklick von einem Doppelten? DU
kannst es erst unterscheiden, wenn nach dem Drückken eine bestimmte Zeit
vergangen ist. In der Zeit dazwischen, zwischen Niederdrücken und dem
Ablauf dieser Zeit, hängt alles in der Schwebe. Kommt noch ein weiterer
Mausklick oder nicht?
Karl Heinz schrieb:> Aber die eine Methode 'externer Interrupt' hat keine Vorteile, ausser> das man den µC damit aus dem Sleep holen kann und man mit externer> Hardware nachhelfen muss, wenn man kein komplizierten Codemonster> produzieren will.
Gib doch einfach zu, dass Du es nicht begriffen hast - garnicht
begreifen willst.
Mit "externer Hardware nachhelfen" kann man auch anderns formulieren:
eine externe Schutzbeschaltung vorsehen!
"Kompliziertes Codemonster": absoluter Blödsinn!
Vielleicht bist Du einfach schon zu alt, wenn es Dich irritiert, dass
eine Enprellung im ms-Bereich stattfinden kann. Damit bekommt man
Betätigungen von Tastern (insbesondere auch Reedrelais) sicher
entprellt, während das Pollen per Software nur einen offenen Kontakt
feststellen kann: Guten Morgen!
Frank Sinatra schrieb:> Wie gesagt fehlt mir noch das Verständnis> des kompletten Codes.
Schön zu lesen ;-)
ALso ich finde die Timer Interrupt Routine sehr gut und möchte mich
gerade bei Herrn Buchegg recht herzlich bedanken, der hier schon
häufiger mit Engels Geduld geholfen hat. Dabei ist er einer der Wenigen,
die sich nicht bei der erstbesten dummen Frage auf einen stürzen :)
Karl Heinz schrieb:> Denn das bedeutet automatisch, dass> der µC nicht mehr beim Niederdrücken einer Taste auf etwas reagieren> kann, sondern erst beim Loslassen (oder nach einer angemessenen> Wartezeit).
Um das ganz klar anzusprechen.
Es gibt einen WESENTLICHEN UNterschied zwischen get_key_press und
get_key_short/long
get_key_press liefert die Information des Tastendrucks beim
Niederdrücken der Taste. Wird eine Taste gedrückt und bleibt das auch so
nach der Entprellung, dann kriegst du diesen Tastendruck von
get_key_press sofort gemeldet (und der entsprechende Tastendruck wird
intern gelöscht, weil er ja bereits behandelt wurde). Damit kannst du
aber nicht einen langen von einem kurzen Tastendruck unterscheiden, denn
zum Zeitpunkt des Niederdrückens steht ja noch nicht fest, welches von
beiden es werden wird. Das kann man ja erst nach einer angemessenen
Zeitspanne sagen (bzw. wenn die Taste wieder losgelassen wurde). Ist der
Tastendruck kürzer als diese Zeitspanne, dann war es ein kurzer. Ist
hingegen nach dieser Zeitspanne die Taste immer noch gedrückt, dann kann
es kein kurzer sein, sondern es ist ein langer. Damit das aber
funktioniert, darf die Information, dass die Taste gedrückt wurde, nicht
schon von einem get_key_press gelöscht worden sein. Daher können die
beiden Funktionseinheiten 'Tastendruck erkennen', 'Tastendruck als
kurz/lang erkennen' auch nicht gemeinsam eingesetzt werden.
Und beim Erkennen von gemeinsamen Tastendrücken ist es nicht anders. Um
zu erkennen, dass 2 Tasten gleichzeitig gedrückt worden sind, darf die
jeweils zuerst gedrückte Taste (und das ist unvermeidlich), nicht schon
mehr oder weniger sofort nach dem Niederdrücken ausgewertet werden.
halbgarer Vollpfosten schrieb:> Karl Heinz schrieb:>> Aber die eine Methode 'externer Interrupt' hat keine Vorteile, ausser>> das man den µC damit aus dem Sleep holen kann und man mit externer>> Hardware nachhelfen muss, wenn man kein komplizierten Codemonster>> produzieren will.>> Gib doch einfach zu, dass Du es nicht begriffen hast - garnicht> begreifen willst.> Mit "externer Hardware nachhelfen" kann man auch anderns formulieren:> eine externe Schutzbeschaltung vorsehen!
Ja. Ist auch wahnsinnig wichtig bei einem Taster der nach Masse
schaltet.
> "Kompliziertes Codemonster": absoluter Blödsinn!> Vielleicht bist Du einfach schon zu alt,
Vielleicht hab ich einfach nur schon zuviele sogenannte Entprellungen
gesehen, die das Papier nicht wert waren, auf dem sie ausgedruckt
wurden?
Frank Sinatra schrieb:> So wie ich es jetzt nutze, löst der Taster NICHT bei KEY1 aus, aber bei> KEY0 und wenn KEY1 und KEY0 gleichzeitig gedrückt.
Du mußt das Beispiel genauso übernehmen, wie in dem Link, also 3
Funktionsaufrufe.
Wenn Du wirklich nur "gleichzeitig" haben willst, mußt Du die beiden
anderen ja nicht auswerten, sondern nur ausführen.
Peter Dannegger schrieb:> Frank Sinatra schrieb:>> So wie ich es jetzt nutze, löst der Taster NICHT bei KEY1 aus, aber bei>> KEY0 und wenn KEY1 und KEY0 gleichzeitig gedrückt.>> Du mußt das Beispiel genauso übernehmen, wie in dem Link, also 3> Funktionsaufrufe.> Wenn Du wirklich nur "gleichzeitig" haben willst, mußt Du die beiden> anderen ja nicht auswerten, sondern nur ausführen.
Hmm.
wo versteckt sich da wieder die kleine Teufelei in
Beitrag "Universelle Tastenabfrage mit 2 Tastenerkennung"
:-)
Ich find nicht raus, warum
Karl Heinz schrieb:> ist absolut logisch. Das ist leicht zu verstehen. Aber mit der common> Routine und wie du sie im Beispiel benutzt, komm ich nicht klar.
Ach, mein Gott.
Stirn auf Tisch klatsch.
Ja, jetzt hab ichs. Ich hab mich in der Klammerung vertan und die ganze
Zeit was anderes gelesen als tatsächlich dort steht.
Ganz im Gegenteil. Das ist noch simpler als ich die ganze Zeit gedacht
hab.
Karl Heinz schrieb:> Ach, mein Gott.> Stirn auf Tisch klatsch.>> Ja, jetzt hab ichs. Ich hab mich in der Klammerung vertan und die ganze> Zeit was anderes gelesen als tatsächlich dort steht.> Ganz im Gegenteil. Das ist noch simpler als ich die ganze Zeit gedacht> hab.
Irren ist menschlich und mache Dinge brauchen ihre Zeit, sie zu
verstehen. Hier und auch woanders!
Frank Sinatra schrieb:
Hmm.
> So wie ich es jetzt nutze, löst der Taster NICHT bei KEY1 aus, aber bei> KEY0 und wenn KEY1 und KEY0 gleichzeitig gedrückt.
Nachdem ich gefunden habe, wo ich mich im
komplett verrannt habe (das ganze hat so erst mal nichts mit Repeat zu
tun), seh ich aber immer noch nicht, wie es zum beobachteten Effekt
kommt. Ich denke es wird Zeit für vollständigen Code.
Eigentlich dürfte ein
1
while(1){
2
3
if(get_key_common(1<<KEY_BACK|1<<KEY_NEXT))
4
{
5
tuewas();
6
}
7
}
nur dann bei tuewas() landen, wenn auch wirklich beide Tasten gedrückt
sind.
Funktioniert denn ein
1
while(1){
2
if(get_key_press(1<<KEY_BACK))
3
ToggleLed1
4
5
if(get_key_press(1<<KEY_NEXT))
6
ToggleLed2
7
}
so wie es soll?
(Wichtig: In der Hauptschleife jeweils nur sinngemaess genau diese Code.
Nichts anderes. Insbesondere darf get_key_common nicht gemeinsam mit
get_key_press in derselben Hauptschleife benutzt werden.)
Karl Heinz schrieb:> Aber die eine Methode 'externer Interrupt' hat keine Vorteile, ausser> das man den µC damit aus dem Sleep holen kann und man mit externer> Hardware nachhelfen muss, wenn man kein komplizierten Codemonster> produzieren will.
Das stimmt doch in dieser Allgemeinheit nicht. Ich habe im zweiten oder
dritten Posting dieses Threads klargestellt, daß es drei Ausnahmen von
der Regel gibt.
Und das angeblich so hoch"komplizierte Codemonster", was in diesen drei
Fällen zur Entprellung benutzt wird, reduziert sich in Fall 1 auf exakt
NULL Zeilen Quelltext (weil hier eben einfach keine Entprellung nötig
ist), in den beiden anderen Fällen auf je ZWEI Zeilen.
Und zwar ist unabhängig von der verwendeten Programmiersprache hier eine
"Zeile" wirklich nur eine Zeile, was wohl die absolute Trivialität des
Sachverhaltes betont.
Wenn du zu blöd bist, den Sachverhalt hinreichend abstrakt zu betrachten
und/oder die Vorteile zu begreifen, die sich ergeben können, wenn man
eben einen dieser drei Sonderfälle hat, dann tust du mir einfach nur
leid...
Wahrscheinlich eine Art Fachidiot. Immer getreu dem Spruch "das haben
wir doch immer so gemacht, das hat sich bewährt", bar jeder Fantasie,
bar jedes eigenständigen Denkens.
Guten Morgen,
nochmal eine Bitte. Gibt es eine einfache Grundregel in welchen
Zusammenhängen und Kombis die verschiedenen Funktionen get_key_short,
get_key_long und get_key_press genutzt werden dürfen. Im allgemeinen bin
ich schon mit der get_key_press Funktion zufrieden, d.h. ich will
eigentlich gar nicht abfragen ob der Taster kurz oder lang gedrückt
wurde.
Wenn ich beispielsweise die get_key_press Funktion nutze, darf ich mit
dieser nach Lust und Laune alle Taster abfragen oder muss bzgl. des Key
States irgendwas bestimmtes beachtet werden. Ich habe das Gefühl, dass
beispielsweise durch
1
while(!get_key_press(1<<KEY_BACK))
durch drücken teilweise auch
1
if(get_key_press(1<<KEY_menu1))
2
{
3
tuemenu2();
4
}
tuemenu2(); ausgeführt wird OHNE das KEY_menu1 wirklich gedrückt wird.
Was muss bei der get_key_press Funktion bzgl. des Keystates genau
beachtet werden?
Frank SInatra schrieb:> Wenn ich beispielsweise die get_key_press Funktion nutze, darf ich mit> dieser nach Lust und Laune alle Taster abfragen oder muss bzgl. des Key> States irgendwas bestimmtes beachtet werden.
Solange du nur get_key_press benutzt, kannst du das nach Lust und Laune
benutzen.
Schwieriger wird es wenn da irgendwelche Zeitdinge ins Spiel kommen. Und
du musst dir darüber im klaren sein, dass es im Rechner kein
'gleichzeitig' gibt. Vor allen Dingen dann nicht, wenn Menschen im Spiel
sind. Egal wie sehr du dich auch bemühst, du schaffst es nicht 2 Tasten
exakt gleichzeitig zu drücken. Das ist nun mal ein Faktum, das du nicht
ignorieren kannst.
Wenn du also
1
if(get_key_press(1<<KEY1))
2
...
3
4
if(get_key_press(1<<KEY2))
5
...
6
7
if(get_key_common(1<<KEY1|1<<KEY2))
8
...
programmierst, dann wird es praktisch immer so sein, dass einer der
beiden get_key_press dem get_key_common einen der beiden Tastendrücke
"wegschnappen" wird. D.h. die Einzelerkennungen werden tadellos
funktionieren, aber der gemeinsame Tastendruck wird nicht funktionieren.
> Ich habe das Gefühl, dass> beispielsweise durch
'Gefühl zu haben' ist an dieser Stelle ganz schlecht. Wenn du denkst
irgendetwas klappt nicht so, wie du denkst, dann überlege dir, wie du
das testen kannst.
> Was muss bei der get_key_press Funktion bzgl. des Keystates genau> beachtet werden?
Bis auf die Zeitsache: gar nichts.
Frank SInatra schrieb:> Ich spezifiziere mein Problem noch einmal genauer mit etwas Code:
Du hast mit ziemlicher Sicherheit irgendein anders Logikproblem im Code.
Gegen die Systematik
1
while(1)
2
{
3
4
if(get_key_press(1<<KEY_BACK))
5
tuewas();
6
7
if(get_key_press(1<<KEY_OK))
8
{
9
while(!get_key_press(1<<KEY_OK))
10
{
11
// wenn hier KEY_BACK gedrückt wird, wird ebenfalls
12
// tuewas(); ausgeführt
13
// dies ist aber nicht gewünscht, verstehe ich auch nicht, da
14
// wir uns in einer Endlosschleife befinden und der
15
// taster KEY_BACK ja gar nicht
16
// abgefragt wird. Vermutlich wieder ein C Problem?
17
}
18
}
19
}
ist nichts einzuwenden. Ich schätze mal, die Programmausführung steckt
in Wirklichkeit gar nicht in der inneren Schleife. Teste das halt mal,
in dem du dir entsprechende Ausgaben einbaust, die dir das anzeigen
OK vielen Dank. Habe ich einmal eingebaut.
Der Code sieht wie folgt aus.
> while( 1 )> {>> if( get_key_press( 1 << KEY_BACK ) )> tuewas();>> if( get_key_press( 1 << KEY_OK ) )> {>> **** irgendeine LED einschalten ****>> while( !get_key_press( 1 << KEY_OK ) )> {> .....> }>> **** die LED wieder ausschalten ****> }> }
Wenn KEY_OK gedrückt wird wird komischerweise die LED eingeschlatet UND
tuewas(); ausgeführt.
Was jedoch funktioniert ist:
1
>while(1)
2
>{
3
>
4
>if(get_key_press(1<<KEY_BACK))
5
>tuewas();
6
>
7
>if(get_key_press(1<<KEY_OK))
8
>{
9
>
10
>****irgendeineLEDeinschalten****
11
>
12
>while(!get_key_press(1<<KEY_OK))
13
>{
14
>if(get_key_press(1<<KEY_BACK)
15
>tuenochetwasanderes();
16
>}
17
>
18
>****dieLEDwiederausschalten****
19
>}
20
>}
D.h. wenn ich den OK Button nochmal abfrage wird in der TAT NUR die LED
getoogelt und NICHT mehr tuwas() ausgeführt. Jedoch NUR MIT dieser
zusätzlichen Abfrage:
Karl Heinz schrieb:> while( !get_key_press( 1 << KEY_OK ) )> {> // wenn hier KEY_BACK gedrückt wird, wird ebenfalls> // tuewas(); ausgeführt> // dies ist aber nicht gewünscht, verstehe ich auch nicht, da> // wir uns in einer Endlosschleife befinden und der> // taster KEY_BACK ja gar nicht> // abgefragt wird. Vermutlich wieder ein C Probl
Das ist vollkommen korrekt.
Das Bit wird ja im Interrupt gesetzt und wenn Du es nicht abholst,
bleibt es das auf ewig.
Du mußt also beim Verlassen des While einen Dummyaufruf zum Löschen
machen.
Am besten läßt Du solche verchachtelten While ganz sein. Bei sowas
verliert man nämlich ruckzuck den Überblick.
Peter Dannegger schrieb:> Du mußt also beim Verlassen des While einen Dummyaufruf zum Löschen> machen.
OK, sowas in der Art habe ich mir schon gedacht, also sowas hier:
Frank SInatra schrieb:> Peter Dannegger schrieb:>> Du mußt also beim Verlassen des While einen Dummyaufruf zum Löschen>> machen.>> OK, sowas in der Art habe ich mir schon gedacht, also sowas hier:
Reden wir alle vom selben?
IN dem Code hier, wird beim ersten Drücken von OK in den 'Subzweig'
gegangen, indem der µC dann in der while-Schleife hängt. In dieser
Schleife kannst du BACK drücken, ohne das erst mal irgendwas passiert.
E>rst durch erneutes Drücken von OK kommst du aus der Schleife raus.
Hast du aber 'innerhalb' der Schleife BACK gedrückt, dann wird der
Tastendruck registriert aber logischerweise nicht bearbeitet. Er geht
aber nicht verloren.
Ist es das, was du beobachtet hast? Denn deine Problembeschreibung hat
sich zumindest für mich ganz anders angehört.
>> if(get_key_press(1<<KEY_BACK))>> {// nix machen, nur dummy}
Find ich so keine gute Lösung.
Kommt ein weiterer Key dazu, dann muss man in allen derartigen Dummy
Aufrufen diesen Key ergänzen.
Karl Heinz schrieb:> Frank SInatra schrieb:> IN dem Code hier, wird beim ersten Drücken von OK in den 'Subzweig'> gegangen, indem der µC dann in der while-Schleife hängt. In dieser> Schleife kannst du BACK drücken, ohne das erst mal irgendwas passiert.> E>rst durch erneutes Drücken von OK kommst du aus der Schleife raus.> Hast du aber 'innerhalb' der Schleife BACK gedrückt, dann wird der> Tastendruck registriert aber logischerweise nicht bearbeitet. Er geht> aber nicht verloren.
Genau dieses hier. In der while Schleife sollte der Back-Button wenn
möglich gar nicht beachtet werden, also auch nicht registriert. Dies ist
mein Problem. Sorry, wenn ich mich da mißverständlich ausgedrückt habe.
Frank SInatra schrieb:> Genau dieses hier. In der while Schleife sollte der Back-Button wenn> möglich gar nicht beachtet werden, also auch nicht registriert.
Wird er aber. Jeder Tastendruck wird registriert.
> Dies ist> mein Problem.
Ok. Dann musst du ihn löschen oder dein Programm so formulieren, dass es
kein Problem ist. Letzters ist der Normalfall, in dem man in seinem
Programm einen Status einbaut. Denn diese 'warte auf
Tastendruck'-Schleifen sind auf einem µC sowieso meistens Gift, wie PeDa
schon sagte. Es ist genau diese 'Wir warten auf etwas' Mentalität, die
in einem Progrmm verhindert, dass ein µC scheinbar mehrere Dinge
gleichzeitig macht. Denn auch wenn er gerade auf eine Bestätigung von
dir wartet, deswegen darf der Codeteil, der das Badewasser überwacht und
gegebenenfalls den Zulauf abdreht ja trotzdem nicht stillstehen sondern
muss auch weiterhin ausgeführt werden.
1
editingValue=false;
2
3
while(1)
4
{
5
if(get_key_press(1<<KEY_BACK))
6
{
7
if(!editingValue)
8
{
9
TasteBACKkannzumjetzigenZeitpunktgedrücktwerden
10
}
11
}
12
13
if(get_key_press(1<<KEY_OK))
14
{
15
if(editingValue)
16
{
17
VeränderneinesWerteswarimGangundistabgeschlossen
18
editingValue=false;
19
}
20
else
21
{
22
einaktuellerWertwirdzumVerändernfreigegeben
23
editingValue=true;
24
}
25
}
26
27
28
// alles was weiterlaufen muss, auch wenn der Benutzer