Forum: Mikrocontroller und Digitale Elektronik Frage zu C Syntax


von tsag (Gast)


Lesenswert?

Tach tach,

och arbeite gerade das Kapitel Tasten entprellen durch 
(http://www.mikrocontroller.net/articles/Entprellung) und bin auf 
folgende Zeile bei Herrn Dannegger in der Komfort-Routine gestoßen:
1
TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
Meine Frage:
Was bedeutet in diesem Zusammenhang (uint8_t)(int16_t)?

Ist das ein Platzhalter für eine 24bit-Konstante (0xfffff oder 
0x000000)?

Grüße

von Peter II (Gast)


Lesenswert?

tsag schrieb:
> Was bedeutet in diesem Zusammenhang (uint8_t)(int16_t)?
>
> Ist das ein Platzhalter für eine 24bit-Konstante (0xfffff oder
> 0x000000)?

nein. das sind Casts.

warum 2 verwenden werden kann ich spontan auch nicht  sagen. Erst wird 
mit int16_t gerechnet und dann wird, damit keine Warnung vom Compiler 
kommt auf uint8_t gecastet.

von asdf (Gast)


Lesenswert?

tsag schrieb:
> Ist das ein Platzhalter für eine 24bit-Konstante (0xfffff oder
> 0x000000)?

Mal abgesehen von irgendwelcher C-Syntax: Überleg mal, wie sich TCNT0 
und ein 24bit Wert vertragen würden.

von Carsten P. (r2pi)


Lesenswert?

Na ja, je nach F_CPU... Sonst steht da ja 1024 / 1000 + 0.5. (Also 
1,424)

Ich weiß schon, wieso ich in Mathe-Formeln und in Code-Zeilen lieber 
mehr als weniger Klammern schreibe und Const-Klassen so mag ;)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:

> warum 2 verwenden werden kann ich spontan auch nicht  sagen. Erst wird
> mit int16_t gerechnet

nicht ganz.
Teile der Berechnung werden in double durchgeführt
danach wird das Ergebnis auf einen 16 Bit signed int gecastet.

Und von diesem 16 Bit signed int wird dann ein unsigned 8 Bit Wert 
gebildet.

Peter wollte wahrscheinlich sicher gehen, dass erst die Reduktion von 
double auf int gemacht wird und erst dann das Vorzeichen weggecastet 
wird.

von Rene H. (Gast)


Lesenswert?

Karl H. schrieb:
> Peter wollte wahrscheinlich sicher gehen, dass erst die Reduktion von
> double auf int gemacht wird und erst dann das Vorzeichen weggecastet
> wird.

<keine Kritik an peda>
An so einer Stelle wäre ein informativer Kommentar sehr gut angebracht
</keine Kritik an peda>

Grüsse,
René

von Yalu X. (yalu) (Moderator)


Lesenswert?

Statt
1
TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms

hätte man auch einfach schreiben können:
1
TCNT0 = (uint8_t)(256 - F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms

Aber dann hätte es ja jeder kapiert ;-)

F_CPU / 1024 ist die Timer-Taktfrequenz nach dem Vorteiler durch 1024.
Besser hätte man hier F_CPU / 1024.0 geschrieben, damit auch die
Division in Floating-Point berechnet wird, was in einigen Fällen ein
etwas genaueres Ergebnis liefert.

F_CPU / 1024 * 10e-3 ist die Anzahl der Timer-Taktperioden, die zusammen
den gewünschten 10 ms entsprechen.

256 - F_CPU / 1024 * 10e-3 ist der ungerundete Startwert für den Timer,
so dass dieser nach 10 ms überläuft, also von 255 nach 0 springt, und
damit einen Interrupt auslöst.

(uint8_t) konvertiert diesen Startwert – passend zum 8-Bit-Register
TCNT0 – in einen vorzeichenlosen 8-Bit-Integer-Wert, wobei eventuelle
Nachkommastellen abgeschnitten werden. Damit würde der Wert also immer
auf die nächstkleinere ganze Zahl abgerundet werden. Um ein Runden zur
nächstliegenden ganzen Zahl zur erreichen, wird vor dem Abrunden durch
(uint8_t) einfach noch 0.5 addiert.

Rene H. schrieb:
> An so einer Stelle wäre ein informativer Kommentar sehr gut angebracht

Der Kommentar steht im zugehörigen Thread, auf dem im Artikel verlinkt
wird:

  Beitrag "Re: Universelle Tastenabfrage"

Ok, im Quellcode hätte er auch nicht geschadet :)

: Bearbeitet durch Moderator
von Karl H. (kbuchegg)


Lesenswert?

Und zu guter letzt:
Das ist das unkritischste an der ganzen Entprellung und meistens die 
erste Zeile, die bei mir wieder rausfliegt.

Denn den Timer gibt es normalerweise sowieso schon im Programm in 
Verwendung und den stell ich mir so ein, wie er für mich passend ist. Ob 
die ISR im 10ms Rhytmus aufgerufen wird, oder ob das 5ms oder doch 20ms 
oder irgendwas dazwischen, ist für die Entprellung völlig wurscht. Da 
richte ich mich nach dem, wofür ich den Timer dann in erster Linie 
brauchen werde.

von W.S. (Gast)


Lesenswert?

tsag schrieb:
> och arbeite gerade das Kapitel Tasten entprellen durch

und du bist der Ansicht, daß es eine Programmier-Frage sei? Nein, ist es 
nicht. Es ist ein logisches Problem, das eigentlich völlig unabhängig 
ist von jeglicher Programmiersprache.

Eigentlich sollte ein jeder, der in's Mikrocontroller-Geschäft 
einsteigen will, die Entprellung von Tasten als eine Grund-Übung aus 
eigener Kraft beherrschen. Also überleg dir lieber die Grundprinzipien, 
als über spezielle Formulierungen von Peter dir den Kopf zu zerbrechen.

Im Grunde ist es ja so unsäglich einfach:
1. Erkennen des Gedrücktwerdens einer Taste (also ungedrückt-->gedrückt)
2. Unterdrücken von Prellerscheinungen
3. Erkennen des langen Gedrücktseins ohne Unterbrechungen als Bsasis für 
eine Repetierfunktion (fakultativ)

W.S.

von Peter D. (peda)


Lesenswert?

W.S. schrieb:
> 1. Erkennen des Gedrücktwerdens einer Taste (also ungedrückt-->gedrückt)

Tasten können aber auch beim Gedrückt halten bzw. Loslassen prellen / 
stören.
Besser ist daher ein gleitender Mittelwert z.B. über 4 Samples, der bei 
0,0 bzw. 1,0 ein Flag setzt/rücksetzt. Das Flag kippen kann man bequemer 
Weise gleich als Aktion speichern.

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.