Fragen zur Taster Entprellung von PeDa

Gast #4495896
Lesenswert?

Hi,
Ich hab grad mal versucht, die Tasterentprellung von PeDa in der 
C-Version nachzuvollziehen und hab zwei Fragen dazu:

1.) Im Worst-Case wird der Tastendruck erst "prelldauer" + 4*10ms später 
registriert, richtig? Für mich liest sich das so, dass erst, wenn 4x 
nacheinander der gleiche Zustand gelesen wird, dieser als gültig 
angenommen wird. Und gelesen wird alle 10ms. Stimmt das so?

2.) cli() wird in jedem Schleifendurchlauf der main 4x aufgerufen - 
wahrscheinlich in deutlich kürzeren Intervallen, als 10ms. Bei jedem 
dieser Aufrufe werden doch die Interrupts gestoppt. Wieso wird dann die 
Interrupt Routine überhaupt mal aufgerufen?!

Viele Grüße
#4495921
Lesenswert?

avr schrieb:

> 1.) Im Worst-Case wird der Tastendruck erst "prelldauer" + 4*10ms später
> registriert, richtig? Für mich liest sich das so, dass erst, wenn 4x
> nacheinander der gleiche Zustand gelesen wird, dieser als gültig
> angenommen wird. Und gelesen wird alle 10ms. Stimmt das so?

Ja, aber nicht nur im Worst case.

> 2.) cli() wird in jedem Schleifendurchlauf der main 4x aufgerufen -
> wahrscheinlich in deutlich kürzeren Intervallen, als 10ms. Bei jedem
> dieser Aufrufe werden doch die Interrupts gestoppt. Wieso wird dann die
> Interrupt Routine überhaupt mal aufgerufen?!

Wo steht da ein cli()? Auf welche Beschreibung beziehst Du Dich? Ich 
verwende die Peda Routine öfters, aber ein cli habe ich nirgends im HP 
stehen.

Gruz
Andreas
Gast #4496302
Lesenswert?

> Ja, aber nicht nur im Worst case.

Naja, es kann ja auch sein, dass durch Zufall während dem Prellen schon 
ein oder zwei mal der richtige Zustand gelesen wird, dann müsste man 
nach der Prellzeit nur noch 3 bzw 2 mal 10ms warten.

>> 2.) cli() wird in jedem Schleifendurchlauf der main 4x aufgerufen -
>> wahrscheinlich in deutlich kürzeren Intervallen, als 10ms. Bei jedem
>> dieser Aufrufe werden doch die Interrupts gestoppt. Wieso wird dann die
>> Interrupt Routine überhaupt mal aufgerufen?!
>
> Wo steht da ein cli()? Auf welche Beschreibung beziehst Du Dich? Ich
> verwende die Peda Routine öfters, aber ein cli habe ich nirgends im HP
> stehen.
>

Also nicht direkt, aber es wird ja get_key_short aufgerufen, das 
wiederum get_key_press aufruft, das cli() aufruft. Auf diese Art kommt 
es zu 4 Aufrufen von cli().
#4496335
Lesenswert?

> ... Mit den 4 Aufrufen von cli() ..

... nach denen dann immer eine Funktion gerufen wird, die eine sei() 
beinhaltet.

Und während der cli()-sei()-Phase werden anfallende Timer-INT's nicht 
vergessen, sondern nur (hier nicht mal 1μs) verzögert. Es geht nur 
darum, daß die Leseroutine ungestört Änderungen am "Zustand" der 
Tastenabfrage machen kann.
Gast #4496394
Lesenswert?

Sorry, dachte irgendwie, ich hätte den Link gepostet. Es geht um das 
hier: 
http://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29

@jcw2: Ahh, das wusste ich nicht, dass die Interrupts nur verzögert 
werden. Danke! Kann ich mir das dann so vorstellen, dass der Timer 
stehen bleibt, aber nicht zurückgesetzt wird, und bei Aufruf sei() 
wieder weiter läuft?
Gast #4496508
Lesenswert?

Okay. Habe jetzt gerade gelesen, dass der Timer ja trotzdem weiter 
läuft. Wenn der Timer dann also einen Interrupt auslösen würde, aber 
nicht kann, weil cli() aufgerufen wurde, wird dieser Interrupt 
gespeichert und sofort ausgeführt, sobald sei() aufgerufen wird, 
richtig?

Was, wenn in der Zeit mehrere Interrupts passieren, zB von 2 
verschiedenen Timern? Wird dann einer "vergessen", oder gibts da so ne 
Art Queue? Wie läuft das?
#4496511
Lesenswert?

> Kann ich mir das dann so vorstellen, dass der Timer stehen bleibt,
> aber nicht zurückgesetzt wird, und bei Aufruf sei() wieder weiter
> läuft?

Wenn der Timer überläuft, dann wird lediglich ein Bit im TIFRn-Register 
gesetzt. Und (stark vereinfacht) prüft die CPU nach jeder 
Befehlausführung ob das I-Flag gesetzt ist, also Interrupts ausgeführt 
werden sollen, und dann ob es anstehende Interrupts gibt, also z.B. 
TIFR0-TOV0 gesetzt ist. Wenn ja wird
1
cli
2
call Timer0_Int_vector
ausgeführt. Letzteres ist der Bereich ab 0x0000 im Flash, wo dann 
üblicherweise ein Sprung zur wirklichen ISR steht. Die ISR endet dann 
mit einen reti, was das I-Flag wieder setzt und zur unterbrochenen 
Stelle zurückkehrt. Und der Fakt, daß nach Befehlsausführung geprüft 
wird, führt dazu, daß nach jedem Interrupt mindesten ein Befehl 
ausgeführt wird, selbst wenn andere Interrupt-Requests anstehen.
Gast #4496537
Lesenswert?

