Hallo. Hilfe - bin verzweifelt, da ich ordentliche Entprellung nicht hin bekommen... ENTPRELL() gibt dauerhaft "0" zurück - aber warum? #define ENTPRELL( port, pin ) /* von Peter Dannegger */ \ ({ /* aktiv-high-Eingang */ \ static uint8_t flag = 0; \ uint8_t i = 0; \ if( flag ){ \ for(;;){ \ if( (port & 1<<pin) ){ \ i = 0; \ break; \ } \ _delay_us( 98 ); \ if( --i == 0 ){ \ flag = 0; \ i = 0; \ break; \ } \ } \ }else{ \ for(;;){ \ if( !(port & 1<<pin) ){ \ i = 0; \ break; \ } \ _delay_us( 98 ); \ if( --i == 0 ){ \ flag = 1; \ i = 1; \ break; \ } \ } \ } \ i; \ }) int main(void) { DDRB &= ~(1<<PB2); // Eingang, Taste DDRA |= ((1<<PA1)|(1<<PA2)); // Ausgang, LED_F, LED_HL // LED_HL_ON, LED_HL_OFF sind Macros, die gut funktionieren while(1) // nur um Tastenrückgabe zu testen { while ((ENTPRELL(PINB,PB2))==1) LED_HL_ON; // auf 1 abfragen while ((ENTPRELL(PINB,PB2))==0) LED_HL_OFF; // aus 0 abfragen }
Nicht abkupfern was nicht funktioniert oder was du nicht verstehst. Nachdenken und selbst schreiben und vor allem: nicht jammern.
Ich würde den Test so formulieren :
1 | while (1) /* nur um Tastenrueckgabe zu testen */ |
2 | {
|
3 | if ((ENTPRELL(PINB, PB2)) != 0) |
4 | {
|
5 | LED_HL_ON; /* bei 1 */ |
6 | }
|
7 | else
|
8 | {
|
9 | LED_HL_OFF; /* bei 0 */ |
10 | }
|
11 | }
|
Probier mal, was dann passiert. Wenn's immer noch nicht geht, probier nochmal ohne Entprellung :
1 | while (1) /* nur um Tastenrueckgabe zu testen */ |
2 | {
|
3 | if ((PINB & (1<<PB2)) != 0) |
4 | {
|
5 | LED_HL_ON; /* bei 1 */ |
6 | }
|
7 | else
|
8 | {
|
9 | LED_HL_OFF; /* bei 0 */ |
10 | }
|
11 | }
|
Nicht dass Dir Deine Hardware ein Ei ins Nest legt. Danach kann man mal in den Tiefen des Makros kramen...
__Son´s B. schrieb: > DDRB &= ~(1<<PB2); // Eingang, Taste Pullup vergessen (lies mal im Artikel nach) Und was sagt Dir "Wenn das Makro für die gleiche Taste (Pin) an mehreren Stellen aufgerufen werden soll, muss eine Funktion angelegt werden, damit beide Aufrufe an die gleiche Zustandsvariable flag auswerten [1]: " mit diesem Beispiel:
1 | // Hilfsfunktion
|
2 | uint8_t debounce_C1( void ) |
3 | {
|
4 | return debounce(PINC, PC1); |
5 | }
|
6 | |
7 | // Beispielanwendung
|
8 | int main(void) |
9 | {
|
10 | DDRB |= 1<<PB2; |
11 | DDRB |= 1<<PB3; |
12 | DDRC &= ~(1<<PC1); |
13 | PORTC |= 1<<PC1; // Pullup für Taster |
14 | |
15 | for(;;){ |
16 | if( debounce_C1() ) // nicht: debounce(PINC, PC1) |
17 | PORTB ^= 1<<PB2; |
18 | if( debounce_C1() ) // nicht: debounce(PINC, PC1) |
19 | PORTB ^= 1<<PB3; |
20 | }
|
21 | }
|
fop schrieb: > Ich würde den Test so formulieren : Danke für deine konstruktive Rü.! Deine Vorschläge decken sich mit meinen Versuchen. Hardware iO, mit dem Macro ENTPRELL() stimmt etwas nicht. Dieter F. schrieb: > Pullup vergessen (lies mal im Artikel nach) "aktiv-high" wie beschrieben, daher ext.10k-Ableitwid. Dieter F. schrieb: > Und was sagt Dir Das Problem steckt im Macro, nicht im Aufruf. Dein Versuch funktioniert genau so wenig! Harald schrieb: > Nicht abkupfern was nicht funktioniert oder was du nicht verstehst. > Nachdenken und selbst schreiben und vor allem: nicht jammern. ...zu blöde, daher...ohne herablassenden Kommentar...
@TO: kein Gemecker, sondern gutgemeinter Hinweis: Wenn du jede Zeile, also den gesamten Quelltext an den linken Seitenrand schiebst, ist der Text schlecht lesbar. Deshalb bitte in Zukunft formatieren und in code-Tags einschließen. Ok? Gruß Erwin
__Son´s B. schrieb: > ENTPRELL() gibt dauerhaft "0" zurück - aber warum? Natürlich, weil debounce beim Tastendruck nicht "rastet" __Son´s B. schrieb: > while ((ENTPRELL(PINB,PB2))==1) LED_HL_ON; // auf 1 abfragen > while ((ENTPRELL(PINB,PB2))==0) LED_HL_OFF; // aus 0 abfragen > } debounce entprellt! Das bedeutet, dass es keinen festen Zustand einnimmt und auch so bleibt! Durch das debounce wird der Zustand auf 1 gesetzt und dann wieder auf 0. probiere folgendes:
1 | if(debounce(PINB,PB2)) LED_HL ^= 1 |
2 | |
3 | if(LED_HL==0){ |
4 | LED_HL_ON; |
5 | }else |
6 | LED_HL_OFF; |
So in der Art!
:
Bearbeitet durch User
__Son´s B. schrieb: > mit dem > Macro ENTPRELL() stimmt etwas nicht. Wenn Du daran nichts geändert hast, dann stimmt es auch. Der Code wurde auf dem STK500 getestet. Du kannst Dir aber das Leben erheblich erleichtern, wenn Du mal den Link auf das Original posten würdest. Und da ist bestimmt auch beschrieben, was das Macro macht und auch ein Beispielcode dabei. Der sah garantiert nicht so aus, wie Dein obiger Code. Zu erwarten, daß jeder erstmal nach dem Original suchen soll, ist grob unhöflich. Ich hab jedenfalls nicht die Zeit dazu. Oder weißt Du noch alles genau, was Du die letzten 20 Jahre irgendwo mal gepostet hast?
:
Bearbeitet durch User
Peter D. schrieb: > Zu erwarten, daß jeder erstmal nach dem Original suchen soll, ist grob > unhöflich. Originalcode; https://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#Tasty_Reloaded
Frage: 1. Hattest du meinen Codeschnippsel mal getestet? 2. Willst du beim gedrückthalten der Taste LED_HL_ON auslösen und beim loslassen der Taste LED_HL_OFF auslösen?
Dominik K. schrieb: > debounce entprellt! > Das bedeutet, dass es keinen festen Zustand einnimmt und auch so bleibt! > Durch das debounce wird der Zustand auf 1 gesetzt und dann wieder auf 0. DANKE - genau das war mein Denkfehler! Mit einer Toggle-Anweisung klappts prima.
Dominik K. schrieb: > 2. Willst du beim gedrückthalten der Taste LED_HL_ON auslösen > und beim loslassen der Taste LED_HL_OFF auslösen? Genau das ist der nächste Schritt. Und danach den Flankenverlauf. Rückgabe von i dann; 0...Eingang X/Taste low 1...Eingang X/Taste high 2...Eingang X, Flanke ansteigend 3...Eingang X, Flanke abfallend
__Son´s B. schrieb: > DANKE - genau das war mein Denkfehler! > Mit einer Toggle-Anweisung klappts prima. Dachte ich mir! ;) Das macro funktioniert nämlich ganz gut.
Dominik K. schrieb: > Dachte ich mir! ;) > Das macro funktioniert nämlich ganz gut. Durch die Änderung von i=0 auf i=2 (Quelle: https://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#Tasty_Reloaded , untere Bemerkung) habe ich alle Rückgabewerte zur Weiterverarbeitung.
__Son´s B. schrieb: > Und danach den Flankenverlauf. Rückgabe von i dann; > 0...Eingang X/Taste low > 1...Eingang X/Taste high > 2...Eingang X, Flanke ansteigend > 3...Eingang X, Flanke abfallend Einfacher gesagt als getan. Aus dem Macro kann nur ein Wert zurück gegeben werden "i". Derzeit ist i=1=ansteigende Flanke, i=2=abfallende Flanke. (1) Nun könnte ich die beiden Rückgabewerte austauschen i=3=Taste high, i=4=Taste low. (2) Auch könnte ich eine Zeitstufe i=1, 5ms später i=3, i=2, 5ms später i=4 einsetzen. Blöde Sache mit der 5ms-Zeitverschwendung. (3) Oder die Zustandänderung in eine Funktion auslagern. Habt jemand eine bessere Idee?
Nunja, es ist nunmal ein macro für Taster und nicht für Schalter! Entweder tauscht du deinen Taster gegen einen Schalter aus oder du setzt ein Flag. Also eine Variable togglen so wie oben beschrieben. Dann kannst du einen Taster verwenden. Was genau hast du denn vor??? Ich dachte du willst einfach nur pro Tastendruck zwischen LED_HL_ON und LED_HL_OFF umschalten?
Dominik K. schrieb: > Was genau hast du denn vor??? > Ich dachte du willst einfach nur pro Tastendruck zwischen LED_HL_ON und > LED_HL_OFF umschalten? Ich möchte dieses Entpreller-Macro, als Basisbaustein (All-In-One) so umbauen, dass es zukünftig für alle Gelegenheiten zur Eingangskontrolle her halten kann. Egal ob irgend wann nur eine Flanke, oder der Tasten-/Schalterzustand benötigt wird. Ob nur eine Taste, oder mehrere Taster/Schalter innerhalb eines Programms verwendet werden. So komme ich im Laufe der Zeit zu guten+stabilen Universal-Modulen, die ich nur noch Einfügen muss. Kleinen Mini-Anpassungen -> FERTIG!
Folgendes klappt schon mal fehlerfrei; int main(void) { ... // div.Deklarationen if ((ENTPRELL (PINB, PB2)) == 1) Sprung = 1; // Taste_gn, Flanke ansteigend if ((ENTPRELL (PINB, PB2)) == 2) Sprung = 2; // Taste_gn, Flanke abfallend if ((ENTPRELL (PINB, PB1)) == 1) Sprung = 3; // Taste_rt, Flanke ansteigend if ((ENTPRELL (PINB, PB1)) == 2) Sprung = 4; // Taste_rt, Flanke abfallend switch(Sprung) { case 1: LED_GN_ON; //Led_gn on == Flanke ansteigend break; case 2: LED_GN_OFF; //Led_gn off == Flanke abfallend break; case 3: LED_RT_ON; //Led_rt on == Flanke ansteigend break; case 4: LED_RT_OFF; //Led_rt off == Flanke abfallend break; }} Auch mit mehreren Tasten, nur nicht bei zeitgleicher Zustandveränderung.
__Son´s B. schrieb: > Hilfe - bin verzweifelt, da ich ordentliche Entprellung nicht hin > bekommen... ...dann fang an, mal _selber zu denken, anstatt blind irgendwelchen Fremdcode in deine Projekte zu kopieren. Ich hab die Prinzipien hier in diesem Forum schon so oft den diversen Leuten erläutert, irgendwann mutiert die eigene Zunge zum Fransenteppich... Zur Not guck in die Quellen der Lernbetty, da kannst du sehen, wie man ein paar Dutzend Tasten zuverlässig entprellt und dran etwas lernen. Dazu war die nämlich da. W.S.
__Son´s B. schrieb: > if ((ENTPRELL (PINB, PB2)) == 1) Sprung = 1; // Taste_gn, Flanke > ansteigend > if ((ENTPRELL (PINB, PB2)) == 2) Sprung = 2; // Taste_gn, Flanke > abfallend Du hast das Makro immer noch nicht verstanden, es darf je Taste nur an einer Stelle aufgerufen werden! Bei 2 Aufrufen wird völlig unnütz doppelter Code erzeugt, d.h. Du entprellst die selbe Taste zweimal nacheinander. Es kann daher passieren, daß der 1. Aufruf 1 und der 2. Aufruf 2 ergibt, und somit Dein Code den 1. Aufruf überschreibt. Willst Du den Returnwert auf verschiedene Werte testen, schreib ihn eine Variable oder werte ihn mit switch/case aus. Für eine Lib, die auch für größere Projekte verwendbar sein soll, ist allerdings die Interruptlösung eindeutig vorzuziehen. Sie verwartet keine Laufzeit und verliert auch keine Tastendrücke, wenn die Mainloop etwas mehr zu tun hat. Die Makrolösung sollte man nur für kleine Projekte benutzen, die z.B. auf einem ATtiny13 laufen.
Peter D. schrieb: > Bei 2 Aufrufen wird völlig unnütz doppelter Code erzeugt, d.h. Du > entprellst die selbe Taste zweimal nacheinander. > Es kann daher passieren, daß der 1. Aufruf 1 und der 2. Aufruf 2 ergibt, > und somit Dein Code den 1. Aufruf überschreibt. Danke für Info! Vorerst hatte ich den Entprellaufruf über eine Funktion pro Taste aufgerufen, hatte diesen dann aber weg rationalisiert, da der direkte Aufruf gut klappt(e). Ev. doch nur Zufall... Peter D. schrieb: > Für eine Lib, die auch für größere Projekte verwendbar sein soll, ist > allerdings die Interruptlösung eindeutig vorzuziehen. Sie verwartet > keine Laufzeit und verliert auch keine Tastendrücke, wenn die Mainloop > etwas mehr zu tun hat. "Interrupt" - als Anfänger eher "abschreckend" - warum auch immer... Werde mich dieses Jahr damit auseinander setzen, da es ein mächtiges Werkzeug dar stellt - gerade bei reaktionskritischen Änderungen.
__Son´s B. schrieb: > Peter D. schrieb: >> Für eine Lib, die auch für größere Projekte verwendbar sein soll, ist >> allerdings die Interruptlösung eindeutig vorzuziehen. Sie verwartet >> keine Laufzeit und verliert auch keine Tastendrücke, wenn die Mainloop >> etwas mehr zu tun hat. > > "Interrupt" - als Anfänger eher "abschreckend" - warum auch immer... > Werde mich dieses Jahr damit auseinander setzen, da es ein mächtiges > Werkzeug dar stellt - gerade bei reaktionskritischen Änderungen. Du brauchst nicht unbedingt einen Interrupt, sondern Du musst die Entprellroutine nur mit einer konstanten Rate aufrufen. Im simpelsten Fall würde man einfach die entsprechenden Timerflags dazu verwenden.
__Son´s B. schrieb: > "Interrupt" - als Anfänger eher "abschreckend" ich bin ja auch kaum über Anfänger hinausgekommen. Interrupt ist einfach, ich mache einen 10ms Timerinterrupt um da Tasten zu entprellen (Dannegger), oder IRMP von Frank(ukw) 64µs z.B. da zähle ich eine Hilfsvariable bis ich wieder bei 10ms bin um die Tasten nach Dannegger auszuwerten. oder per Drehencoder Auswertung Interupt alle 1ms, Drehencoder (auch Dannegger) bis 10 zählen Tasten auswerten. Die Tasten wenn alle auf einem Port liegen können es 8 Tasten gleichzeitig sein, wenn nicht schiebt man Tasten Bits von Port A Port B Port C eben in ein Hilfs Byte welches dann ausgewertet wird und wertet wieder 8 Tasten aus 3 Ports aus.
:
Bearbeitet durch User
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.