Forum: Compiler & IDEs Entprellung


von TechInfo (Gast)


Lesenswert?

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

von TechInfo (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von TechInfo (Gast)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.


von TechInfo (Gast)


Lesenswert?

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.

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

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

von ... .. (docean) Benutzerseite


Lesenswert?

<<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...

von TechInfo (Gast)


Lesenswert?

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.

von ... .. (docean) Benutzerseite


Lesenswert?

ich hatte es bisher immer das z.B die Kommunikation über den i2c Bus 
lang genug gedauert hat um das Entprellen zu übernehmen...

von TechInfo (Gast)


Lesenswert?

@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.

von Karl H. (kbuchegg)


Lesenswert?

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
}

von Karl H. (kbuchegg)


Lesenswert?

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
}

  

von TechInfo (Gast)


Lesenswert?

fehlt bei der Initialisierung von PinState nicht noch "TASTERPORT &" ?

von Karl H. (kbuchegg)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

>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.

von Karl H. (kbuchegg)


Lesenswert?

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?

von TechInfo (Gast)


Lesenswert?

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 ;)

von Karl H. (kbuchegg)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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.

von TechInfo (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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

von TechInfo (Gast)


Lesenswert?

Wie schön dass wir am Ende immer wieder auf einen Nenner kommen ;)

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
Noch kein Account? Hier anmelden.