Vielen Dank schonmal für die Infos. Eine OT Frage hab ich noch: Macht es 
(von außen betrachtet) einen Unterschied, ob ich
a) TCNT0 preloade, überlaufen lasse und dann ISR(TIMER0_OVF_vect) 
aufrufe, oder
b) OCR0 setze, TCNT0 bei Match zurücksetze und dann 
ISR(TIMER0_COMP_vect) aufrufe?
#4496630
Lesenswert?

Naja, wenn es nicht einmalig sein soll, dann hat die Preload-Variante 
den Nachteil, daß der Preliad für den nächsten Zyklus in der ISR 
passiert, die ja nicht sofort laufen muß (wegen cli USW.), und auch wenn 
man den Preload auf TCNTn aufaddiert, bleibt ein Jitter den die 
Hardware-Variante CTC nicht hat. Nur wenn man einfach nur eine grobe 
Zeitbasis z.B. für PeDa braucht und/oder den Timer durchlaufen läst, 
würde ich auf CTC-Mode verzichten.
Wenn ich z.B. exakt 1ms brauche,
 dann 16MHz Quarz, Timer0 CTC /64 OCR0A=249
#4496650
Lesenswert?

damit mir aber kein IRQ auch verzögert durch die Lappen geht, ich mache 
ja noch IRMP, zähle nach IRMP hoch bis 10ms und verzweige dann bei 10ms 
in Tastenauslesen, so habe ich keine 2 IRQ.

Es können mir dann in der Tastenroutine IRMP IRQ durch die Lappen gehen, 
hatte mal versucht im long IRQ Teil alle 10ms den IRQ wieder freizugeben 
mit sei() und bei Wiedereintritt durch ein Flag an der long IRQ 10ms 
vorbeizuhüpfen, ich habe das aber noch nicht vollständig ergründet, 
irgendwie funkioniert es.
#4496662
Lesenswert?

16M  8  250 = 1k
Und von 0 ausgehend ist der 250te Takt der mit dem Wert 249 in TCNT0. 
CTC will den TOP-Wert im OCR0A, also 249.

Bei halbem Takt muß bis 125 gezählt werden, TOP ist also 124.

Wenn das 8MHz aus dem internen RC-Oszilator sind, dann ist es aber egal 
ob 124 oder 126 ;-)
#4496801
Lesenswert?

Die 10ms von PeDa sind ja auch nur eine Hausmarke. Das ist eher das 
Raster für eine Zeitsteuerung, die man oft auch noch braucht. Wenn die 
Taster nicht zu schlecht sind und man keine 40ms Zeit hat zum Drücken 
(sind ja nur 25 Anschläge/s ;-), dann dürfen es auch 5ms sein, oder eben 
20ms.
#4496920
Lesenswert?

Carl D. schrieb:
> Die 10ms von PeDa sind ja auch nur eine Hausmarke. Das ist eher das
> Raster für eine Zeitsteuerung, die man oft auch noch braucht. Wenn die
> Taster nicht zu schlecht sind und man keine 40ms Zeit hat zum Drücken
> (sind ja nur 25 Anschläge/s ;-), dann dürfen es auch 5ms sein, oder eben
> 20ms.

genau aus diesem Grund nimmt man ja 10ms Interrupts, nicht wegen der 
Taster, die funktionieren auch mit 8, 15, 20ms, aber alle 10ms einen 
Counter hochzählen ist ne schöe Zeitbasis.

Ich habe z.B. Aufgaben verteilt,
alle 330ms LCD aktualisieren, egal wann ich ins Schattenram schreibe, 
wozu öfter LCD update machen?
alle 250ms WS2812b aktualisieren
alle Minute bei >500ms prüfen ob was anderes nicht zeitkritisches zu 
machen ist
#4496987
Lesenswert?

avr schrieb:
> @jar: Also du zählst dann in der ISR eine Variable hoch bis 33 und

genau, so flimmert das LCD weniger und trotzdem wird die aktuelle 
Uhrzeit geschrieben und ich brauche nie drüber nachzudenken das zuviele 
Schreibvorgänge aufs LCD zu verschiedensten Zeiten von verschiedenen 
Orten kommen, wäre ja auch doof mal Fenster hoch zu schreiben und kurz 
danach die Uhrzeit zu aktualisieren oder die Temperatur.
#4496994
Lesenswert?

avr schrieb:
> Ergo, du sparst dir einen weiteren Timer

Das ist Zweck der Übung. Aus dem schnellsten notwendigen Timer-Interrupt 
kann man durch Zählvariablen verschiedene Zeittakte ableiten. Dies spart 
Interrupts und die damit verbundenen Aufrufzeiten (Registersicherung 
usw).

Setzt man in der ISR für die verschienen abgeleiteten Takte Flags 
(Semaphores, Merker), so können die Jobs in der Mainloop laufen. Dies 
spart Rechenzeit in der ISR, was die Verzögerung weiterer Interrupts 
gering hält.

...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren