Forum: Mikrocontroller und Digitale Elektronik C Syntax & AVRStudio4


von college (Gast)


Lesenswert?

guten abend, die herren,

ich hätte ein paar fragen zu c-syntax und avr-studio4.
auf dieser webseite habe ich  im kapitel "softwareentprellung", das 
quellcode von Peter Dannegger gefunden. das quellcode enthält folgende 
zeile:
TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
kann jemand diese zeile interprätieren?

beim simulieren würde ich gerne die zwischenwerte meiner variablen, die 
ich deklariert habe, sehen. bis jetzt kann ich nur die zustende von den 
ports anschauen. gibt es irgendein zusätzliches tool, das sowas 
ermöglicht, oder kann man was an den einstellungen ändern?

danke im voraus

von holger (Gast)


Lesenswert?

>TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
>kann jemand diese zeile interprätieren?

interpr*e*tieren

Nee, weil sie Fehler enthält.
(int16_t)-(....)

Zeilen aus Codes nicht abtippen !
1:1 kopieren ist besser.

von STK500-Besitzer (Gast)


Lesenswert?

>TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);

erst mal sind da zwei Casts: die Berechnung -(F_CPU / 1024 * 10e-3 + 
0.5) wird zu einem int16 (word) gemacht und dann zu einem uint8 (byte).
Die Berchnung selbst ist dann wieder was mit einer Fließkommazahl.

Der Timer wird auf einen bestimmten Wert gesetzt.

von college (Gast)


Lesenswert?

kann man das nicht irgendwie einfacher und verständlicher schreiben, 
weil diese schreibweise hatte ich nie gesehen.
und die 2-te frage, hat jemand eine idee?

von STK500-Besitzer (Gast)


Lesenswert?

>und die 2-te frage, hat jemand eine idee?

Nö. Du könntest höchstens die Berechnung in mehrere Schritte (und 
Variablen) aufteilen.

von college (Gast)


Lesenswert?

die zweite frage war zu avr-studio4, beim testen will ich die werte von 
meinen variablen. das vereinfacht die fehlersucher erheblich (zumindest 
für mich) ;)

von Dietmar E (Gast)


Lesenswert?

> kann jemand diese zeile interprätieren?

Schlecht lesbarer Code.

> TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);

"F_CPU / 1024" wird vermutlich dort stehen, weil ein Timer mit 
1024er-Hardware-Vorteiler benutzt wird, d.h. F_CPU / 1024 ist die 
Geschwindigkeit, mit der der Timer zählt. Anders ausgedrückt: dieser 
Term entspricht "Impulse pro Sekunde".

"* 10e-3" ist eine andere Schreibweise für "/ 1000". Wenn man die 
Impulse pro Sekunde durch 1000 teilt, erhält man die Impulse pro ms. In 
dieser zeitlichen Grössenordnung, eine Millisekunde, wird gerne 
entprellt: Der Timer wird so eingestellt, dass in 1 ms ein Interrupt 
kommt.

+ 0.5 ist eine (überflüssige) mathematisch korrekte Rundung: die 
Teilerei ergibt eine Fliesskommazahl und der Compiler muss daraus für 
die Zuweisung an TCNTO eine Integer-Zahl machen. Indem man vorher 0.5 
addiert, wird mathematisch korrekt gerundet Beispiele: aus 10.1 wird 10 
(10.1 + 0.5 = 10.6, davon bleibt bei Umwandlung zu Integer der 
Vorkommateil, die 10). Aus 10.6 wird korrekterweise 11 (10.6 + 0.5 = 
11.1, davon bleibt Vorkommaanteil 11).

Das "-" sorgt schliesslich dafür, dass nicht der ausgerechnete Wert 
(Impulse pro ms) in's Timer-Register kommt, sondern die gleich grosse 
Differenz zum Überlauf des Timers. Beispiel: Man rechnet 10 Impulse/ms 
aus. Das 8-Bit-Register läuft bei 255 über, danach kommt 0. Also wird 
der Wert 246 in's Timer-Register geschrieben: nach 10 Impulsen, also in 
1 ms, kommt dann der Überlauf zu 0 und damit der gewünschte Interrupt. 
Dass "-x" dem Wert "Überlauf - x" entspricht, hängt mit binären 
Rechenregeln zusammen. Zum Nachrechnen: -10 ist definiert als das 
Zweierkomplement von 10, binär 1111111111110110. Wenn man die unteren 8 
Bit davon als vorzeichenlose Integer interpretiert (1111110110), ergibt 
das 246.

> kann man das nicht irgendwie einfacher und verständlicher schreiben

Vieleicht so:

  #define TIMER_PRESCALER     1024
  #define TIMER_OVERFLOW      256
  #define TIMER_TICKS_PER_MS  ((F_CPU / TIMER_PRESCALER) / 1000)

  TCNT0 = TIMER_OVERFLOW - TIMER_TICKS_PER_MS;

von Dietmar E (Gast)


Lesenswert?

Wenn F_CPU sehr niedrig ist, einen anderen Vorteiler nehmen, damit es 
nicht auf genaue Rechnug ankommt (also nicht drei Impulse pro ms oder 
etwas in der Art).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dietmar E wrote:

> "* 10e-3" ist eine andere Schreibweise für "/ 1000".

Nein, es ist eine irreführende Schreibweise für »/ 100.0«.  Offenbar
soll der Timer mit 10 ms Taktperiode laufen.

Man beachte auch, dass »/ 100« etwas anderes als »/ 100.0« hier
bewirken würde.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:

> Nein, es ist eine irreführende Schreibweise für »/ 100.0«.

Die Intention sehe ich natürlich schon (Darstellung des Intervalls
in Millisekunden).  Dafür hätte man lesbarer schreiben können:
1
#define TIME_MS(x) ((x) * 1e-3)
2
3
... * TIME_MS(10)

von Dietmar E (Gast)


Lesenswert?

> es ist eine irreführende Schreibweise für »/ 100.0«.

Oops. Da hat er mich erwischt. Wer rechnet schon mit 10 vor dem Komma 
bei Exponentialschreibweise.

von Peter D. (peda)


Lesenswert?

Also im Original steht ja auch ein Kommentar dahinter:
1
TCNT0 = (u8)(s16)-(XTAL / 1024 * 10e-3 + 0.5);        // preload for 10ms
Man könnte aber auch schreiben:
1
#define ms e-3
2
3
TCNT0 = (u8)(s16)-(XTAL / 1024 * 10ms + 0.5);        // preload for 10ms


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Das lässt sich zwar besser lesen, ist aber von den Seiteneffekten für
den nichtsahnenden Nutzer fies.

von college (Gast)


Lesenswert?

ich bedanke mich bei allen, die mir geholfen haben. echt netter forum. 
weiter so.

MfG ;)

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.