Hi,
habe mir gerade mal Gedanken über eine Entprellroutine gemacht...
Würde das nicht ausreichen? Geht auch nur um das drücken des Tasters...
void debounce_switch()
{
uint8_t debounce_count = 0;
for(int i=0; i<8;++i)
_delay_us(50);
if(!(PINB & (1<<PINB0)))
++debounce_count;
else
debounce_count = 0;
}
Beste Grüße,
Michael
Du erhöhst deinen debounce_count 2 mal innerhalb der Schleife.
Ist an und für sich kein Beinbruch, dann werden halt einfach nur 4
hintereinanderliegende 0-Bits schon akzeptiert.
Wie willst du die Funktion verwenden?
Entprellung
uint8_t debounce_switch(volatile uint8_t *port, uint8_t pin)
{
for(uint8_t debounce_count=0; debounce_count<8; ++debounce_count)
{
_delay_us(500);
if(*port & (1<<pin))
{
debounce_count = 0;
return 0;
}
}
return 1;
}
Habe es jetzt so abgeändert... Brauch es nur um einen Tastendruck zu
entprellen, das loslassen ist uninteressant. Wenn der Schalter gedrückt
wird, geht der Pin auf Massepegel.
Danke
Moin,
mal eine Frage aus Interesse:
was ist eigentlich so furchtbar an einer Hardware-Entprellung?
Es gibt hier eine Vielzahl von Beiträgen zur Software-Enprellung.
Ein schnödes RC-Glied pro Taster (so viele von den Dingern verbaut man
ja auch nicht), und das Problem ist an der Wurzel gelöst.
Software-Entprellung ist doch nur das Doktern an Symptomen, ohne die
Ursache zu beseitigen.
Oder übersehe ich irgendwas wichtiges?
Liebe Grüße aus der Wesermarsch
Ralph
Die Ursache, der prellende Kontakt, der läßt sich nicht beseitigen!
Ein Taster prellt immer beim Schließen. Ist ein mechanisches Problem.
Der einer Kontakt wird mit Kraft gegen den anderen bewegt, schlägt auf
und federt zurück. Alternativ müsstest Du einen Taster bauen, dessen
Kontakt exakt zum richtigen Zeitpunkt abgebremst wird. Nur wie soll das
gehen? :-)
Ein Entprellen per Software ist ein sehr eleganter Weg, weil er Bauteile
spart. Und weil man mit Software auch eine Repeat-Funktion realisieren
kann. Mit Hardware wäre das recht aufwendig.
Carsten
Ralph Fischer schrieb:> Ein schnödes RC-Glied pro Taster (so viele von den Dingern verbaut man> ja auch nicht), und das Problem ist an der Wurzel gelöst.
wenn mans richtig macht.
Pollin zb hat Hardware Entprellung, machts aber falsch. Folge: Der µC
stürzt regelmässig ab.
Mit der PeDa Entprellung bin ich persönlich hoch zufrieden. Neben dem
Entprellen kriege ich quasi zum Drüberstreuen noch einige Vorteile: Das
Ding übersieht garantiert keinen Tastendruck (solange Interrupts
aktiviert sind), kann zwischen langen und kurzen Tastendrücken
unterscheiden und auf Wunsch krieg ich auch noch einen Autorepeat auf
der Taste (eine von mir besonders bei Inkrement/Dekrement Funktionen
gerne genutzte Funktionalität). Und das alles für noch nicht einmal 1%
der Rechenzeit. Da kann man doch nicht meckern :-)
Die Frage lautet für mich also nicht
"Warum Software, wenn es auch in Hardware geht"
sondern
"Warum Hardware, wenn es auch in Software problemlos geht"
Die Entprellungen auf Basis Warteschleife: Von denen halte ich
persönlich nichts, weil dann die Durchlaufzeiten unnötigerweise
verlängert werden, ohne dass ich ausser der Entprellung noch etwas dafür
kriegen würde.
Ralph Fischer schrieb:> was ist eigentlich so furchtbar an einer Hardware-Entprellung?>> Es gibt hier eine Vielzahl von Beiträgen zur Software-Enprellung.>> Ein schnödes RC-Glied pro Taster (so viele von den Dingern verbaut man> ja auch nicht), und das Problem ist an der Wurzel gelöst.>> Software-Entprellung ist doch nur das Doktern an Symptomen, ohne die> Ursache zu beseitigen.
Wenn schon Hardware-Entprellung, dann aber richtig und kein
"funktioniert solange Taster neu ist" RC Glied.
Nämlich ein Umschalttaster und ein RS Flipflop.
Ansonsten haben Karl Heinz und Carsten schon alles gesagt.
Moin Jungs,
nur damit keine Mißverständnisse aufkommen: ich habe nicht behauptet,
daß HW-Entprellung das einzig Senkrechte wäre. Das war wirklich eine
neugierige Frage.
Bisher habe ich RC-Glieder mit ca. 15 Hz Grenzfrequenz genommen (weil
menschliche Muskeln nicht schneller als 7 Hz können). Funktioniert auch
in einer 30 Jahre alten Z80-Mimik noch tadellos.
Das war wohl mit
> "funktioniert solange Taster neu ist"
gemeint.
> Nämlich ein Umschalttaster und ein RS Flipflop.
Tja, und ab hier gefällt mir Software dann auch besser ;-)
Zusatzfrage: gibts von der Dannegger-Entprellung irgendwo eine
Darstellung als Flußdiagramm?
Ich beherrsche nur Bascom und Z80-Assembler (letzteres schon einige
Monde eingerostet). Dann könnte ich mir das mal nachhäkeln...
Herzlichen Dank und Ende der Fred-Kaperung :-)
Liebe Grüße aus der Wesermarsch
Ralph
Michael schrieb:> if(!(PINB & (1<<PINB3)))> {> if(debounce_switch(&PINB, PINB3))> {> ....> }> else> {> ....> }>> }>> @Karl heinz Buchegger: So nutze ich meine Funktion... Habe ich vergessen> zu erwähnen...
Damit detektierst du keinen Tastendruck, also das wechseln einer Taste
vom Zustand 'nicht gedrückt' in den Zustand 'gedrückt'.
Du stellst nur fest, ob die Taste gedrückt ist. Und wenn du 2000 mal in
der Sekunde nachsiehst ob die Taste gedrückt ist, dann führst du auch
deinen Ausführungsteil 2000 mal aus.
Karl heinz Buchegger schrieb:> Du stellst nur fest, ob die Taste gedrückt ist. Und wenn du 2000 mal in> der Sekunde nachsiehst ob die Taste gedrückt ist, dann führst du auch> deinen Ausführungsteil 2000 mal aus.
Nope...
Die if(!(PINB & (1<<PINB3))) ist nur wahr wenn der Taster gedrückt
wird... Ansonsten liegt an meinem Eingang ein High-Pegel an... Mich
interessiert auch nur der Tastendruck also der Pegelwechsel von High auf
Low an meinem Eingang.
Michael schrieb:> Die if(!(PINB & (1<<PINB3))) ist nur wahr wenn der Taster gedrückt> wird...
Genau.
Und dann gibt debounce() jedesmal 1 zurück.
Eine Flankenerkennung erfolgt nicht.
Du kriegst alle 500µs * 8 = 4ms ne 1 solange Du drückst und nicht nur
beim Wechsel der Taste zu gedrückt.
Peter
Peter Dannegger schrieb:> Genau.> Und dann gibt debounce() jedesmal 1 zurück.> Eine Flankenerkennung erfolgt nicht.>> Du kriegst alle 500µs * 8 = 4ms ne 1 solange Du drückst und nicht nur> beim Wechsel der Taste zu gedrückt.>>> Peter
Genau, aber wenn ich die Taste drücke, tue ich dies bewusst... Die
Funktion ist quasi ein EMV Schutz...Meiner Meinung nach erkenne ich den
Flankenwechsel mit einer kontinuierlichen Abfrage ala: if(!(PINB &
(1<<PINB3)))...
Wenn ein Puls in meinen Eingang haut, wird diese Bedingung auch wahr,
aber die debounce_switch liefert dann hoffentlich eine 0.
Michael schrieb:> Peter Dannegger schrieb:>> Genau.>> Und dann gibt debounce() jedesmal 1 zurück.>> Eine Flankenerkennung erfolgt nicht.>>>> Du kriegst alle 500µs * 8 = 4ms ne 1 solange Du drückst und nicht nur>> beim Wechsel der Taste zu gedrückt.>>>>>> Peter>> Genau, aber wenn ich die Taste drücke, tue ich dies bewusst... Die> Funktion ist quasi ein EMV Schutz...
Junger Mann.
Ja nachdem was dein Programm dann sonst noch so tut, kannst du die Taste
gar nicht so schnell loslassen, dass sie deni Programm nicht ein paar
mal als gedrückt erkennt.
Es gibt Anwendungen da ist das ok:
zb Rollo fährt hoch, SOLANGE eine Taste gedrückt ist
zb Autofenster fährt rauf/runter, SOLANGE eine Taste gedrückt ist.
Willst du abre auf einen einmaligen Tastendruck hin, nur EINMAL eine
Aktion auslösen, dann wirst du um eine Flankenerkennung nicht
umhinkommen.
zb. LED wechselt von ein auf aus
zb. Cursor geht zum nächsten Menüpunkt
etc.
> Meiner Meinung nach erkenne ich den> Flankenwechsel mit einer kontinuierlichen Abfrage ala: if(!(PINB &> (1<<PINB3)))...
Und wie soll das gehen?
Um einen Wechsel zu erkennen, muss man den jetzigen Zustand mit einem
früheren Zustand vergleichen. Und das findet sich in deinem Code nun mal
nicht.
Wenn ich dir sage, dass in meinem Badezimmer jetzt das Licht brennt,
kannst du dann die Frage beantworten: Ist das Licht innerhalb der
letzten halben Stunde eingeschaltet worden?
Nein kannst du nicht.
Wenn ich dir aber die Zusatzinfo gebe, dass vor einer halben Stunde das
Licht noch nicht gebrannt hat, dann kannst du das entscheiden.
Wenn deine Aufgabe also lautet: Wenn das Licht eingeschaltet wird (und
nur dann. Nicht wenn das Licht einfach nur brennt), dann schalte die
Heizung aus, dann brauchst du beides: Den Zustand des Lichtes zum
Zeitpunkt an dem du das letzte mal nachgesehen hast und den jetzigen
Zustand. Aus der Differenz ergibt sich, ob in der Zwischenzeit das Licht
eingeschaltet wurde. Das Licht kann stundenlang brennen und du kannst
hunderte male feststellen dass es brennt. Interessant für die Aufgabe
ist nur das Erkennen des Wechsels.
Und nein. Das Ganze hat mit Entprellen erst mal an sich überhaupt nichts
zu tun. Das Entprellen sorgt nur dafür, dass du nicht auf jede kleine
Flanke hereinfällst, wie sie nun mal bei Tastern durch den Prellvorgang
unvermeidlich sind.
Herr Buchegger,
ich habe das Problem erkannt. Sie haben Recht.
Ich sehe aber gerade keine (andere) Möglichkeit den Flankenwechsel zu
detektieren.
Ich habe mir das immer so vorgestellt:
Mein Standardzustand:
PINB3 = 1;
Nach Tastendruck:
PINB3 = 0;
nichts anderes bedeutet die Abfrage: if(!(PINB &(1<<PINB3))), oder?
Meine Abfrage im Main Loop:
PINB3 == 0 ? debounce_switch() : 0;
Meine debounce_switch() soll lediglich einem nicht durch einen Menschen
ausgeführten Tastendruck filtern. Über die _delay_us() Zeit kann man
streiten.
Was habe ich sonst für Möglichkeiten den Flankenwechsel zu erkennen?
Michael schrieb:> Was habe ich sonst für Möglichkeiten den Flankenwechsel zu erkennen?
INdem man, wie gesagt, den jetzigen Zustand mit dem Zustand von der
letzen Abfrage vergleicht
1
uint8_tKeyPressedPrevious;
2
uint8_tKeyPressedNow;
3
4
KeyPressedPrevious=(PINB&(1<<PINB3);// erst mal für eine
5
// vernünftige Initialisierung sorgen
6
7
while(1){// und los gehts: Endlosschleife
8
9
// wie ist die Taste jetzt?
10
KeyPressedNow=(PINB&(1<<PINB3));
11
12
// unterscheidet isch das von der letzten Abfrage?
13
if(KeyPressedNow!=KeyPressedPrevious){
14
// jawohl, tut es!
15
// irgendwas muss also mit der Taste passiert sein.
16
// Entweder wurde sie gedrückt oder losgelassen.
17
// Was denn nun
18
if(!KeyPressedNow){
19
// Aha. Taste wurde gedrückt
20
....
21
....
22
}
23
24
// für den nächsten Schleifendurchgang den jetzigen
25
// Zustand der Tasten als den alten merken
26
KeyPressedPrevious=KeyPressedNow;
27
}
28
}
29
}
Das Entprellen kannst du jetzt selber mit dazu einbauen.
Flankenerkennung bedeutet immer, dass man den Zustand des Pins von 2
Zeitpunkten miteinander vergleichen muss! Dazu muss man sich den alten
dann eben in einer Variablen merken.