Hallo zusammen ! Im Tutorial habe ich folgende Routine zum Entprellen von Tastern gefunden. Funktioniert soweit auch ! (Atmega8 und WINAVR) Jedoch möchte ich jetzt die ganze Sache so ummodellieren, dass ich PIND0,PIND1 und PIND2 gleichzeitig abrufen möchte... wie kann ich das jetzt umschreiben....? Hintergrund ist, dass mein Programm zu lange dauert , weil jeder PIN einzeln abgefragt wird und jedes mal 200ms draufgehen.... Danke für eure HIlfe und Mühe ! //Funktion zum Entprellen der Taster -------------------------------------- inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) { if ( ! (*port & (1 << pin)) ) { /* Pin wurde auf Masse gezogen, 100ms warten */ _delay_ms(100); if ( *port & (1 << pin) ) { /* Anwender Zeit zum Loslassen des Tasters geben */ _delay_ms(100); return 1; } } return 0; }
@rudi >Im Tutorial habe ich folgende Routine zum Entprellen von Tastern >gefunden. Das ist die einfache, aber schlechte Routine. Versuchs mal damit. http://www.mikrocontroller.net/articles/Prellen MfG Falk
ok habe mal ein wenig ausprobiert... Ich möchte einfach nur einen Tastendruck erkennen... habe mal versucht den Code zu modifizieren... habe KOmmentare in den Code eingefügt...könnt ihr mir sagen, ob ich das so lassen ? bzw. was kann ich noch weglassen ? Vielen Dank für eure hilfe
rudi wrote: > ok habe mal ein wenig ausprobiert... > > Ich möchte einfach nur einen Tastendruck erkennen... > > habe mal versucht den Code zu modifizieren... > > habe KOmmentare in den Code eingefügt...könnt ihr mir sagen, ob ich das > so lassen ? > Wenns funktioniert kannst du es so lassen. > bzw. was kann ich noch weglassen ? > if( get_key_press( 1<<KEY0 )) > LED_PORT ^= 1<<LED0; > > // könnte ich auch schreiben .. anstatt KEY0 --> > z.B PB0 oder PB1 oder PD5 ???? Könntest du, aber wozu? KEY0 ist doch aussagekräftiger als PB0 Wenn schon, dann erfinde einen anderen Namen für KEY0. Zb. Hast du eine Taste, die logisch gesehen "nach links" bedeutet. Vielleicht hast du auch eine Taste für "nach rechts". Und noch eine dritte für "Enter". Also machst du
1 | #define KEY_DDR DDRB
|
2 | #define KEY_PORT PORTB
|
3 | #define KEY_PIN PINB
|
4 | |
5 | #define KEY_LEFT PB0
|
6 | #define KEY_RIGHT PB1
|
7 | #define KEY_ENTER PB3
|
8 | #define ALL_KEYS (1<<KEY_LEFT | 1<<KEY_RIGHT | 1<<KEY_ENTER)
|
9 | |
10 | #define REPEAT_MASK (1<<KEY_LEFT | 1<<KEY_RIGHT)
|
11 | #define REPEAT_START 50 // after 500ms
|
12 | #define REPEAT_NEXT 20 // every 200ms
|
Damit hast du dokumentiert: DIe Tasten hängen am Port B Die Taste für "links" hängt auf PB0. Die für "rechts" auf PB1 und "Enter liegt auf PB3 Weiters hast du ein Makro ALL_KEYS, das du bei der Initialisierung des Ports benutzen kannst:
1 | int main() |
2 | {
|
3 | KEY_DDR &= ~(ALL_KEYS); // Am DDR die entsprechenden 0-en setzen |
4 | KEY_PORT |= ALL_KEYS; // Für die Tasten die Pullup Widerstände ein |
5 | |
6 | ....
|
Weiters hast du mit dem Makro REPEAT_MASK dokumentiert, dass sowohl "links" als auch "rechts" einen Autorepeat besitzen, wohingegen die dritte Tatse "Enter" da nicht auftaucht und daher auch keinen Autorepeat hat. Bei der Abfrage machst du dann
1 | if( get_key_press( 1<<KEY_LEFT ) || get_key_rpt( 1<<KEY_LEFT ) ) |
2 | LED_PORT ^= 1<<LED0; |
3 | |
4 | if( get_key_press( 1<<KEY_RIGHT) || get_key_rpt( 1<<KEY_RIGHT) ) |
5 | ....
|
Wenn du jetzt eine Änderung in der Hardware machen musst: * zb alle Tasten vom Port B an den Port D verlegen
1 | #define KEY_DDR DDRD
|
2 | #define KEY_PORT PORTD
|
3 | #define KEY_PIN PIND
|
alles andere passt sich von alleine daran an * zb. die Enter Taste von PB3 nach PB6
1 | #define KEY_ENTER PB6
|
alles andere passt sich wieder von alleine an (inklusive Port Einstellungen und Pullup Widerstände. Die Kunst ist nicht auf Biegen und Brechen abzuspecken. Die Kunst besteht darin den Code so zu schreiben, dass man bei Änderungen nur an möglichst wenigen Stellen anpassen muss und der Compiler (Präprozessor) den Rest anpasst.
Danke erstmal für deine Hilfe... also am besten Erkläre ich jetzt auch mal was ich vorhabe ! Ich habe eine Tastenblock mit 12 Tasten. (3x4 Matrix Anschluß)-->also 3 Spalten und vier Zeilen. Um das Auslesen zuz realisieren habe ich die Spalten als Eingänge mit Pull ups und die Zeilen als Ausgänge definiert. Ausgangspegel =high ("1"). Das heißt jetzt wenn ich eine Taste z.b die Zahl 3 erkennen möchte (Zeile 1 und Spalte 3) , schreibe ich am ausgang Zeile 1 eine "0" und überprüfe ob eine "0" in Spalte 3 eingelesen wird. Habe den Code nochmal geändert...jedoch erhalte ich folgende Fehlermeldung test.c:47: error: expected expression before ')' token test.c:52: error: expected expression before ')' token _______________________________________________________ //Zeile 47//wofür ist dieser Teil überhaupt gedacht ? if( (key_state & REPEAT_MASK) == 0 ) // check repeat function rpt = REPEAT_START; // start delay if( --rpt == 0 ) { rpt = REPEAT_NEXT; // repeat delay key_rpt |= key_state & REPEAT_MASK; } } wie kann ich mein vorhaben am besten mit dieser Routine realisieren ?? Vielen dank für eure unterstützung mfg rudi
rudi wrote: > > Ich habe eine Tastenblock mit 12 Tasten. (3x4 Matrix Anschluß) Diese Information wäre schon vor laaaanger, laaanger Zeit nützlich gewesen. > > Habe den Code nochmal geändert...jedoch erhalte ich folgende > Fehlermeldung > > test.c:47: error: expected expression before ')' token > test.c:52: error: expected expression before ')' token > > _________________________________________________________ > > //Zeile 47//wofür ist dieser Teil überhaupt gedacht ? > > if( (key_state & REPEAT_MASK) == 0 ) // check repeat > function > rpt = REPEAT_START; // start delay > if( --rpt == 0 ) > { > rpt = REPEAT_NEXT; // repeat delay > key_rpt |= key_state & REPEAT_MASK; > } > } > //Zeile 47//wofür ist dieser Teil überhaupt gedacht ? Für den Autorepeat. Wenn der Benutzer auf der Taste einschläft, dann sorgt dieser Programmteil dafür, dass ständig neue Tastendrücke generiert werden. Als du das hier > _________________________________________________________ geschrieben hast, hast du genau diese Funktionalität benutzt, oder hast du etwa 30 mal auf _ getippt? > wie kann ich mein vorhaben am besten mit dieser Routine realisieren ?? Auf die schnelle würde ich sagen: gar nicht. Das ist das falsche Werkzeug. Diese Routinen sind super wenn es um Einzeltasten geht. Für eine Tastenmatrix muss man aber anders auswerten. Wie?: Das hast du schon beschrieben. Das Prinzip "Ein Tastendruck gilt erest dann, wenn er 3 oder 4 mal hintereinander als gedrückt erkannt wird", kannst du ja beibehalten. Aber die Funktionen müsste man derartig kräftig umschreiben, dass man sie gleich neu schreiben kann. Du hast ein Array für alle Tasten in dem für jede Taste ein Zähler realisiert ist. In deiner Abfrage Funktion gehst du alle Tasten (nach dem von dir beschriebenen Prinzip) durch und wenn eine Taste gedrückt ist, erhöhst du den Zähler. Ist die Taste nicht gedrückt, wird der entsprechende Zähler auf 0 gesetzt. Erreicht der Zähler 3 oder 4 (such dir was aus), dann gilt diese Taste als gedrückt und du vermerkst dir dieses in einem anderen Array. Diese Abfragefunktion hängst du an einen Timer und lässt sie alle 10 ms aufrufen. Damit hast du funktional was ähnliches gebaut wie die PeDa Tastenabfrage und Entprellung, nur halt angepasst an deine Matrix.
Hallo und vielen Dank dass du versuchst mir zu helfen... ja so eine Idee hatte ich auch schon mal...habe es mal programmiert , jedoch leider mit der 'debounce' Routine zum Entprellen... habs mal angefügt (ist nur ein Ausschnitt aus meinem Code) aber man sagte mir hier, dass dies eine schlechte Routine wäre, was ich ja einsehe, da mein Programm ja jede Taste einzeln abfragt und ein Durchlauf ja dann ziem,lich lange dauert.... deswegen wollte ich eigentlich diese Routine so ändern, dass ich alle 3 spalten auf einmal abfrage und nachher auswerte was gedrückt wurde.... ...mhhh... was meint ihr dazu ? Danke
rudi wrote: > Hallo und vielen Dank dass du versuchst mir zu helfen... > > ja so eine Idee hatte ich auch schon mal...habe es mal programmiert, > jedoch leider mit der 'debounce' Routine zum Entprellen... > habs mal angefügt (ist nur ein Ausschnitt aus meinem Code) Ich hab dir doch erklärt, wie die bessere Funktion funktioniert. Warum schusterst du dann immer noch mit _delay rum. Das führt zu nächst. Im letzten Post hab ich die Idee entwickelt, nach der die bessere Entprellung funktioniert. Umsetzen musst du das schon alleine. Auch wenn dein Code nicht so ausgefuchst optimiert ist, wie die PeDa Entprellung, so kann sie doch auf demselben Prinzip basieren. Und damit du das Prinzip verstehst (das ist aus dem original PeDa Code nur schwer zu erkennen), hab ich das mal auseinander genommen. Da passiert nicht mehr: für jede Taste gibt es einen Zähler. In einem regelmässigne Interrupt wird jede Taste untersucht ob gedrückt oder nicht. Ist sie gedrückt -> Zähler um 1 rauf. Ist sie nicht gedrückt -> Zähler wieder auf 0. Erreicht der Zähler die 4, dann gilt die Taste als gedrückt. > deswegen wollte ich eigentlich diese Routine so ändern, dass ich > alle 3 spalten auf einmal abfrage und nachher auswerte was > gedrückt wurde.... Ja. Mach das mal.
Denkanstoß: Die PeDa-Bulletproof-Entprellung ist dafür gedacht, dass jede Taste etwas anderes bewirkt und dass mehrere Tasten gleichzeitig etwas auslösen können. Hier soll aber ein Ziffernblock ausgewertet werden. Da ist das gleichzeitige Betätigen mehrerer Tasten eigentlich ein Bedienungsfehler. Daher bietet sich an, alle 20 ms die komplette Matrix auszuwerten und den Tastenwert zu ermitteln. Entprellt wird dann der Tastenwert. Ist dieser eine vorgesehene Anzahl von 'Runden' stabil, so wird er übernommen, ist er anders als der vorherige übernommene Wert, so wird die Aktion ausgelöst, die das Eingeben einer Ziffer bewirken soll. ...
Habe es mal versucht zu programmieren...jedoch habe ich noch nicht so viel Erfahrung... Ich glaube dass man an dem Code noch einiges optimieren kann.... - was ich jetzt noch nicht geschafft habe, einen Timer einzubauen, der diese Routine all1e 10ms abfragt.... oder wie war das gemeint ? Vielen Dank füpr eure Hilfe
rudi wrote: > Habe es mal versucht zu programmieren...jedoch habe ich noch nicht so > viel Erfahrung... Ich habe es mir nicht angesehen, C ist mir zu kryptisch, ist nicht mein Ding. > - was ich jetzt noch nicht geschafft habe, einen Timer einzubauen, der > diese Routine all1e 10ms abfragt.... > > oder wie war das gemeint ? Bei mir hat (fast) jedes AVR-Programm (mindestens) einen Timer-Interrupt, der diverse Aufgaben synchronisiert, so auch das Abfragen und Entprellen von Bedienungstasten. Im Anhang gibt's als Beispiel ein einfaches Programm für Tiny2313, das eine Tastenmatrix 3x4 abfragt und entprellt, eine dreistellige 7-Segmentanzeige betreibt und einen Sirenensound erzeugt, wenn die Eieruhr abgelaufen ist. Ich hoffe, es hilft Dir weiter... ...
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.