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
intmain(void){
7
8
//Zaehlvariable
9
intz=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
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
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.
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
... ü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.
> 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.
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!
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.
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