Hallo, ich habe eine Frage zu dem Flankenerkennungs-Code: http://www.mikrocontroller.net/articles/Entprellung#Flankenerkennung Wenn man den Taster gedrückt hält, durchläuft das Programm doch einfach alle Zustände und gibt dann wieder und wieder rw=1 aus, oder? Das ist ja genau das, was man nicht möchte. Das hieße aber auch, dass man quasi so schnell drücken muss, dass nicht alle else if durchlaufen werden müssen. Zudem verstehe ich nicht, wieso Taste losgelassen ein eigener Zustand ist. In der else if-Abfrage wird immer noch der Wert des Tasters abgefragt, obwohl er doch eigentlich nicht mehr gedrückt ist in diesem Zustand. Gruß TechInfo
Vergesst meine Frage, habe gesehen dass die if-Bedigungen ja unterschiedlich sind (mit und ohne !). Ich hätte aber noch eine Frage zu Peter Daneggers C-Routine mit Interrupt-Steuerung: Durch welchen Teil des Codes wird gewährleistet, dass mehrere Tasten gleichzeitig gedrückt werden können, wie in der Beschreibung zu lesen ist?
> Durch welchen Teil des Codes wird gewährleistet, dass mehrere Tasten > gleichzeitig gedrückt werden können, wie in der Beschreibung zu lesen > ist? Das ist dadruch gewährleistet, dass alle Portpins gleichzeitig behandelt werden. In den Statusvariablen entspricht jedes Bit einer Taste und da die Statusvariablen alle immer mit allen 8 Bit gleichzeitig in die Verknüpfungen eingehen, werden alle maximale möglichen 8 Tasten unabhängig voneinander immer gleich behandelt. Das ist eines der genialen Dinge an diesem Code. Ich weiss nicht wer den anderen Code da reingestellt hat. Ich hab ihn auch noch nicht im Detail analysiert. Er erscheint mir aber auf den ersten Blick etwas dubios. Vor allem der Satz hier: <Zitat> Die Entprellung geschieht dabei durch die ganze Laufzeit des Programms </Zitat> lässt bei mir die Alarmglocken klingeln.
Ich habe den anderen Code eben mal implementiert. Funktioniert einwandfrei. Benutze allerdings auch eine futsch neue Tastatur. Für das fertige Programm werde ich dann wohl auf deinen Code zurückgreifen.
Noch ne Frage: Wo wird hier realisiert, dass erst bei VIER Timer Overflows die Taste als gedrückt behandelt wird? Ich sehe nirgendwo einen Zähler, aber mein Assembler ist auch schon etwas eingerostet... http://www.mikrocontroller.net/articles/Entprellung#Interrupt-Verfahren_.28nach_Peter_Dannegger.29
TechInfo wrote: > Noch ne Frage: > > Wo wird hier realisiert, dass erst bei VIER Timer Overflows die Taste > als gedrückt behandelt wird? Ich sehe nirgendwo einen Zähler, aber mein > Assembler ist auch schon etwas eingerostet... Der Zähler ist auch nicht leicht zu finden, weil er auf 2 Register aufgeteilt ist: iw0 und iw1 Für die Taste am Pin 3 bilden bsp die Bits 3 in iw0 und Bit 3 in iw1 den 2 Bit-Zähler der bis 4 zählt.
Karl heinz Buchegger wrote: > TechInfo wrote: >> Noch ne Frage: >> >> Wo wird hier realisiert, dass erst bei VIER Timer Overflows die Taste >> als gedrückt behandelt wird? Ich sehe nirgendwo einen Zähler, aber mein >> Assembler ist auch schon etwas eingerostet... > > Der Zähler ist auch nicht leicht zu finden, weil er auf > 2 Register aufgeteilt ist: iw0 und iw1 > > Für die Taste am Pin 3 bilden bsp die Bits 3 in iw0 und Bit 3 in iw1 > den 2 Bit-Zähler der bis 4 zählt. Ich bin mir da jetzt gar nicht mehr so sicher. Im Assembler Code ist das tatsächlich sehr versteckt. Im C Code ist das aber eindeutig ct0 und ct1, die zusammen so arbeiten und den Zähler realisieren.
Ok, danke. Kannst Du Dir vielleicht doch noch diesen Code genauer anschauen? http://www.mikrocontroller.net/articles/Entprellung#Flankenerkennung Meiner Meinung nach macht er gar keine echte Entprellung, sondern nur die Flankenerkennung. Falls die Taste genau im Rhythmus der Abarbeitung der if-Anweisungen prellt, werden die Zustände einfach durchlaufen, als ob ein echter Tastendruck vorliegt. Bei einem Zähler z.B. wäre das fatal.
Karl heinz Buchegger wrote: > Ich bin mir da jetzt gar nicht mehr so sicher. > Im Assembler Code ist das tatsächlich sehr versteckt. Ich sag mal, der Code dort vergleicht nur 2 Samples. Anbei mein Original-Code, da heißen dann die Counterbytes key_ct0, key_ct1. Mit iwr0, wr0 hatte ich (Interrupt-) Working-Register gemeint, die also einen Funktionsaufruf nicht überleben. In C kann man natürlich leicht auch auf 16/32 Tasten erweitern (int16_t, int32_t). Bzw. aufm ARM7 sinds automatisch mindestens 32 Tasten (man muß ja nicht alle abfragen). Peter
<<me hat den Code eingefügt Der Code verhindert das das Festhalten einer Taste Signale ergibt... Beispiel: Taste ist nicht gedrückt rw=0 alles io Taste wird gedrückt rw=1 alles io Taste wird gehalten rw=0 alles io taste wird losgelassen rw=0 alles io Die Entprellung erfolgt ÜBER DIE LAUFZEIT des Hauptprogramms, wird die funktion zu oft aufgerufen wird natürlich nicht entprellt, sondern es kann passieren das die Zustände durchlaufen werden... Dafür ist diese Variante sehr schnell, die CPU liegt niemals brach, sie kann immer was tun...
Ok, aber um zu gewährleisten, dass die Funktion im Hauptprogramm nicht zu oft aufgerufen wird, muss da ja wieder ein delay eingefügt werden. Und dann liegt die CPU doch brach.
ich hatte es bisher immer das z.B die Kommunikation über den i2c Bus lang genug gedauert hat um das Entprellen zu übernehmen...
@Nix Nix Zustand könnte man sich doch eigentlich auch sparen, oder? Er entspricht ja Zustand 2. Man müßte dann in Zustand 2 nur zustand=0 setzen.
Die ganze Funktion (wenn es nur um das Erkennen der anstiegenden Flanke geht), könnte man so schreiben
1 | #define TASTERPORT PINC
|
2 | #define TASTERBIT PINC1
|
3 | |
4 | unsigned char PinRaised() |
5 | {
|
6 | static unsigned char PinState; |
7 | unsigned char NewState = TASTERPORT & ( 1 << TASTERBIT ); |
8 | |
9 | if( NewState == PinState ) |
10 | return 0; |
11 | |
12 | NewState = PinState; |
13 | return NewState != 0; |
14 | }
|
Tschuldigung. Da ja im Beitrag explizit steht, dass es sich um low-aktive Taster handelt, wird wahrscheinlich die abfallende Flanke interessanter sein:
1 | #define TASTERPORT PINC
|
2 | #define TASTERBIT PINC1
|
3 | |
4 | unsigned char PinDropped() |
5 | {
|
6 | static unsigned char PinState = (1 << TASTERBIT); |
7 | unsigned char NewState = TASTERPORT & ( 1 << TASTERBIT ); |
8 | |
9 | if( NewState == PinState ) |
10 | return 0; |
11 | |
12 | NewState = PinState; |
13 | return NewState == 0; |
14 | }
|
TechInfo wrote:
> fehlt bei der Initialisierung von PinState nicht noch "TASTERPORT &" ?
Kannst du machen.
Ich geh davon aus, dass die Taste beim ersten Aufruf der Funktion
(dürfte im Normallfall ein paar ms nach Einschalten des
Geräts sein) nicht gedrückt ist. Wenn doch, dann werte ich
das bereits als ersten Tastendruck.
und warum initialsierst du dann PinState = (1 << TASTERBIT) ? Gibt es dafür einen bestimmten Grund? 1 << TASTERBIT gibt doch nicht den Wert des Bits, sondern seine Position innerhalb des Registers zurück. Demnach könnte man PinState doch mit einem x-beliebigen Wert initialisieren, oder?
TechInfo wrote: > und warum initialsierst du dann PinState = (1 << TASTERBIT) ? > Gibt es dafür einen bestimmten Grund? 1 << TASTERBIT gibt doch nicht den > Wert des Bits, sondern seine Position innerhalb des Registers zurück. Quatsch: 1 << TASTERBIT ergibt eine Zahl, die genau an der Bit-Position TASTERBIT eine 1 aufweist. Alle anderen Bits sind 0. > Demnach könnte man PinState doch mit einem x-beliebigen Wert > initialisieren, oder? Nein könnte man nicht. Wenn die Taste nicht gedrückt ist (und ausser der Taste nichts anderes am Port hängt), dann wird vom Port der Wert 1 << TASTERBIT eingelesen. Sprich ein Byte, das an der Stelle wo der Taster sitzt eine 1 aufweist. Und das nehme ich als Initialisierung für den Zustand. Ist die Taste beim Einschalten nicht gedrückt, dann wird vom Port genau wieder dieser Zustand eingelesen TASTERPORT & ( 1 << TASTERBIT ) (diesmal allerdings werden alle anderen Bits ausmaskiert). Wie auch immer: Da meine Initialisierung aus einem 1 Bit an bewusster Stelle besteht und vom Port ebenfalls ein byte eingelesen wird, dass eine 1 an besagter Stelle aufweist (weil ja der Taster nicht gedrückt ist), ergibt der nachfolgende Vergleich if( PinState == NewState ) true, und es passiert nichts weiter. So wie es sein soll. Nur weil ich ein Gerät einschalte, hab ich ja nicht automatisch einen Tastendruck gemacht.
>Quatsch: >1 << TASTERBIT >ergibt eine Zahl, die genau an der Bit-Position TASTERBIT eine >1 aufweist. Alle anderen Bits sind 0. Ok, das meinte ich auch, habe mich aber falsch ausgedrückt. >Wie auch immer: Da meine Initialisierung aus einem 1 Bit >an bewusster Stelle besteht und vom Port ebenfalls ein byte >eingelesen wird, dass eine 1 an besagter Stelle aufweist >(weil ja der Taster nicht gedrückt ist), ergibt der >nachfolgende Vergleich > > if( PinState == NewState ) > >true, und es passiert nichts weiter. Verstehe den Unterschied immer noch nicht. Der Port ist durch Pull-Ups mit 0b11111111 initialisiert. Sagen wir, der Taster hängt an Pin 3. Dann hast du in PinState den Wert 0b00000100 = 4 stehen. In NewState wird dann ebenfalls 0b00000100 eingelesen (kein Tastendruck). Wieso meinst Du, dass wenn ich PinState mit TASTERPORT & ( 1 << TASTERBIT ) initialisiere (genau wie NewState), sofort nach Einschalten des Gerätes ein Tastendruck erkannt wird? Es gibt doch keinen Unterschied zwischen den beiden Initialisierungen.
TechInfo wrote: > Wieso meinst Du, dass wenn ich PinState mit TASTERPORT & ( 1 << > TASTERBIT ) initialisiere (genau wie NewState), sofort nach Einschalten > des Gerätes ein Tastendruck erkannt wird? Es gibt doch keinen > Unterschied zwischen den beiden Initialisierungen. Du sagtest aber nicht, dass du mit TASTERPORT & ( 1 << TASTERBIT ) initialisieren möchtest, sondern, Zitat: > Demnach könnte man PinState doch mit einem x-beliebigen Wert > initialisieren, oder?
In meiner ersten Antwort sprach ich aber von TASTERPORT & ( 1 << TASTERBIT ), und deine Reaktion darauf habe ich so gelesen dass es damit einen Unterschied zu Deiner Version gibt. Dann sagen wir eben, einen x-beliebigen Wert außer 0 ;)
TechInfo wrote: > In meiner ersten Antwort sprach ich aber von TASTERPORT & ( 1 << > TASTERBIT ), und deine Reaktion darauf habe ich so gelesen dass es damit > einen Unterschied zu Deiner Version gibt. > > Dann sagen wir eben, einen x-beliebigen Wert außer 0 ;) Nein, eben nicht irgendein x-beliebiger Wert. Der Wert kann 1 << TASTERBIT sein, er kann auch TASTERPORT & ( 1 << TASTERBIT ) sein, aber damit hat sichs auch schon. Einer der beiden, aber kein anderer. Ein x beliebiger Wert wäre zb. auch 5 oder 63. Beide funktionieren nicht wie gewünscht. Spiels doch mal in Gedanken durch.
Ok sorry, Du hast Recht. Bei einem anderen Wert wird ja dann NewState=PinState gesetzt und somit funktioniert der nächste Durchlauf der Funktion nicht mehr.
Sorry, ich hab es jetzt nochmal durchgespielt und bin anscheinend zu blöd. Gehen wir davon aus, dass der Taster am ersten Pin des Ports liegt: 1. Aufruf der Funktion: static unsigned char PinState = (1 << TASTERBIT); //PinState enthält den Wert 1 unsigned char NewState = TASTERPORT & ( 1 << TASTERBIT ); //NewState enthält den Wert 1 if( NewState == PinState ) return 0; //Bedingung true, alles ok. Zweiter Aufruf, Taster jetzt gedrückt: static unsigned char PinState = (1 << TASTERBIT); //PinState enthält immer noch den Wert 1 (static) unsigned char NewState = TASTERPORT & ( 1 << TASTERBIT ); //NewState enthält jetzt den Wert 0 if( NewState == PinState ) return 0; //Bedingung falsch NewState = PinState; return NewState == 0; //NewState enthält durch die Zuweisung den Wert 1. NewState==0 ist false. Also wird doch 0 zurückgegeben, aber eigentlich müßte es eine 1 sein, oder nicht?
TechInfo wrote: > > NewState = PinState; Ooops. Mein Fehler. (Man sollte Funktionen immer testen bevor man postet. Mögen sie noch so einfach sein :-) Muss natürlich PinState = NewState; heissen. Klarer Fall von: richtig gedacht aber falsch hingeschrieben. > return NewState == 0; > > //NewState enthält durch die Zuweisung den Wert 1. NewState==0 ist > false. Also wird doch 0 zurückgegeben, aber eigentlich müßte es eine 1 > sein, oder nicht? Richtig. Zuweisung anders rum, dann klappts auch mit dem Vergleich. (und dann macht auch das static bei PinState Sinn. so ist das etwas sinnfrei). Wie gesagt: mea culpa
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.