Forum: Compiler & IDEs Frage zum einfachen Entprellen über Delay


von Michael N. (pinstripe)


Lesenswert?

Hallo zusammen,

ich beschäftige mich gerade mit dem Entprellen eines Taster über ein 
einfaches Delay. Hierzu habe ich aus den Tutorials von 
mikrocontrollerspielwiese.de folgenden C-Code:
1
#include <avr/io.h>
2
#define F_CPU 1000000UL  // 1 MHz
3
#include <util/delay.h>
4
#include "boarddefs.h"
5
6
int main(void){
7
   
8
    //Zaehlvariable
9
    int z=0;
10
   
11
    //alle PORTS sind Ausgaenge
12
    DDRB = 255; DDRC = 255; DDRD = 255;
13
   
14
    //PC0 wieder loeschen -> PC0 ist nun Eingang
15
    DDRC &= ~_BV(PC0);
16
   
17
    //alle LEDs aus bzw. alle PULL UPs an, wo Eingänge definiert
18
    PORTB = 255;    PORTC = 255;    PORTD = 255;
19
   
20
    while (1){
21
       
22
        //Wenn Taste gedrueckt
23
        if (bit_is_clear(PINC,0)) {
24
           
25
            z++;        
26
            if (z==4) z=1;
27
           
28
            PORTB=255; PORTC=255; PORTD=255;
29
           
30
            if (z==1) led1on;
31
            if (z==2) led2on;
32
            if (z==3) led3on;
33
   
34
            //warten, bis Taste losgelassen wird
35
            while (bit_is_clear(PINC,0)) {_delay_ms(100);}
36
37
        }
38
       
39
        //nochmal warten
40
        _delay_ms(100);
41
       
42
    }
43
return(0);
44
}

Der Code funktioniert, es tritt kein Prellen auf. Jedoch bin ich mir 
über denn genauen Sinn der Delays in diesem Beispiel nicht ganz klar:

1.) Warum benutzt der Autor hier den while Befehl?
1
//warten, bis Taste losgelassen wird
2
   while (bit_is_clear(PINC,0)) {_delay_ms(100);}
Das hieße ja "während" bzw. "sobald Taster gedrückt->warte 100ms". 
Eigentlich könnte, ich den delay-Befehl doch einfach so in die 
if-Schleife einfügen, ohne eine while-Schleife ?!? Stellt man das Delay 
jedoch mal auf 2000ms, so merkt man, dass das delay erst beginnt, wenn 
der Taster losgelassen wird. Warum? Entprellen wir hiermit also das 
Loslassen des Tasters?

2.) Warum "nochmal warten?" Dann entprellen wir ja zwei mal das 
Loslassen des Tasters, aber gar nie das Drücken des Tasters, oder?
1
//nochmal warten
2
   _delay_ms(100);

Vielen Dank für jede Antwort bereits im Voraus!
Grüße, pinstripe

von Oliver S. (oliverso)


Lesenswert?

Michael N. schrieb:
> Warum

fragst du das nicht denjenigen auf mikrocontrollerspielwiese.de, der den 
Code verbrochen hat?
Tasten entprellen über delay ist etwas, was nicht unbedingt sinnvoll 
ist.

Oliver

von Patrick (Gast)


Lesenswert?

Michael N. schrieb:
> Das hieße ja "während [...] Taster gedrückt->warte 100ms".

Genau.

Michael N. schrieb:
> Eigentlich könnte, ich den delay-Befehl doch einfach so in die
> if-Schleife einfügen, ohne eine while-Schleife ?!?

Nein. Denk nochmal drüber nach.

Michael N. schrieb:
> Stellt man das Delay
> jedoch mal auf 2000ms, so merkt man, dass das delay erst beginnt, wenn
> der Taster losgelassen wird.

Naja... Wie hast Du das nachgewiesen, dass das delay tatsächlich immer 
erst beginnt, wenn Du den Taster loslässt?
Ich würde eher sagen, Du erwischst bei jedem Loslassen das delay 
zufällig irgendwo "in der Mitte".

Michael N. schrieb:
> Entprellen wir hiermit also das
> Loslassen des Tasters?

Nö. Der Autor wartet so lange, bis PINC0 wieder High (d. h. der Taster 
losgelassen) wird. Den gleichen Effekt hätte übrigens auch
1
while (bit_is_clear(PINC,0)) {}

