Kann mir jemand einen Hinweis geben, wie man Peters Code so erweitern kann, dass zusätzlich zum langen Drücken einer Taste auch noch das sehr lange Drücken erkannt wird? (Soll als eine Art "reset" verwendet werden, also nicht für die normale Bedienung.) Vielen Dank im voraus, ...Rolf
Rolf Niepraschk schrieb: > Kann mir jemand einen Hinweis geben Wo ist Dein Problem? Niemand hindert Dich daran, das entsprechende Bit in key_state zu testen und damit einen Zähler im Timerinterrupt hochlaufen zu lassen.
Danke. Es funktioniert. ...Rolf
Gast
#3823080
Peter Dannegger schrieb: > Sowas macht man am besten als Statemaschine. > Für 3s Wartezeit muß der Timerinterrupt >12ms sein oder man nimmt ein > uint16_t als Zähler. > enum { OFF, ON, BLINK }; > > int main() > { > uint8_t state = OFF; > for(;;){ > switch( state ){ > case OFF: > led_off(); > if( get_key_short( 1<<KEY1 )) > state = ON; > if( get_key_long( 1<<KEY1 )) > state = ON; > break; > case ON: > led_on(); > if( get_key_short( 1<<KEY1 )) > state = OFF; > if( get_key_long( 1<<KEY1 )) > state = BLINK; > break; > case BLINK: > led_blink(); > if( get_key_short( 1<<KEY1 )) > state = OFF; > if( get_key_long( 1<<KEY1 )) > state = OFF; > break; > } > } > } Hallo, doofe Frage, aber bist du sicher dass das so funktioniert? Ich habe das meiner Meinung nach genauso, allerdings passiert auf Tastendruck nichts. Außerhalb der SM funktioniert es tadellos. Jemand eine Idee? Danke!
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
AnBo schrieb: > aber bist du sicher dass das so funktioniert? > Ich habe das meiner Meinung nach genauso, allerdings passiert auf > Tastendruck nichts. Dein Code ist dermaßen verschieden zu meinem Beispiel, es wäre ein Wunder, wenn er genauso funktionierte. Probier doch meinen einfach mal aus.
Gast
#3824971
Hallo, ich bin noch mal alles Schritt für Schritt durchgegangen und habe es mit deinem Code verglichen. Da ist mir dann letztendlich aufgefallen, dass ich die Pullups in einem Schritt wieder ausgeschaltet hatte. Danke für deine ganzen Mühen und die viele Hilfestellung!
Peter Dannegger schrieb: > Probier doch meinen einfach mal aus. LOL.
Guten Tag zusammen. Ich habe mich die letzen Tage mit dem hier vorgestellten Entprellcode auseinandergesetzt und möchte als erstes sagen: "Danke an Peter Dannegger für diesen tollen code und an alle die ihn weiter verbessert haben!" Zugegeben, ich habe nicht jede Zeile verstanden, aber weiss jetzt wie ich ihn anwenden kann. Vielleicht würde ja Zettel und Stift zu besserem Verständnis führen ;-) Als kleines Dankeschön habe ich mir mal die Mühe gemacht alles hier zusammengetragene in eine Datei zu packen. Die Nutzung von mehreren Eingangsports, für mehr als acht Tasten, habe ich allerdings nicht eingebaut. Da ich programmieren nur mit PICs gelernt habe, kann ich nur die Funktion dieses angehängten codes bestätigen (Simuliert mit Proteus). Wenn also mal jemand die Version für AVR kontrollieren könnte wäre das super. Ich habe es aber nach bestem Gewissen versucht umzusetzen. Den Simulationsschaltkreis für Proteus habe ich auch angefügt. Also viel Spass damit :-) Schöne Grüsse Mario @Peter Dannegger: Darf ich den Code im CCS Forum posten? Unter Angabe der Quelle natürlich.
Gast
#3946245
Hallo, bei mir reagieren die Taster nicht ;/ Musste ein paar Anpassungen der Timer für den Attiny841 vornehmen. Die ISR wird alle 10ms aufgerufen, dass soweit schon richtig. Die Leds hab ich direk an PINA 0 - 2 angeschlossen und auf der anderen Seite mit einem 470Ohm Widerstand nach GND verbunden. Die Taster sind direkt mit PINB 0 - 2 verbunden und auf der anderen Seite mit GND verbunden.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
Nun Pumba? Der KEY0 fehlt in der Definition. Vielleicht solltest Du erstmal nur mit get_key_press() arbeiten. Wenn Du das verstanden hast, kannst Du die zeitabhängigen Taster-Funktionen einbauen, konfigurieren und auch nutzen. Ok ?
Die Pullups sind beim 841 bei PUE. Steht auch im Datenblatt. Bei mir hats damals funktioniert mit dem 841.
Gast
#3946269
Die key_press Variante macht auch nichts, ausser die Leds direkt auf HIGH zu setzen.
Versuch mal anstatt so
1 | |
das so zu machen
1 | |
Mathias dein Vorlag ist unsinning, wenn Du nicht weist wie der Code von PeDa funktioniert, dann rate bitte nicht. Mathias O. schrieb: > key_state ^ ~KEY_PINdas so zu machenkey_state ^ KEY_PIN
Jo er hat ja die Taster active low. Dachte die sind an VCC angeschlossen.
Gast
#3946309
Das mit der neuen Ansteuerung mit PUEx hatte ich bislang nicht gewusst. Laut dem Datenblatt werden die Pullups wie folgt gesetzt. PUEx |= (1<<PUEx1) | (1<<PUEx0); die einzelnen Bits PUEx0 sind im Atmel Studio nicht per defines gesetzt. Spielt aber keine Rolle. Da ich die auch mit 0, 1 etc machen kann. Jedoch geht es so wie ich mir gedacht habe nicht.
1 | |
2 | |
3 | |
Mit welchem Wert hast du F_CPU definiert? 2278?
Gast
#3946326
F_CPU ist 8MHz
Wo hängt dein Quarz dran? PB0 und PB1 sind doch XTAL.
Dann schreib mal 8000000UL bei F_CPU
Gast
#3946342
Der Takt ist hier NICHT das Problem! Das geht. Ob nun "8E6" oder "8000000UL" spielt keine Rolle. Quarz ist keiner im Einsatz. Ich arbeite mit der internen Oscillator. Der läuft mit 8MHz
Gast
#4062969
Das Atomisieren per cli(); sei(); finde ich ein wenig heftig. In meiner App läuft parallel ein anderer Interrupt, der alle 256 CPU cycles für ein paar Takte zuschlägt (soft PWM). Der würde regelmäßig und oft gekillt. Es geht ja nur darum, den Tasten - Debouncer für die Dauer der Tastenstatus Abfragen lahm zu legen. Andere Interrupts, die die Tastatur - Variablen nicht verändern, dürfen ja schadlos laufen ... od'r? Ich lösche / setze daher selektiv nur das Timer - Interrupt Enable Bit des 10ms Timers. Sollte - was sehr unwahrscheinlich, aber immerhin möglich ist - genau während dieser Sperre ein Timer Overflow eintreten, gibt's in der Tastatur (und nur dort) einen Glitch von 10ms ... das ist meiner Meinung nach vertretbar.
Servus, Wiso ein "Glitch von 10ms" ? Ich verstehe das Interruptsystem etwas anders: Wenn der Timerinterrupt wieder aktiviert wurde, was ja nur ein paar µs dauert, springt man sofort in Timer Interrupt Routine, wenn das Timer Interrupt Flag gesetzt ist. Klar können auch noch andere Interrupts mit höhere Priorität anstehen, die will ich jetzt nicht betrachten.
Gast
#4066389
@Uwe S Servus, wieder mal nachgelesen ... hast recht ... für den Fall, dass der 10ms key-Timer während der Atomexplosion überläuft (und das entsprechende Timer Interrupt Flag 0 ist) wird der Interrupt gespeichert und nach dem erneuten Setzen des Flags ausgeführt (in meinem Fall TIFR2.TOV2) Liebe Grüsse aus +/- Wien
Mario Sachse schrieb: > "Danke an Peter Dannegger für diesen tollen code und an alle die ihn > weiter verbessert haben!" auch ich möchte noch mal Danke sagen für diese Entprellroutine. Ich nutze sie im AVR, im Arduino mal zum Tasten entprellen, klappt sogar an einer I2C LCD Schnitte mit PCF8574 die ich für 8 Tasten nutze. Beschreibung, Timer Interrupt 64µs für IRMP wenn ein Counter auf 10ms hochgezählt hat wird in die I2C Tastaturabfrage gesprungen (100-200µs) dort wird ein Flag gesetzt das es ein langer IRQ wird, der Interrupt für IRMP wieder freigegeben und solange das Flag gesetzt ist am I2C Tastenabfragen vorbei gesprungen. Das Flag wird nur zurückgenommen wenn I2C wieder frei ist, der TWI Auftrag erledigt ist. So entgeht mir kein IRMP Befehl, kein Tastendruck. Für eine Laser Steuerung wo ausser den regulären 20Hz Impulsen mit 80µs Breite zur Lasertriggerung auch leider noch Fremdimpulse kommen unter 10µs und fremd triggern habe ich nun die IRQ auf 10µs gesetzt wie eine Tastaturabfrage und trigger den Laser nur noch wenn ein solider Trigger größer 40µs erfolgt. Getestet mit einem Arduino als Pulsgenerator, ich kann F und Trigerbreite schön einstellen und sehen wie PeDas Entprellroutine wirkt.
Gast
#4083576
Moin, ich nutze die Entprellroutine auf einem STM32F1 und habe bei einem Taster festgestellt, dass er häufiger nicht als gedrückt erkannt wurde. Die Funktion im IRQ wird alle 10ms aufgerufen und es gab keine atomic Blöcke in den Tastenfunktionen. Nun dachte ich mir, alle IRQs sperren ist etwas zu viel des Guten, es geht ja nur um das Auslesen der Tastenpins. Spricht etwas gegen folgenden Ansatz? In der debounce.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
in der Funktion die dann im IRQ aufgerufen wird:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
Das scheint schon deutlich besser zu funktionieren, ich habe aber den Eindruck, dass gelegentlich "kurze" Tastendrücke doch noch unerkannt bleiben. Bin mir aber nicht ganz sicher, ob es nicht evtl. die Entprellung ist. Eigentlich müsste aber ein gedrückter Taster deutlich länger dauern, als die Entprellzeit.
Hallo, bei den AVR µC kann man alle Interrupts Sperren und dann wieder freigeben, oder nur den zugehörigen Timer-Interrupt. Die Abarbeitung des Timer-Interrupts wird dann nach seiner Freigabe "sofort" nachgeholt. Und geht nicht 'verloren'. Bei deiner Realisierung in call_button_in_IRQ() geht aber dieser Interrupt verloren ! Also hier würde ich mal ansetzen.
Gast
#4083722
Hallo Uwe, danke für die Antwort. Interessanter Gedanke, das ergibt durchaus Sinn. Wie macht man das denn bei den STM32? Bei mir sorgt der SysTick für die 10ms Zeitbasis, aber das wird ja auch noch für andere Dinge benutzt und daher möchte ich das nicht aus dem Takt bringen. Je häufiger ich also Tastenabfragefunktionen benutze, desto häufiger würde der SysTick IRQ kurzzeitig gesperrt werden... Wenn ich über
1 | |
den SysTick IRQ in den Tastenabfragefunktionen ausschalte und kurz danach wieder anschalte, wird er vermutlich nicht nachgeholt.
Hallo Forumsmitglieder, ich habe mich schon versucht an den Codebeispielen für Microchip PIC Mikrocontroller aber ich scheitere leider beim Aufruf der Funktionen. Ich nutze 4 von 8 Pins des PORT A als Eingänge, der Rest sind Ausgänge. Compiler ist XC8 in Verbindung mit einem PIC16F628. Beim Aufruf der Funktion in meinem Main Programm gibt mir der Compiler zu verstehen dass er "KEY1" nicht kennt.
1 | |
2 | |
Die Fehlercodes lauten:
1 | |
1 | |
Gerne füge ich noch den Quellcode der "unbounce.c" diesem Post hinzu. Gruß Martin
Dave schrieb: > Nun dachte ich mir, alle IRQs sperren ist etwas zu viel des Guten, es > geht ja nur um das Auslesen der Tastenpins. Wenn Dein IRQ so extrem zeitkritisch ist, daß er nicht mal eine Verzögerung um 2 CPU-Befehle verträgt, dann hast Du weitaus größere Probleme.
So ich nochmal, nachdem ich den Fehler der richtigen Deklaration beheben konnte nun eine neue Herausforderung: Es sind 4 Taster am PIC angeschlossen an RA0, RA1, RA6 und RA7 (alle als Input in den TRISA Regsiter gesetzt, der Rest des PortsA ist als Output deklariert)). Die Entprellroutine funktioniert auch zu 50% denn nur die letzten beiden Taster RB6&7 werden ausgewertet. Ich bin leider etwas verunsichert ob ich etwas falsch gemachte habe daher hier dier Code in voller Schönheit. Nicht wunder, es handelt sich um einen Microchip PIC16F628. Hier der Inhalt der Headerdatei:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
Und hier nachfolgend die Funktionen:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
Irgendwie will der Fehler sich mir nicht offenbaren. Gruß
Um das Verhalten der "inneren" Variablen sowie der verschiedenen Abfrageroutinen mal genauer zu beobachten sowie damit zu experimentieren habe ich die ganze Routine mal in ein PC-taugliches C-Programm gewandelt. Vielleicht kann damit ja noch jemand was anfangen.
Hallo, ich verwendet die original Routine von Peter Dannegger und diese funktioniert perfekt. Bevor ich es für mein Projekt versuche, funktioniert die Routine auch, wenn man z.B. 3 PINs als Ausgang schaltet. Das bedeutet man wertet einen gesamten Port aus, der sowohl Ein als auch Ausgänge hat. Können(und wenn ja welche?) Probleme auftreten? Liebe Grüße
Wuhu W. schrieb: > funktioniert die Routine auch, > wenn man z.B. 3 PINs als Ausgang schaltet. ja Wuhu W. schrieb: > Das bedeutet man wertet einen gesamten Port aus, der sowohl Ein als auch > Ausgänge hat. aber das Ergebnis wird mit den definierten KEYs (Eingänge) oder bei der Abfrage *) verundiert, je nach dem ob high- oder low- aktiv, bei Abfrage auf high ver"unden", bei Abfrage auf low negiert ver"unden" *) ret_key=get_key_press( ALL_KEYS ); // welche Taste(n) will ich wissen?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
Wuhu W. schrieb: > Können(und wenn ja welche?) Probleme auftreten? Die Entprellung ist je Pin unabhängig. D.h. auch 7 Out-Pins sind dem einen In-Pin völlig wurscht. Nur die Maske für Repeat-Funktion will nur die aktiven Inputs sehen.
Gast
#4264010
http://www.compuphase.com/electronics/debouncing.htm Falls ihr immer noch Schwierigkeiten oder ein Brett vorm Kopf habt, lest euch die Erklärung im Link auch mal durch. Etwas kleinschrittiger. Ich habe etwas gebraucht (also nen guten halben Bleistift) an Hand des obigen Codes das Konzept nachzugehen. Man hat, glaub ich, einfach zuerst Probleme sich klar zu machen, was Peter wann als logisch '1' und '0' speichert (die internen Zustände und aktuellen Ports) und dass das Ding halt rückwärts zählt.
Gast
#4304589
Wenn es nur um das Entprellen geht, reicht es, wenn der Eingang in definierten Zeitintervallen (Timer-Int.) abgefragt wird, die größer sind als die max. Prellzeit. Beispiel: Der Taster wurde gedrückt und prellt noch während der 1. Abfrage. Möglichkeit 1: Er wird während des Prellens zufällig als "nicht gedrückt" erfasst. Nicht weiter schlimm: Er war vorher nicht gedrückt und wird nun eben für eine Intervall-Länge weiterhin als "nicht gedrückt" angesehen. Danach hat er ab der 2. Abfrage ausgeprellt und wird fortan statisch als "gedrückt" erfasst, solange er gedrückt bleibt. Möglichkeit 2: Er wird schon während des Prellens zufällig als "gedrückt" erfasst. Prima! Das war ja auch die Absicht beim Drücken. Bei den folgenden Abfragen hat er ausgeprellt und wird weiterhin statisch als "gedrückt" ausgewertet. Mehr Aufwand zum reinen Entprellen braucht's nicht. Alles darüber Hinausgehende dient nicht mehr dem Entprellen des Tasters, sondern der prophylaktischen Störunterdrückung von extern eingestreuten Spikes oder Bursts auf die mitunter langen Taster-Zuleitungen. Wo diese Störquellen ausgeschlossen werden können, reicht die Timer-Entprellung.
Gast
#4305178
Spart wieviele FLASH-/RAM-Bytes? Ganz abgesehen von der Implementierungs-/Fehlersuch-/Umbau(weils doch mehr Funktion braucht)-Zeit. Es gibt was, das tut was es soll, wozu also neues erfinden.
Gast
#4306059
@Bastler Es ging mir nur um die simple Betrachtung des reinen Entprellens, das bzgl. der Komplexität meist 'überkandidelt' interpretiert und "gelöst" wird. Dazu braucht es nicht eine einzige zusätzliche Codezeile. Die Eingangsabfrage muss ohnehin gemacht werden. Indem man diese in einen zeitlich passenden Timerinterrupt verfrachtet, ist das reine "Entprellungsproblem" gelöst, wie ich im vorigen Beitrag gezeigt habe. Dort wo diese reine Entprell-Funktionalität ausreicht, braucht man keine All-inclusive-Routine.
Gast
#4306115
Hallo Simpel, im rein mathematischen Sinn, hast Du leider nichts gezeigt. Anforderung, ich habe 8 Tastereingänge und möchte verschiedene Events von der Entprellroutine erhalten. 1) Wurde eine Taste gedrückt ? 2) Wurde eine Taste losgelassen ? 3) Ist eine Taste immer noch gedrückt (repeat pressed) ? 4) Wurde eine Taste nur kurz gedrückt ? Bitte schreibe, als Beweis, das Vorgegebene als Code deine bevorzugten Programmiersprache nieder.
Karl M. schrieb: > Bitte schreibe, als Beweis Was soll er beweisen? Denn Simpel schrieb: > Es ging mir nur um die simple Betrachtung des reinen Entprellens Mit seiner entsprechenden (simplen) Problemlösung hat er ganz recht, da brauchts doch nicht mehr (erwähnte fehlende Störeinstreuungen vorausgesetzt).
Gast
#4340410
Hallo, ich habe die Entprellung bei mir mit einem PIC implementiert, und sie funktioniert auch einwandfrei. Jetzt habe ich aber ein Problem weil ich einen zweiten Timer habe der alle 148 us aufgerufen wird. Mein Timer für den Entpreller ist auf 10ms gestellt. der zweite Timer hat eine höhere Priorität, aber selbst ohne die bringt er die Routine anscheinend so durcheinander das Tasten als gedrückt erkannt werden obwohl diese nicht gedrückt werden. Oder erst nach mehrmaligem schnellen drücken erkannt werden. Kann das an dem schnellen Timer liegen oder habe ich doch irgendwo in meinem Code mist gebaut? Sobald ich den Timer deaktiviere oder dessen Interrupt funktioniert alles.
Gast
#4340771
Ich kann meine Frage selber beantworten... Zitat datasheet: If both low-priority and high-priority interrupts are enabled, the Stack registers cannot be used reliably to return from low-priority interrupts. If a high-priority interrupt occurs while servicing a low-priority interrupt, the Stack register values stored by the low-priority interrupt will be overwritten. In these cases, users must save the key registers in software during a low-priority interrupt. Normalerweise erledigt das ja der Compiler. Natürlich unter der Voraussetzung das man richtig programmiert. Auszug aus dem C Compiler Handbuch: A high-priority interrupt uses the shadow registers to save and restore the minimal context, while a low-priority interrupt uses the software stack to save and restore the minimal context
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
Keine Ahnung ob das aus einem Beispiel kopiert wurde oder wo ich das her hatte, das Projekt liegt schon etwas länger in der Ecke. Wenn aber für beide Interrupts das gleiche Register zum speichern verwendet wird, tritt denke ich genau das ein was oben beschrieben wurde.
1 | |
2 | |
3 | |
4 | |
Das ist also korrekt. Und jetzt funktioniert es auch :)
Gast
#4471676
Hallo Peter! Deine Entprell-Routine nutze ich schon seit ein paar Jahren - vielen Dank dafür! Nun wollte ich die get_key_long() Funktion anwenden (zur Einstellung eines Zahlenwertes: kurzer Druck = +1, langer Druck = +10). Ergebnis: Ein langer Tastendruck wird zuverlässig erkannt. Bei einem kurzen gibt es leider nur eine Erfolgsquote von ca. 90%, d.h. etwa jeder 10te wird falsch als langer Tastendruck erkannt. Etwas verwirrt habe ich einen Attiny13A nur mit der Entprellroutine gefüttert, ein Knopf, zwei LEDs, 9,6MHz/8, verschiedene Werte für REPEAT_START und REPEAT_NEXT, aber dasselbe Problem. Hat jemand schon einmal Åhnliches beobachtet? Außerdem ist mir folgendes aufgefallen: Ich hatte den Sinn von REPEAT_NEXT so verstanden, dass ein weiterer langer Druck gezählt wird, wenn der Knopf nach Ablauf dieses Zeitintervalls immer noch gedrückt ist. Nun wird in der get_key_long() aber hier:
1 | |
key_press durch den Aufruf von get_key_press() gelöscht, und jeder folgende Aufruf von get_key_long() liefert 0, auch wenn in key_rpt das entsprechende Bit gesetzt ist. Mit
1 | |
wird es etwas besser, aber dann gibt's nach jedem langen Tastendruck einen kurzen "gratis", was wohl auch nicht der "Spezifikation" entspricht... Mir fällt aber nix ein, wie man dies ohne Einführung einer weiteren Variable lösen könnte.
Gast
#4471694
Folgender Code funktioniert bei mir einwandfrei:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
lg Chris
Gast
#4472189
Hallo Chris, OK, auch da wird natürlich ein langer Druck zusätzlich als kurzer gezählt - allerdings gleich am Anfang und nicht erst beim Loslassen. Das dürfte für den User besser einzuschätzen und komfortabler sein. Hast Du schon einmal das Problem mit "falsch-langen" gehabt (also einem kurzen Druck, der als langer erkannt wurde?) Mit welchem Takt arbeitest Du? Wieviele Interrupts generierst Du? In meiner "richtigen" Anwendung habe ich F_CPU = 1MHz. Ich brauche einen Millisekunden-Takt, den ich mit TIM0_COMPA generiere. Bei jedem 10. wird dann per
1 | |
2 | |
3 | |
4 | |
die Abfrage der Taster vorgenommen. Der Tiny13A zum Testen taktet geringfügig höher (9,6/8MHz).
Gast
#4472825
Hi, genau, der erste Tastendruck erhöht um 1 (bzw. erniedrigt in meinem Beispiel). Hält man weiter gedrückt, wird in 10er Schritten gezählt. Beim Loslassen passiert nichts. Ich führe die Tastenentprellung im Timerinterrupt alle 10 ms durch. Wenn ich auch einen ms-Takt brauche, stelle ich den Interrupt auf 1ms und zähle im Interrupt eine Variable bis 10 hoch. Die Entprellfunktion rufe ich direkt im Interrupt (als inline Funktion) auf.
AVR-Bastler schrieb im Beitrag #4471676: > Ergebnis: Ein langer Tastendruck wird zuverlässig erkannt. Bei einem > kurzen gibt es leider nur eine Erfolgsquote von ca. 90%, d.h. etwa jeder > 10te wird falsch als langer Tastendruck erkannt. Dann ist die Zeit für lang zu lurz. AVR-Bastler schrieb im Beitrag #4471676: > Ich hatte den Sinn von REPEAT_NEXT so verstanden, dass ein weiterer > langer Druck gezählt wird, wenn der Knopf nach Ablauf dieses > Zeitintervalls immer noch gedrückt ist. Das wird kompliziert, wenn man alle 3 Sachen machen will (kurz, lang, repepeat), nicht nur für den Bediener. Beitrag "Re: Universelle Tastenabfrage" Beitrag "Re: Universelle Tastenabfrage"
Gast
#4472853
AVR-Bastler schrieb im Beitrag #4472189: > if (!(msec % 10)) > { > debounce(); > ... Da fällt mir gerade auf: Wenn dieser Code bei dir in der Hauptschleife steht, kann er innerhalb einer Millisekunde öfter aufgerufen werden, wenn deine Schleifenlaufzeit kleiner als 1 ms ist. Weil die geprüfte Bedingung ja die ganze Zeit erfüllt ist, bis msec erhöht wird. Das würde das falsch-erkennen der langen/kurzen Tastendrücke erklären. Mach vielleicht besser einen Zähler, der bis 10 zählt und wieder auf 0 gesetzt wird. Dann wird wirklich nur jedes 10. mal die Entprellung durchgeführt.
Gast
#4473359
chris schrieb: > Da fällt mir gerade auf: > Wenn dieser Code bei dir in der Hauptschleife steht, kann er innerhalb > einer Millisekunde öfter aufgerufen werden, Das ist ein valider Punkt. - Danke! Ich dachte schon, das war's. Leider nein. Aber ich habe nun mit den Zeiten noch etwas gespielt. Wenn ich die debounce() alle 50ms aufrufe, funktioniert es. Dafür fallen dann sehr schnelle Tastendrücke hinten runter. Also kann ich mir aussuchen, ob ich am langen oder am kurzen (Zeit-) Ende Fehler habe. Ich denke, der Taster ist einfach schrottig.
Gast
#4473362
AVR-Bastler schrieb im Beitrag #4473359: > Das ist ein valider Punkt. - Danke! > Ich dachte schon, das war's. Leider nein. Wie sieht denn dein aktueller (vollständiger) Code aus?
Gast
#4473367
Hallo Peter, Peter D. schrieb: > Dann ist die Zeit für lang zu lurz. Ich habe die REPEAT_START schon auf 255. Aber danke für die get_key_long_r() und get_key_rpt_l(). Ich werde die morgen mal simulieren.
AVR-Bastler schrieb im Beitrag #4473359: > Wenn ich die debounce() alle 50ms aufrufe, funktioniert es. Das glaub ich Dir nicht. 50ms * 255 = 12,75s. Da mußt Du ja auf der Taste einschlafen für Langdruck. Also entweder Deine Zeitbasis stimmt nicht, Deine 50ms stimmen nicht oder Du hast in der Repeat-Maske Pins drin, die garnicht für Langdruck vorgesehen sind.
Gast
#4496786
Sorry - hab gerade "Land unter", da bin ich noch nicht wieder dazu gekommen. Deine Rechnung ist natürlich richtig, Peter. Deine Annahme, ich würde bei der Fehlersuche wahllos alle Parameter gleichzeitig ändern, natürlich nicht. Aber auch 255*10ms = 2,55s ist für einen Anwender zu lang. Trotzdem habe ich es damit mal versucht, einfach um herauszufinden, ob dieser Parameter das Problem löst. Hat er nicht.
Hi Peter, Ich habe Deinen Code jetzt integriert. Woran ich aber gerade grüble ist, dass das "get_key_long" bereits nach sehr kurzem "Lang-Drücken" des Tasters registriert wird. Ich habe in den Defines diesen Wert von 50 auf 100 geändert "#define REPEAT_START 100 " Da sich das Verhalten aber nicht ändert, nehme ich also an, dass ich an der falschen Stelle gedreht habe. Mein Ziel ist es, ein Lang-Drücken von etwa 2 Sekunden zu detektieren. Danke im Voraus Hannes
Johannes H. schrieb: > Da sich das Verhalten aber nicht ändert, nehme ich also an, dass ich an > der falschen Stelle gedreht habe. Du hast hier verschwiegen, dass Du noch woanders dran geschraubt hast, wie Du in folgendem Thread schreibst. Johannes H. schrieb: > Ebenso habe ich den Vorteilquotienten von 1024 auf 1600 gesetzt da ich > mit einem höheren Takt als in Deinem Beispiel arbeite. 1600? Zeig mal den Code, wie Du das gemacht hast.
Ja ertappt :) Also es geht um diese Zeile:
1 | |
Hab mir ausgerechnet, welcher Wert für 16MHz da ungefähr stehen muss, um 10ms zu erhalten-->1600
Johannes H. schrieb: > Hab mir ausgerechnet, welcher Wert für 16MHz da ungefähr stehen muss, um > 10ms zu erhalten-->1600 Dann schau Dir mal TCCR0 im Datenblatt und im Code an! Das wird auf den Teiler 1024 gesetzt. Diesen setzt Peter dann für TCNT0 wieder ein. Du kannst da nicht einfach 1600 hinschreiben. Den Teiler 1600 kann man (naturgemäß) gar nicht konfigurieren in TCCR0. Im Datenblatt stehen die gültigen Teiler. Wenn, dann solltest Du besser den Faktor 10e-3 korrigieren. Mit welcher Frequenz läuft Peters Code? 1MHz oder 8MHz? Dann überlege, wie Du ihn für 16MHz modifizieren musst. Im anderen Thread hatte Dich auch schon jemand darauf hingewiesen... aber offenbar hast Du das nicht verstanden ;-) Es kommt bei Peters Code gar nicht so groß auf die Zeiten an. Sie sollten jedoch zumindest größenordnungsmäßig passen. Das reicht in den meisten Fällen.
Ja den Vorteiler nicht, aber den Zählwert im TCNT-Register kann man doch beliebig setzen. Peters Code nutzt 1MHz, da habe ich mich um Faktor 10 verguckt. Also wird bei meinen 16MHz der Interrupt 16 Mal häufiger aufgerufen (wenn ich den Code so lasse), oder?
Johannes H. schrieb: > Peters Code nutzt 1MHz, da habe ich mich um Faktor 10 verguckt. > Also wird bei meinen 16MHz der Interrupt 16 Mal häufiger aufgerufen > (wenn ich den Code so lasse), oder? Peter hat das portabel formuliert für TCNT0: Er benutzt F_CPU. Wenn dieser bei Dir auf 16000000UL steht, dann ist alles bereits richtig. Der Wert (F_CPU / 1024 * 10e-3 + 0.5) wird dann automatisch 16 mal größer. Du brauchst also in der Regel nichts mehr anzupassen.
Ok, ja seh ich ein, da bin ich einem Denkfehler aufgesessen... Aber das ursprüngliche Problem dass "get_key_long" nach einer viel zu kurzen Zeit auslöst, besteht immer noch. Hast Du da noch eine Idee?
Gast
#4558174
Johannes H., bei mir funktioniert das alles, es liegt an deinem Programm. Wo ist das ?
Hallo, Da ist der Code:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
Den ganzen Debounce-Code habe ich eine separate c-Datei ausgelagert. Karl, wie stellst Du denn ein, nach welcher Zeit "get_key_long" auslöst?
Gast
#4563841
Johannes H. schrieb: > wie stellst Du denn ein, nach welcher Zeit "get_key_long" auslöst? Dort wo Du Repeat_Start definiert hast.
Ich habe mal versucht alle Funktionalitäten aus dem Thread zusammen zu tragen und in ein möglichst wiederverwertbares Modul zu packen. Vielleicht kann es jemand brauchen. Die verwendete cm_atomic.h ist unter folgendem Link zu finden: Beitrag "Re: atomic-lib für stm32"
Gast
#4591319
Hallo Michael ! und hier ist schon der erste Fehler !
1 | |
2 | |
Dieser Wert ist direkt abgängig von dem Pollintervall !
Dass die Werte vom Pollintervall abhängen ist klar, aber warum soll das dann gleich falsch sein? Mag ja sein, dass du recht hast, verstehen tue ich es aber nicht. Zugegebenermaßen habe ich die Repeat-Geschichten aber auch noch nie genutzt, sondern einfach so übernommen. Daher ist es sehr wahrscheinlich, dass ich den entsprechenden Beitrag nicht gelesen habe.
Lieber Herr Dannegger, Vielen Dank! Der Code arbeitet sofort und perfekt! Ich sollte nur am Anfang für mehr Freiheit mit Pins für die Tasten etwas anpassen:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
usw. mit entsprechenden
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
Auch REPEAT_NEXT habe ich auf 10 gesetzt, aber das ist wohl eine Geschmackssache. Vielen Dank für diese Möglichkeit!
Gast
#4890714
Hallo, ich würde meine C Kenntnisse als sehr bescheiden bezeichnen. Dennoch versuche Ich gerade den Code aus Beitrag "Universelle Tastenabfrage" zu verstehen. Ich verstehe den Sinn folgender Anweisung nicht ... ct0 = ~( ct0 & i ); Unmittelbar zuvor wird der Wert von ct0 initialisiert. static uint8_t ct0 = 0xFF, ct1 = 0xFF, rpt; Wenn nun ct0 mit 0xFF initialisiert wurde und ein bitweises und mit i erfolgt, dann kann das Ergebnis doch immer nur gleich dem Wert von i sein. Oder? Demzufolge wäre doch ct0 ~= i; doch viel kürzer und einfacher zu verstehen. Wo liegt mein Denkfehler? Gruß Henning
Gast
#4890726
Guten Mittag, in der Deklaration der Variable und ihre "Reichweite".
1 | |
Gast
#4890738
Hallo, was möchtest du mir damit sagen? Input please ... Im Beitrag zur Entprellung steht nichts von static uint8_t ct0; sondern static uint8_t ct0 = 0xFF, ct1 = 0xFF, rpt; Bedeutet das, das der Wiki Beitrag, der den Anfängern ja erklären soll wie es funktioniert, fehlerhaft ist? Dann sollte das umgehend von einem "Wissenden" korrgiert werden... Gruß Henning
Gast
#4890771
Henning schrieb: > Hallo, > > was möchtest du mir damit sagen? > Input please ... > > Im Beitrag zur Entprellung steht nichts von > static uint8_t ct0; > > sondern > static uint8_t ct0 = 0xFF, ct1 = 0xFF, rpt; > > Bedeutet das, das der Wiki Beitrag, der den Anfängern ja erklären soll > wie es funktioniert, fehlerhaft ist? Grundlagen! Das "static" sorgt dafür, dass die Variable nur ein Mal initialisiert wird, und nach dem Verlassen der Funktion aber immer noch besteht (ähnlich einer globalen Variable, nur dass der Zugriff auf diese nur innerhalb dieser Funktion erfolgen kann. Würde es fehlen, würde die Variable bei jedem Funktionsaufruf neu initialisiert werden. Ob da nur eine defklariert wird, oder fünf, ist dabei egal.
Gast
#4890773
Die Antwort von Karl war schon richtig aber du hast nicht darüber nachgedacht. https://de.wikibooks.org/wiki/C-Programmierung:_static_%26_Co. >> Unmittelbar zuvor wird der Wert von ct0 initialisiert. Deine Annahme stimmt nur für das erste Mal.
Gast
#4890788
Ahhh, jetzt hab ich's. Habe aus Karl's erster Antwort einfach nicht entnehmen können, das es um das Wörtchen "static" in der Variablendeklaration geht... Jetzt ist mir natürlich klar, das meine Schlussfolgerungen Unsinn waren. Vielen Dank für die Erleuchtung. Henning
Hallo Peter & Andere, Ich bin bei der Anwendung Der Entprellroutine in meiner Anwendung auf ein Problem gestoßen: Mittels "Kurz Drücken" eines Tasters werden verschiedene Modi durchgeschaltet, sprich ein index inkrementiert. Mittels "Lang Drücken" desselben Tasters wird der µC mit Deiner "try_sleep"-Funktion schlafen gelegt und mittels Level Change Interrupt wieder aufgeweckt. Jetzt habe ich das Problem, dass beim Aufwecken auch gleichzeitig ein "Kurz Drücken" detektiert wird und damit der nächste Modus ausgewählt wird, was nicht erwünscht ist. Leider habe keine Möglichkeit gefunden, während der Aufwachphase, das "get_key_short" temporär zu deaktivieren. Siehst Du/ihr eine Möglichkeit? Danke & Gruß
Gast
#4892791
Johannes H. schrieb im Beitrag #4892788 > Leider habe keine Möglichkeit gefunden, während der Aufwachphase, das > "get_key_short" temporär zu deaktivieren. Siehst Du/ihr eine > Möglichkeit? Dann mach das doch in der Einschlaf-Phase. Also deinen Index um 1 verringern, so dass er nach dem Aufwecken und dem "get_key_short" wieder stimmt.
Hi Edson, Ja das funktioniert, dass ich darauf nicht gekommen bin :) Aber ich suche noch nach der eleganten Lösung. Den Index zu verringern ist ja nur ne Art Workaround. Hast Du schon mit Peters Debounce Algorithmus gearbeitet?
Hi, bin jetzt mit dem Workaround an eine weitere Grenze gestoßen und muss nun eine andere Lösung finden. Ich hatte gerade probiert, beim Einschlafvorgang einfach den Timer 0 Interrupt zu deaktivieren und eine kurze Zeit nach dem Aufwachen wieder zu aktivieren, da hängt sich das Programm aber irgendwo auf :( Peter/Edson, was für Optionen fallen euch denn noch ein?
Johannes H. schrieb: > Leider habe keine Möglichkeit gefunden, während der Aufwachphase, das > "get_key_short" temporär zu deaktivieren. Siehst Du/ihr eine > Möglichkeit? https://www.mikrocontroller.net/attachment/115266/Knightrider2.zip
1 | |
2 | |
3 | |
Hallo Peter, Nein das funktioniert leider nicht :( Es wird weiterhin nach dem Aufwachen das kurze Drücken detektiert.
Hallo! Horst hatte ja schon mal in seinem Beitrag Beitrag "Re: Universelle Tastenabfrage" angefragt, wie man die Repeat-Funktion nicht nur für eine Taste, sondern für alle Tasten unabhängig hinbekommt. Ein Szenario dafür ist z. B. ein Tastmodul mit acht Eingängen, an die Taster in acht verschiedenen Räumen angeschlossen sind. Ich dachte mir, dass man dafür einfach einen weiteren vertikalen Zähler verwenden könnte, dann allerdings z. B. 3-bit oder sogar noch breiter. Den Code stelle ich mir so vor:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
Die restlichen Funktionen sind identisch wie von Peter geposted. Nur leider funktioniert das bei mir so nicht. Einige Tasten werden sofort bei get_key_short erkannt, andere sofort bei get_key_long. Zwischendurch ändert sich das mal. Keine der Tasten ändert beim länger drücken ihren Repeat-Status. Wie müsste die Timer-Routine richtig aussehen und wie wäre die korrekte Erweiterung für einen 4- bzw. 5-bit vertikalen Counter?
Ich muss mich korrigieren. Der von mir gepostete Code funktioniert genauso, wie gewünscht. Problem war nur, dass ich ihn gleich in Assembler implementiert und sich da ein Fehler eingeschlichen hatte. Im Beitrag hatte ich für mich als Kontrolle die C-Version geschrieben. Ein weiteres Problem war das Timing. Ein 3-bit vertical counter ist doch bisl arg wenig. Nun schwanke ich zwischen eine 4-bit oder 5-bit vertical counter. Der 4-bit gefällt mir momentan am besten. Das Schema zur Erweiterung um weitere Bits ist übrigens recht simpel und offensichtlich:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Mathias W. schrieb: > Problem war nur, dass ich ihn gleich in > Assembler implementiert und sich da ein Fehler eingeschlichen hatte. Magst Du diesen Code auch mal veröffentlichen? Dann bräuchte ich mir nicht die Mühe machen, die Komfortroutine in Assembler zu übertragen. Die Kurz-Lang Erkennung wäre für mich wichtig.
Falls man bis zu 64 vertikale Zähler beliebiger Breite (besser: Höhe) braucht, kann man das folgende template VCounter nehmen. Es ist genau der gleiche vertikale Zähler mit impliziter Rücksetzung. Vorteile: - vollkommen generisch - gekapselt Nachteile: - C++ mit TMP - ein paar Zeilen Code in Header-Datei Ist also der direkte Ersatz für ct0, ct1, ct2, ... im originalen Code.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
Gast
#6106509
Im Original Code von Peter Danneger wird die Globale Variable: volatile uint8_t key_state; deklariert aber im Code finde ich keine Startinitialisierung. in der ISR finden dann auch gleich eine Bitoperation damit statt. Da die Variable keine Initialisierung hat, nehme ich an das der undefinierte Zustand für den Start bewusst in kauf genommen wird? Stimmt das? MfG Elias
EliasH schrieb: > Im Original Code von Peter Danneger wird die Globale Variable: > volatile uint8_t key_state; globale variable -> zero-initialized C-Buch oder hier: https://en.cppreference.com/w/c/language/initialization
Gast
#6767499
Hallo Versuche die Tasterabfrage in meinen Atmega 8 zum laufen zu bekommen. Es geht so weit alles, komme nur mit der Nutzung der Tasten durcheinander. Es sthet drin: - get_key_press() - get_key_rpt() - get_key_press() mit get_key_rpt() - get_key_short() mit get_key_long() - get_key_short() mit get_key_long_r() und get_key_rpt_l() Leider komme ich mit der Bezeichnung und der Nutzung nicht klar. Die Beschreibungen sind alle relativ kurz geraten. Welche Taste macht was wann und mit welcher?
Gast
#6767517
Hallo, Sollte man dann ich das Programm "befragen" und den Code der Basisfunktionen verstehen? Als Tipp, alle genannten Funktionen bekommen ein Bitmaske der Keys übergeben.
Gast
#6767560
Das habe ich getan. Kann mit einer Taste einschalten mit einer anderen aus, kurz einschalten mit lang ausschalten das geht alles und klar. Was mach ich aber damit: get_key_short() mit get_key_long_r() und get_key_rpt_l() Es werden 3 Tasten angegeben. Das ist mir unklar.
Gast
#6767590
Hallo, ich habe noch ein paar Links für dich: Beitrag "Re: Universelle Tastenabfrage" Über dieses Bild / Diagramm sollte sich einiges Aufklären. Beitrag "Problem mit Tasterentprellung" https://www.mikrocontroller.net/articles/Entprellung Dann hängt es immer noch davon ab, wie also durch wen das Programm implementiert wurde. Stichwort: Fehler im eigenen Code und Codetests.
Gast
#6767592
Von meiner Seite aus, hatte ich die Basiscode von Peda (Peter Dannegger), Codeteile und die Funktionsnamen in Assembler unter LunaAVR implementiert. Dann auf beliebige Ports noch erweitert, so dass man über die Hochsprache LunaAVR auch einfach zwei oder drei 8 Bit Ports entprellen kann.
Gast
#6767831
Hallo Karl M. Habe deinen Rat befolgt und die Artikel von Peter durchgelesen. Muss ganz ehrlich sein, das ist für mich ein ganzes Stück zu hoch. Da reichen meine Verständnisse in C nicht aus. Habe parallel dazu auf meinem Atmega 8 das Programm installiert und verschiedene Versionen geteste. Mit if(get_key_press(1<<KEY_1)) kann ich die LED ohne Probleme ein und mit if(get_key_press(1<<KEY_2)) ausschalten. Das geht. Leider erschliesst sich die Nutzung, wie Peter sie beschreibt gar nicht. Such jetzt nach der Funktion, mit Taster kurz drücken einschalten, mit Taster lang drücken ausschalten. Dachte das diese Funktion ist get_key_short() mit get_key_long(), geht aber nicht. Da ist wohl noch ein grosse Denkfehler von mir drin.
Gast
#6767873
Habe das nächste in den Griff bekommen. Es funktioniert jetzt auch get_key_short und get_key_long Bedienung mit einem Taster ein und aus. Hatte den Timer falsch eingestellt.
Gast
#6767910
Ich entprelle hardwaremäßig
Gast
#6767916
Was macht das get_key_release
Gast
#6768045
Steffen schrieb: > Was macht das get_key_release Guck mal in den C-Code 😉
Gast
#6768378
Heiner schrieb: > Guck mal in den C-Code 😉 Das habe ich gemacht. Leider reichen meine Kenntnisse von C dazu nicht aus. Den Ablauf verstehe ich nicht (muss ich das?). Möchte den Code anwenden und dazu zählt für mich die Nutzung der Tasten.
Gast
#6768730
Steffen schrieb: > Heiner schrieb: >> Guck mal in den C-Code 😉 > > Das habe ich gemacht. Leider reichen meine Kenntnisse von C dazu nicht > aus. Den Ablauf verstehe ich nicht (muss ich das?). Möchte den Code > anwenden und dazu zählt für mich die Nutzung der Tasten. Damit wirst Du nicht weit kommen - was wirst Du machen, wenn etwas nicht funktioniert ( und dieser Fall wird so sicher eintreten wie das Amen in der Kirche 😉) - wieder hier laut um Hilfe rufen? Allein die Frage “muss ich das?” zeigt Deine Unfähigkeit und die Ignoranz.
Gast
#6773683
Steffen schrieb: > Leider reichen meine Kenntnisse von C dazu nicht > aus. Den Ablauf verstehe ich nicht (muss ich das?). Der Ablauf ist unter C etwas kreativer als außerhalb. Wenn du nur Hochsprachen kennst dann wäre ein Konzept: Tasten (Fernbedienung/Kabel) senden Ereignisse: A_down, A_repeat, A_up_kurz, A_up_lang an die Anwendung wesentlich einfacher (Tastatur-Treiber u.U. eher in einfachen assembler).
Gast
#6773998
Steffen schrieb: > Was macht das get_key_release Signalisiert das Loslassen der Taste, wie der Name schon suggeriert. Siehe die Grafiken unter Beitrag "Re: Universelle Tastenabfrage"
Gast
#7117288
Guten Abend, ich möchte die Entprellroutine als Teil einer nicht kommerziellen studentischen Projektarbeit verwenden. Die Funktionen habe ich in eine Source Datei und die Defines, Variablen und Prototypen in eine Header Datei geschrieben. Mit den Funktionen frage ich in meinem Programm ein paar Taster ab. Als Kommentar habe ich am Anfang beider Dateien geschrieben:
1 | |
2 | |
3 | |
4 | |
Wäre das so ausreichend gekennzeichnet oder gibt es für (diesen) Programmcode auch sowas wie eine GNU Lizenz? Hat da jemand Informationen zu oder von Herrn Dannegger diesbezüglich etwas gelesen? Ansonsten muss ich mal meinen Betreuer fragen ob sowas in Ordnung ist und wie das gekennzeichnet werden muss. Mit freundlichen Grüßen
Gast
#7117346
Daniel N. schrieb: > Hat da jemand Informationen zu oder von Herrn Dannegger diesbezüglich > etwas gelesen? Frag ihn einfach, er ist aktiv hier https://www.mikrocontroller.net/user/show/peda
@Daniel N. Ja, kannst Du so machen.
Falls man long und repeat parallel auf Tastern nutezen möchte hier meine erweiterung im Timer Interrupt
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.