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
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
intmain()
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
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...
...