Michael N. schrieb:
> Warum "nochmal warten?" Dann entprellen wir ja zwei mal das
> Loslassen des Tasters, aber gar nie das Drücken des Tasters, oder?

Nö. Nachdem der Taster losgelassen wurde, wird das IF-Konstrukt 
verlassen, und der Code wartet 100ms.

von Peter D. (peda)


Lesenswert?

Michael N. schrieb:
> //alle PORTS sind Ausgaenge
>     DDRB = 255; DDRC = 255; DDRD = 255;
>
>     //PC0 wieder loeschen -> PC0 ist nun Eingang
>     DDRC &= ~_BV(PC0);

Oh Gott!

Man programmiert niemals Eingänge als Ausgänge, auch nicht nur 2µs lang.
Und man setzt immer erst den Pegel und dann die Richtung.


Peter

von Patrick (Gast)


Lesenswert?

... übrigens habe ich bei diesem Code ebenfalls ziemliche 
Bauchschmerzen.

Einfach nur lange genug zu warten, bis auch der gröbste Taster sicher 
nicht mehr prellt (nämlich das ist das, was hier passiert), ist zwar 
prinzipiell möglich, kann aber bestenfalls als "Holzhammermethode" 
bezeichnet werden.

von Karl H. (kbuchegg)


Lesenswert?

> 1.) Warum benutzt der Autor hier den while Befehl?
> //warten, bis Taste losgelassen wird
>    while (bit_is_clear(PINC,0)) {_delay_ms(100);}
> Das hieße ja "während" bzw. "sobald Taster gedrückt->warte 100ms".

An dieser Stelle ist aber die Taste schon gedrückt.
D.h. die richtige Umschreibung (die auch im Kommentar steht) ist hier 
eigentlich:
   der Benutzer hat mit dem Patschehändchen die Taste niedergedrückt
   und jetzt wartet das Programm darauf, dass er auch wieder mal
   loslässt.
   denn: ein Tastendruck besteht aus 2 Teilen:
            * dem Niederdrücken
            * und dem Loslassen

Wenn eine Aktion nur bei jedem Tastendruck erfolgen soll, dann kann man 
nicht einfach sagen

    if( Taste ist niedergedrückt )

denn die Taste kann eine halbe Stunde niedergedrückt sein (wenn der 
Benutzer auf der Taste eingeschlafen ist) und jedesmal wenn das Programm 
an dieser Stelle vorbeikommt, stellt es fest, dass die Taste 
niedergedrückt ist und macht dann logischerweise auch jedesmal die 
Aktion.

d.h. ist man auf einen einzelnen Tastendruck aus, dann wird zwar die 
Aktion gemacht, sobald man die Taste im niedergedrückten Zustand 
erwischt. Aber die Aktion darf nur ein einziges mal gemacht werden. Der 
Benutzer muss dazwischen auch mal loslassen. Erst dann gilt das nächste 
mal 'Taste als niedergedrückt erkannt' als 'nächster Tastendruck'.

> Eigentlich könnte, ich den delay-Befehl doch einfach so in die
> if-Schleife einfügen, ohne eine while-Schleife ?!?

Probiers aus.




Und im übrigen hoffe ich, dass das ein Tutorial ist, welches letzten 
Endes zeigt, wie man Tasten nicht auswertet.

von Michael N. (pinstripe)


Lesenswert?

Patrick schrieb:
> Michael N. schrieb:
>> Stellt man das Delay
>> jedoch mal auf 2000ms, so merkt man, dass das delay erst beginnt, wenn
>> der Taster losgelassen wird.
>
> Naja... Wie hast Du das nachgewiesen, dass das delay tatsächlich immer
> erst beginnt, wenn Du den Taster loslässt?
> Ich würde eher sagen, Du erwischst bei jedem Loslassen das delay
> zufällig irgendwo "in der Mitte".

Ich habe nach dem delay-Befehl eine weitere Anweisung eingefügt (z.B. 
"led4on"). Solange ich nun den Taster gedrückt halte (z.B. 10sec) 
passiert gar nichts, und wenn ich den Taster loslasse, dauert es 2sec 
bis led4 angeht.

