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.
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.
Tschuldigung. Da ja im Beitrag explizit steht, dass es sich
um low-aktive Taster handelt, wird wahrscheinlich die abfallende
Flanke interessanter sein:
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