Liebe Community!
Ich habe eine Frage zur Entprellungs-"Komfort-Routine" von Peter
Dannegger, siehe hier:
http://www.mikrocontroller.net/articles/Entprellung#Interrupt-Verfahren_.28nach_Peter_Dannegger.29
Ich weiß, es wurde schon oft durchgekaut, jedoch konnte dass alles meine
Fragen nicht klären. Das Hauptproblem ist, dass ich derzeit keine
Möglichkeiten habe, auch nur irgendwas auf einem AVR zu testen.
Trotz allem muss ich mehr oder weniger bis Sonntag ein Projekt
fertigstellen, in dem ich eine Entprellung brauche. An und für sich ist
die Routine ja auch sehr komfortabel, und ich habe mich sehr gerne dafür
entschieden.
Jedoch bin ich mir bis heute im Unklaren, was die einzelnen Abfragen
GANZ GENAU machen, und welche sich stören.
Es gibt ja die 4 Abfragen:
get_key_press
get_key_short
get_key_long
get_key_rpt
Nun, kann ich denn auf einfache Weise, so wie hier 1 | if (get_key_short(1<<KEY0)) {
| 2 | // Tue Aktion A
| 3 | }
| 4 | else if (get_key_short(1<<KEY0)) {
| 5 | // Tue Aktion B
| 6 | }
|
zwischen langem Tastendruck und kurzem unterscheiden? Immerhin wartet
die Routine ja auf das loslassen der Taste, bis ein short-press oder
long-press erkannt wird. Bekomme ich da Probleme mit dem if/else
if-Statement?
Und aus dem Source-Code:
// check if a key has been pressed. Each pressed key is reported
// only once
Heißt das, wenn er einmal abgefragt ist, wird er nie wieder als gedrückt
erkannt, oder wie? Oder nur, bis der ISR-Ablauf wieder durchgerannt ist?
Bitte helft mit ein bißchen, ich komme im Moment kein Stück weiter... :(
Vielen Dank im Vorraus!
Lg Marc
Marc Brexner schrieb:
> zwischen langem Tastendruck und kurzem unterscheiden? Immerhin wartet
> die Routine ja auf das loslassen der Taste, bis ein short-press oder
> long-press erkannt wird.
keine einzige der get_... Funktionen wartet auf irgendwas.
> Bekomme ich da Probleme mit dem if/else
> if-Statement?
Nein
> Und aus dem Source-Code:
> // check if a key has been pressed. Each pressed key is reported
> // only once
>
> Heißt das, wenn er einmal abgefragt ist, wird er nie wieder als gedrückt
> erkannt, oder wie?
Es heist genau das was dort steht.
Du drückst auf die Taste und get_key_press liefert für diese Taste
einmal TRUE. Du drückst erneut auf die Taste und get_key_press liefert
wieder nur 1mal TRUE
> Bitte helft mit ein bißchen, ich komme im Moment kein Stück weiter... :(
Du machst dir zu viele Sorgen.
Alle get_.... Funktionen liefern dir die Info ob eine Taste
nieder-gedrückt wurde. So wie auf deinem Keyboard auch. Du drückst die
Taste 'A' und 1 'a' erscheint in deinem Text. 1 Tastendruck - 1 Aktion.
Im Falle von get_key_short vs. get_key_long klarerweise erst dann, wenn
die Taste wieder losgelassen wird.
Nunja, aber sobald einmal get_key_press abgefragt wurde, liefert mir
get_key_short doch nur noch false?
Ich meine, kann so ein Gebilde denn noch funktionieren?
1 | if (get_key_press(1<<KEY0) || get_key_press(1<<KEY0)) { // Ist mind. ein Taster gedrückt (nicht key_short, sondern key_press! siehe debounce.h)
| 2 | if (~clockStatus & (1<<CK3)) { // Wird die Uhr gerade nicht verstellt
| 3 | if (get_key_short(1<<KEY0) || get_key_short(1<<KEY1)) {
| 4 | if (~clockStatus & (1<<CK0)) { // Ist die Anzeige aus, die ...
| 5 | clockStatus |= (1<<CK0); // ... Anzeige eingeschalten
| 6 | }
| 7 | else { // Ist die Anzeige aus, die ...
| 8 | clockStatus &= ~(1<<CK0); // ... Anzeige ausschalten
| 9 | }
| 10 | }
| 11 | if (get_key_long(1<<KEY0)) { // Ist die Taste zum verstellen lange genug gedrückt...
| 12 | clockStatus |= (1<<CK3); // ... Modus zum verstellen der Uhr betreten
| 13 | }
| 14 | }
| 15 | else
| 16 | {
| 17 | if (get_key_short(1<<KEY0)) // Ist Taster 0 gedrückt, wechselt man von H auf M, von M auf S, und von S auf fertig.
| 18 | {
| 19 | if (clockStatus & (1<<CK4)) {
| 20 | clockStatus &= ~(1<<CK4); // Stunde aus
| 21 | clockStatus |= (1<<CK4); // Minute an
| 22 | }
| 23 | else if (clockStatus & (1<<CK5)) {
| 24 | clockStatus &= ~(1<<CK5); // Minute aus
| 25 | clockStatus |= (1<<CK6); // Sekunde an
| 26 | }
| 27 | else if (clockStatus & (1<<CK6))
| 28 | {
| 29 | clockStatus &= ~(1<<CK6); // Sekunde aus
| 30 | clockStatus &= ~(1<<CK3); // Bearbeitung beendet
| 31 | seconds = displayHours * 3600 + displayMinutes * 60 + displaySeconds; // Neue Uhrzeit übernehmen
| 32 | }
| 33 | }
| 34 | else if(get_key_short(1<<KEY1) || get_key_press(1<<KEY1) || get_key_rpt(1<<KEY1)) { // Wird Taster 1 gedrückt (oder repeat)
| 35 | if (clockStatus & CK4) {
| 36 | displayHours++; // Um eine Stunde erhöhen
| 37 | if (displayHours == 24) { // Nur bis 23:59:59! -> Maximal 23h
| 38 | displayHours = 0;
| 39 | }
| 40 | }
| 41 | else if (clockStatus & CK5) {
| 42 | displayMinutes++; // Um eine Minute erhöhen
| 43 | if (displayMinutes == 60) {
| 44 | displayMinutes = 0; // Nur bis 23:59:59! -> Maximal 59min
| 45 | }
| 46 | }
| 47 | else if (clockStatus & CK6) {
| 48 | displaySeconds++; // Um eine Sekunde erhöhen (1s)
| 49 | if (displaySeconds == 60) {
| 50 | displaySeconds = 0; // Nur bis 23:59:59! -> Maximal 59s;
| 51 | }
| 52 | }
| 53 | }
| 54 | }
| 55 | }
|
Ich kann es mir nur schwer vorstellen...?
Du sollst auch nicht get_key_press mit get_key_short an einem Portpin
mischen.
get_key_short und get_key_long gehören zusammen.
und
get_key_press und get_key_rpt gehören zusammen.
Also schön brav immer innerhalb einer der beiden 'Familien' bleiben.
In der ISR wird in ein paar Variablen vermerkt, dass eine Taste gedrückt
wurde. Sobald du die entsprechende Abfrage auf diese Taste machst, wird
dieser Vermerk für diese Taste gelöscht. D.h. Nach einem get_key_press
wird dir ein unmittelbar nachfolgender get_key_short immer ein FALSE
liefern. So schnell kannst du eine Taste gar nicht drückn, dass du das
in der Zeit dazwischen schaffst.
Aber wie kann ich denn dann meine Steuerung realisieren? Ich wollte
Taster sparen, indem ich zwischen langen und kurzen Tastendrücken
unterscheide. Auszug aus dem Handbuch meiner Uhr:
Bedienung:
Taster 0 -> Oberer Taster
Taster 1 -> Unterer Taster
Uhr inaktiv (keine LEDs an):
Taster 0 oder Taster 1 einmal kurz drücken -> Uhr wird eingeschalten
Uhr aktiv (LEDs an):
Taster 0 einmal lange drücken -> Uhr geht in Modus zum Einstellen
Taster 0 oder Taster 1 einmal kurz drücken -> Uhr wird ausgeschalten
Einstellungsmodus (LEDs blinken):
Stunden-anzeige blinkt: Die Stundenanzahl kann nun durch Drücken von
Taster 1 nun verstellt werden. Wird Taster 1 lange gedrückt, geht er in
den sogenannten „Repeat-Modus“, und signalisiert alle 200 Millisekunden
einen Tastendruck für Sie. Durch Drücken von Taster 0 wird die Eingabe
der Stundenanzahl gespeichert, und Sie können die Minuten einstellen.
(Die Minuten-Anzeige beginnt zu blinken)
Minuten-Anzeige blinkt: Die Minutenanzahl kann nun durch Drücken von
Taster 1 nun verstellt werden. Wird Taster 1 lange gedrückt, geht er in
den sogenannten „Repeat-Modus“, und signalisiert alle 200 Millisekunden
einen Tastendruck für Sie. Durch Drücken von Taster 0 wird die Eingabe
der Minutenanzahl gespeichert, und Sie können die Sekunden einstellen.
(Die Sekunden-Anzeige beginnt zu blinken)
Sekunden-Anzeige blinkt: Die Sekundennzahl kann nun durch Drücken von
Taster 1 nun verstellt werden. Wird Taster 1 lange gedrückt, geht er in
den sogenannten „Repeat-Modus“, und signalisiert alle 200 Millisekunden
einen Tastendruck für Sie. Durch Drücken von Taster 0 wird die Eingabe
der Sekunden-Anzahl gespeichert, und die von Ihnen eingestellte Uhrzeit
übernommen.
> Ich meine, kann so ein Gebilde denn noch funktionieren?
Nein. So wird das nichts.
Du gehst davon aus, dass die die get_.... Funktionen solange TRUE
liefern, solange eine Taste gedrückt ist. Genau das tun sie aber nicht
und genau das ist auch der Witz an der ganzen Sache.
Hm, okay. Jetzt verstehe ich, wie das funktioniert. Nun muss ich nur
noch überlegen, was ich mache, um je nach aktuellem Modus auf die
Abfragen zu reagieren...
Irgendwie macht dass das ganze jetzt um einiges schwerer... =/
Marc Brexner schrieb:
> Taster 0 oder Taster 1 einmal kurz drücken -> Uhr wird eingeschalten
> Uhr aktiv (LEDs an):
if Anzeige == aus )
{
if key pressed 0 or key pressed 1
Anzeige ein
}
else
{
if key short 0 or key short 1
Anzeige aus
else if key long 0
{
// Einstellungsmodus
while ! key pressed 0
{
if key pressed 1 or key repeat 1
Stunden++
}
while ! key pressed 0
{
if key pressed 1 or key repeat 1
Minuten++
}
while ! key pressed 0
{
if key pressed 1 or key repeat 1
Sekunden++
}
}
}
> Irgendwie macht dass das ganze jetzt um einiges schwerer... =/
find ich nicht :-)
Ganz im Gegenteil
1 | if (clockStatus & (1<<CK1)) // Tasterabfrage aktiv, mal sehen was nun zu tun ist
| 2 | {
| 3 | if (~TIMSK1 & (1<<OCIE1A)) { // Timer für Tastenabfrage ist inkativ, also ...
| 4 | TIMSK1 |= (1<<OCIE1A); // ... aktivieren
| 5 | }
| 6 | if (~clockStatus & (1<<CK0)) { // Uhr ist aus
| 7 | if (get_key_short(1<<KEY0) || get_key_short(1<<KEY1)) { // Bei kurzem Tastendruck
| 8 | clockStatus |= (1<<CK0); // Anzeige einschalten
| 9 | }
| 10 | }
| 11 | else {
| 12 | if (~clockStatus & (1<<CK3)) { // Wenn die Uhrzeit nicht bearbeitet wird
| 13 | if (get_key_short(1<<KEY0) || get_key_short(1<<KEY1)) { // Bei kurzem Tastendruck
| 14 | // TODO: ALLES AUS damit AVR wieder Energie sparen kann! Diese Anweisung schaltet nur die Anzeige aus!
| 15 | clockStatus &= ~(1<<CK0);
| 16 | }
| 17 | else if (get_key_long(1<<KEY0)) { // Bei langem Tastendruck von Taster 0
| 18 | clockStatus |= (1<<CK3); // Einstellungsmodus betreten
| 19 | }
| 20 | }
| 21 | else {
| 22 | if (get_key_short(1<<KEY0)) { // Taster 0 wird gedrückt -> Modus umschalten!
| 23 | if (clockStatus & (1<<CK4)) {
| 24 | clockStatus &= ~(1<<CK4); // Stunde aus
| 25 | clockStatus |= (1<<CK4); // Minute an
| 26 | }
| 27 | else if (clockStatus & (1<<CK5)) {
| 28 | clockStatus &= ~(1<<CK5); // Minute aus
| 29 | clockStatus |= (1<<CK6); // Sekunde an
| 30 | }
| 31 | else if (clockStatus & (1<<CK6)) {
| 32 | clockStatus &= ~(1<<CK6); // Sekunde aus
| 33 | clockStatus &= ~(1<<CK3); // Bearbeitung beendet
| 34 | seconds = displayHours * 3600 + displayMinutes * 60 + displaySeconds; // Neue Uhrzeit übernehmen
| 35 | }
| 36 | }
| 37 | if (get_key_press(1<<KEY1) || get_key_rpt(1<<KEY1)) { // Wird Taster 1 gedrückt oder gehalten aktuelle ausgewähltes "Element" der Uhr hochzählen.
| 38 | if (clockStatus & CK4) {
| 39 | displayHours++; // Um eine Stunde erhöhen
| 40 | if (displayHours == 24) { // Nur bis 23:59:59! -> Maximal 23h
| 41 | displayHours = 0;
| 42 | }
| 43 | }
| 44 | else if (clockStatus & CK5) {
| 45 | displayMinutes++; // Um eine Minute erhöhen
| 46 | if (displayMinutes == 60) {
| 47 | displayMinutes = 0; // Nur bis 23:59:59! -> Maximal 59min
| 48 | }
| 49 | }
| 50 | else if (clockStatus & CK6) {
| 51 | displaySeconds++; // Um eine Sekunde erhöhen (1s)
| 52 | if (displaySeconds == 60) {
| 53 | displaySeconds = 0; // Nur bis 23:59:59! -> Maximal 59s;
| 54 | }
| 55 | }
| 56 | }
| 57 | }
| 58 | }
|
Dann hat dieses Gebilde in deinen Augen schon etwas mehr
durchsetzungskraft, oder? Danke für deinen "Prototypen"! :D
Lg Marc
Da ich seit gestern wieder zu Hause bin, habe ich mich gleich
hingesetzt, und auf meinem Testboard was zusammengesteckt. Dieses von
mir zuletzt gepostetes "Gebilde" funktioniert - Danke, für eure Hilfe!
Und ein großes Lob an Peters Entprellungs-Code, der funktioniert
wirklich TOP
Lg Marc
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|