Datum:
Angehängte Dateien:Bei der bekannten Super-Duper-Lösung haben Anfänger oft das Problem, sie zu verstehen, da das Vertikal-Counter Prinzip nicht so offensichtlich ist. Außerdem haben Anfänger oftmals Angst vor Interrupts. Man sieht ja oft die abenteuerlichsten Konstrukte, die mehr rein zufällig funktionieren. D.h. wenn man sie in weiteren Projekten benutzen will, gibt es plötzlich das große Staunen, weil eine vermeintlich fertige Lösung nun rumzickt. Manchmal wird auch nur das Loslassen gemeldet. Man stelle sich mal vor, die S-Bahn Tür würde erst bei Loslassen der Öffnungstaste öffnen. Der Griff zur Notbremse ist damit vorprogrammiert. Hier nun eine Lösung, die deutlich einfacher gestrickt ist, d.h. gut zu verstehen. Daher kann sie natürlich nicht so leistungsfähig sein. Aber die meisten Frickellösungen wird sie trotzdem weit in den Schatten stellen. Da sie keinen Interrupt benutzt, gibt es eine Einschränkung dahingehend, daß sie pro Drücken und Loslassen mindestens einmal aufgerufen werden muß, sonst geht die Betätigung verloren. Ansonsten ist die Wirkungsweise identisch: Man hat ein Flag, wo gemerkt wurde, ob vorher Losgelassen oder Gedrückt erkannt wurde. Und dieses Flag entscheidet nun, ob die entgegengsetzte Betätigung entprellt werden muß. Damit vermeidet man unnötige Wartezeiten, wenn die Taste länger gedrückt wird. Auch wird während der Entprellzeit 256 mal auf Preller geprüft, d.h. bei einem Preller wird nicht die komplette Wartezeit vergeudet. Damit muß man auch nicht so lange warten, wie bei nur einem Test, da ja die Prellperiode (Federkonstante der Kontaktfeder) kürzer ist, als die gesammt Prellzeit. Daher sollten 25ms ausreichen. Sie muß als Macro definiert sein, damit auch für jede Taste eine andere Flagvariable angelegt wird. Daher können mehrere Tasten unabhängig entprellt werden. Peter
Datum:
Peter Dannegger schrieb: > Manchmal wird auch nur das Loslassen gemeldet. Man stelle sich mal vor, > die S-Bahn Tür würde erst bei Loslassen der Öffnungstaste öffnen. Der > Griff zur Notbremse ist damit vorprogrammiert. Ich habe das Beispiel mal umgesetzt (#) und beobachte, dass die LED den Zustand erst in dem Moment ändert, wenn der Taster losgelassen wird. Meine grundsätzliche Änderung ist hardwareseitig: Der Taster auf dem Pollinboard ist active-high vorgegeben, d.h. externer Pull-down im Ruhezustand und Verbindung zu Vcc im gedrückten Zustand. Edit: Wenn ich die Logik im Makro für active high anpasse, funktioniert das Umschalten wie erwartet direkt beim Drücken der Taste. Prima! Die Anpassung ist jetzt auch im Wikiartikel. (#) http://www.mikrocontroller.net/articles/Pollin_Fun...
Datum:
Stefan B. schrieb: > Meine grundsätzliche Änderung ist hardwareseitig: Der Taster auf dem > Pollinboard ist active-high vorgegeben Das ist die ungebräuchliche Beschaltung, da man dann nicht die internen Pullups benutzen kann. Aber ich denke, das schaffst Du selber. Ist wie beim Fernsehquiz: "Legen sie ein ! um, damit die Funktion stimmt." Und die Zeilen zum Enablen des Pullups müssen natürlich auch raus. Man kann sogar das Programm so ändern, daß beide Flanken zurückgegeben werden (als 1 bzw. 2), dazu muß nur eine Zuweisung auf "i = 2;" geändert werden. Peter
Datum:
Ich finde es zwar schön das hier ein Beispiel für Anfänger ist aber ich komme mit dem Macro nicht zurecht... wie macht man daraus eine Funktion ? Ich habe das jetzt in meine "main" eingefügt und es funktioniert, würde das Ganze aber gerne in ein Modul auslagern (tast.c und tast.h). Das Define gehört ja dann in das .h file und der Code ja in das entsprechende c file. Sorry das ich nachfrage aber ich verstehe Macros noch nicht.
Datum:
Du kannst das Macro in ein *.h File schreiben und dann aufrufen. Als Macro habe ich es schreiben müssen, damit auch mehrere Tasten entprellt werden können. Dazu muß aber für jede Taste eine extra Flagvariable angelegt werden. Wäre es eine Funktion, würde die Variable für alle Tasten die gleiche sein und damit das Programm nicht funktionieren. Ein Macro ist nur eine Textersetzung, d.h. der Macroaufruf wird durch den kompletten Text ersetzt und damit wird bei jeder Ersetzung auch eine neue static Flagvariable angelegt. Daher darf man das Macro pro Taste auch nur an einer Stelle aufrufen. Ein Macro endet am Zeilenende und deshalb müssen die Zeilen der Macrodefinition mit dem Zeilenverlängerungszeichen '\' abgeschlossen werden. Für den Compiler ist das alles also nur eine einzige Zeile. Ein "return" darf man im Macro nicht verwenden, es würde sich auf den Aufrufer beziehen, d.h. das Main würde verlassen. Ein Macro hat aber einen Wert, wie jeder C-Ausdruck und das ist der Wert der letzen Anweisung. Deshalb das "i;" am Ende. Ansonsten verhält sich ein Macro wie eine Inline-Funktion. Peter
Datum:
if( --i == 0 ){
flag = 1;
i = 1;
break;
Kann mir bitte jemand erklären, wann diese if-Bedingung wahr wird? i ist
doch vorher immer Null und die Bedingung wird doch erst wahr, wenn i=1
ist, oder hab ich da was falsch verstanden?
Danke
Datum:
Eine 8Bit Variable erreicht nach 256 mal runterzählen wieder 0. Man könnte auch zu Anfang "i = 255;" schreiben, der eine Schleifendurchlauf weniger spielt hier keine Rolle. Peter
Datum:
Hallo, was ist eigentlich der Unterschied zwischen einer debouce() function und der _delay_ms() alleine
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) { if ( ! (*port & (1 << pin)) ) { /* Pin wurde auf Masse gezogen, 100ms warten */ _delay_ms(50); // max. 262.1 ms / F_CPU in MHz _delay_ms(50); if ( *port & (1 << pin) ) { /* Anwender Zeit zum Loslassen des Tasters geben */ _delay_ms(50); _delay_ms(50); return 1; } } return 0; } |
Beispiel:
debounce(&PIND, PD2);
if(!(PIND & (1<<PIND2)))
{
test();
}
mann hätte ja auch sowas schreiben können
if(!(PIND & (1<<PIND2)))
{
test();
_delay_ms(1000);
}
denn braucht der Compiler in dem Fall nicht mehr die debounce Funktion,
um auf die delay header zugreifen.
anderes formuliert was ist der Nutz von so eine Funktion, wenn man das
gleiche mit einer Zeile erzielen kann
Danke im Voraus
Jack
Datum:
Jack schrieb: > was ist eigentlich der Unterschied zwischen einer debouce() function und > der _delay_ms() alleine >
> inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) > |
> ... Dieses debounce() hat nicht im entferntesten Ähnlichkeit mit meiner Funktion. Es verlangt, daß genau darin innerhalb 100ms losgelassen wird. Sobald Deine Programme auch nur ein Quentchen größer werden und nicht ständig im debounce() rumtrödeln können, werden Dir massiv Tastendrücke verloren gehen. Außerdem werden ständig dem Main 100ms CPU-Zeit geklaut, solange eine Taste gedrückt ist. > Beispiel: > debounce(&PIND, PD2); > if(!(PIND & (1<<PIND2))) > { > test(); > } Das ist völliger Quatsch, wo hast Du das her? So darf mein Debounce nicht aufgerufen werden und es fehlt die Auswertung des Returnwertes. Und danach den Pin nochmal direkt einzulesen, macht das Entprellen ja wieder zunichte. Schau Dir doch bitte erstmal meinen Beispielcode an, da ist es richtig. > anderes formuliert was ist der Nutz von so eine Funktion, wenn man das > gleiche mit einer Zeile erzielen kann Dann zeig dochmal diesen Einzeiler her, der auch sauber entprellt und die Flanke auswertet. Peter
Datum:
Peter schreibt: >Dann zeig dochmal diesen Einzeiler her, der auch sauber entprellt und >die Flanke auswertet der sauber entpreller kann einfach so
_delay_ms(100); |
sein, so dass man nicht x-mals nach einem Zustand abfragen braucht >Dieses debounce() hat nicht im entferntesten Ähnlichkeit mit meiner >Funktion ja vielleicht habe ich meine Frage falsch formuliert, der Sourcecode, und die Beschreibung stammen aus der http://www.mikrocontroller.net/articles/AVR-GCC-Tu... und ich kann nicht verstehen warum man sich die mühe macht und die Enprellfunktion schriebt, wenn man an jedem Gebrauch des Entprellens einfach
_delay_ms(DEBOUCE_TIME); |
statt
(debounce(&PINx, Pxx)) |
schreiben kann Danke nochmal im Voraus mfg Jack
Datum:
Was machst du wenn deine Taste länger als 100ms prellt, oder wenn du ein Zeitkritisches Programm hast und nicht 100ms "übrig"? Gruß Fabian
Datum:
Probier einfach mal das gleiche zu erreichen, wie mein Beispielcode: Du hast 2 Tasten und 2 LEDs. Jede Taste muß ihre LED umschalten, egal wie lange gedrückt wird und ob die andere Taste gedrückt ist. Das wirst Du mit Deinem Delay nicht schaffen. Delay und Entprellen sind 2 völlig unterschiedliche Dinge. Du wirst Dich bestimmt auch schon über Geräte mit schlechtem Entprellen geärgert haben. Nur weil andere schlecht programmieren, braucht man noch lange nicht selber schlecht programmieren. Peter
Datum:
Moin Jungs. Ich habe eine einfache Frage. Ich möchte eine Überprüfung machen, ob an einem Digitaleingang eine Spannung anliegt. Ich prüfe allerdings nur, ob keine Spannung anliegt. Dann wird ein ErrorFlag gesetzt. Jetzt muss ich beim Aufruf der Funktion nicht mehr
if(debounce(&PINB,PB1)) ERR=1; |
aufrufen, sondern das invertierte von PB1,weil die Flag ja nur gesetzt werden soll, wenn nichts anliegt. Wie kann ich PB1 invertieren, bzw was muss ich übergeben beim Aufruf? Grüße und Danke
Datum:
Ich weis ja nicht warum immer no ein Umstand für getrieben wird einen Taster zu entprellen... das geht mit nem Widerstand und einem Kondesnator deutlich einfacher :-)
Datum:
ich schrieb: > Ich weis ja nicht warum immer no ein Umstand für getrieben wird einen > Taster zu entprellen... das geht mit nem Widerstand und einem > Kondesnator deutlich einfacher Das ist richtig - vor allem für den Hobbybastler, bei dem Platinenfläche und Kosten eine eher untergeordnete Rolle spielen. Wenn du allerdings an ein kommerzielles Produkt denkst, das zig mal gebaut wird, summieren sich die Mehrkosten für die größere Platine und die RC-Kombination und irgendwann spielt das u.U. eine Rolle. Außerdem ist die Software-Lösung flexibler: dort änderst du ein paar Parameter und kannst so das zeitliche Verhalten beeinflussen - bei der Hardwarelösung musst du dazu schon zum Lötkolben greifen. Oder denk an ein Projekt mit vielen Tastern/Schaltern: willst du wirklich alle Rs & Cs bestücken müssen? Bei einer Tastatur wären das immerhin über 200 Bauteile.
Datum:
ich schrieb: > Ich weis ja nicht warum immer no ein Umstand für getrieben wird einen > Taster zu entprellen... Wo siehst Du da einen Umstand? Einfach nur nen bewährten Code benutzen, sich freuen und gut is. Umständlich ist immer nur, einem Anfänger zu erklären, das Entprellen nötig ist und das ein stumpfes Delay kein Entprellen ist, sondern nur die CPU stark belastet. > das geht mit nem Widerstand und einem > Kondesnator deutlich einfacher > :-) Stimmt, damit kackt dann die CPU deutlich einfacher ab, siehe Pollin-Board: Beitrag "Pollin AVR Board Fehler beim drücken der Taster / Qualität der Bauteile" Funktionieren ist was anderes. Peter
Datum:
Carsten schrieb: > if(debounce(&PINB,PB1)) > ERR=1; Wenn Du Dich nicht auf den ursprünglichen Code beziehst, mach bitte nen eigenen Thread auf. Peter
Datum:
Ist das wirklich so ein Anfängerproblem? Ich kann mich eigentlich auch als µC Anfänger bezeichnen. Gut, ich konnte davor schon programmieren und ich kannte mich auch mit elektronik und so aus. Trotzdem habe ich für bei meiner Entprellmethode keine Probleme gehabt. Also bei meiner wird nur x mal gezählt ob eine Taste auch die x Zyklen gedrückt ist. Bei Prellungen wird von vorne angefangen. Braucht man einen Zustand erst nach Loslassen wird das im entsprechenden Code dann direkt geregelt. Ich weiß nicht was daran schwer sein soll.
Datum:
Hallo, ich bin neu hier und ein echter Rookie, "muss" mich aber aufgrund einer Studienarbeit mit der ganzen µC-Thematik befassen und ein bisschen programmieren (es macht an sich Spaß, ist nur echtes Neuland), unter anderem eben einen Taster inkl. Entprellung. An dem debounce-Makro versteh ich größtenteils alles, bis auf die if(flag)-Abfrage. flag ist ja am Anfang 0, d.h. es wird direkt else abgearbeitet. Aber selbst dann, wenn der Taster also die 25ms gedrückt bleibt und flag=1 gesetzt wird, so wird doch das Makro beendet und eine 1 zurückgegeben, oder? Das wiederum heißt doch, dadurch dass bei erneutem Aufrufen des Makros flag wieder 0 gesetzt wird, dass die if(flag)-Abfrage nie true ist und nie abgearbeitet wird ... wozu ist diese dann da? Oder hab ich da ordentlich was übersehen? Sorry, ich weiß auch, dass der Thread schon alt ist, aber die Frage kommt mir leider erst 2012;) Dank euch! Beste Grüße
Datum:
Hi! Du hast übersehen, dass die Variable flag als static deklariert wurde. Gruß Stefan