Patrick schrieb:
> Der Autor wartet so lange, bis PINC0 wieder High (d. h. der Taster
> losgelassen) wird. Den gleichen Effekt hätte übrigens auch
> while (bit_is_clear(PINC,0)) {}

Die Anweisung innerhab der {} wird solange ausgeführt wie ich die 
Taste gedrückt halte. (richtig?) Wenn ich die Taste nun aber länger als 
100ms drücke, was macht er dann? Beginnt er nochmal mit dem 100ms-delay? 
@ Karl-Heinz-Buchegger: Ist dieser Teil des Codes also nur dazu da, zu 
verhindern, dass die if-Schleife öfters als einmal durchlaufen wird, 
falls ich den Taster länger drücke? Also nicht zum entprellen?

Entschuldigt bitte, aber ich glaube ich habe nicht das Verständnis für 
den Einsatz des while-Befehls an dieser Stelle. Vielen Dank an alle, die 
bereits geantwortet haben!

von Karl H. (kbuchegg)


Lesenswert?

Michael N. schrieb:

> @ Karl-Heinz-Buchegger: Ist dieser Teil des Codes also nur dazu da, zu
> verhindern, dass die if-Schleife

Nebenschauplatz:
Ein 'if' ist keine Schleife.
Das Wesen einer SChleife besteht darin, dass etwas wiederholt ausgeführt 
wird. Bei einem 'if' wird nichts wiederholt. Ein if entscheidet anhand 
der angegebenen Bedingung, ob sein then-Teil oder ob sein else-Teil 
auszuführen ist (wobei das else auch fehlen kann). Wiederholt wird da 
gar nichts. Ein if ist einfach nur eine Entscheidung.

> öfters als einmal durchlaufen wird,
> falls ich den Taster länger drücke? Also nicht zum entprellen?

Es macht denn Unterschied von

* mache etwas EINMALIG, wenn eine Taste niedergedrückt WURDE

im unterschied zu:

* mache etwas SOLANGE eine Taste niedergedrückt IST.


Bei dir dann eben:
Du drückst einmal auf die Taste und die Zahl wird um 1 hochgezählt (bzw. 
die nächste LED leuchtet). Und zwar unabhängig davon wie lange die Taste 
gedrückt ist. Jedesmal, wenn du erneut auf die Taste drückst (nicht zu 
schnell hinterinander), wird mit jedem Tastendruck die Zahl um 1 
weitergezählt.

Im Gegenzug zu:
Du drückst die Taste nieder und die Zahl wird laufend um 1 erhöht und 
zwar solange, wie die Taste niedergedrückt ist. Du drückst drauf und 
sofort beginnen deine LED eine nach der anderen zu leuchten. Und zwar 
solange, wie du auf der Taste bleibst.



Probiers halt einfach aus!
Da explodiert nichts.


> Also nicht zum entprellen?
Hat mit entprellen so gesehen wenig zu tun. Das entprellen wird in dem 
Code durch die _delay_ms 'erreicht'. Einfach solange nicht auf den Port 
schauen, bis der Taster sicher ausgeprellt hat.
Ist nicht gerade die feine englische Art. Eher die 'hau drauf und hinter 
mir die Sintflut'-Methode.

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Hallo!

Michael N. schrieb:
> Hierzu habe ich aus den Tutorials von
> mikrocontrollerspielwiese.de folgenden C-Code:

Wenn ich dir von Anfänger zu Anfänger mal einen Tip geben darf. Ich 
persönlich habe viel über das Tut hier auf der Seite gelernt. Ich habe 
gerade mal ein wenig über deine Seite gelesen. Also Alter Schwede, das 
ist arg, was dort geschrieben wird. Du wirst damit nicht glücklich. Lies 
das Tut hier auf der Seite wenigstens mal an, du wirst sehr schnell den 
fachlichen Unterschied merken. Und hier bekommst du auch am Anfang nur 
das nötigste gelernt, um das du innerhalb sehr kurzer Zeit etwas sehen 
kannst. Und nur wenn du möchtest kannst du hier auch bis ins Detail für 
fast alles eine ordentliche Begründung finden.

Von den bisschen erfahreneren Leuten können sich ja mal welche die Seite 
ansehen, das ist echt der Hammer.

http://www.mikrocontrollerspielwiese.de

MfG Dennis

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.