mikrocontroller.net

Forum: Compiler & IDEs Was genau macht (uint16_t) ((uint32_t) F_CPU/BAUDRATE) ?


Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend,


ich versuche gerade den Software-Uart-Code vom Roboternetz
( http://www.rn-wissen.de/index.php/Software-UART_mit_avr-gcc )
auf einem ATtiny25 zum laufen zu bekommen und verstehe die Funktion 
folgender Zeile nicht ganz:


OCR1A  = (uint16_t) ((uint32_t) F_CPU/BAUDRATE);

Ich kenne diese Typedefs bis jetzt nur aus den herkömmlichen 
Variablendeklarationen, aber das hier scheint etwas Anderes zu sein.

Meine Vermutung: "(uint32_t) F_CPU/BAUDRATE" teilt dem Compiler mit, 
dass er 32 Bit für den Wert reservieren soll, weiter links wird dann 
abgerundet.
Aber man merkt wohl, dass ich das Konzept noch nicht so ganz durchschaut 
habe.

Kann mir jemand etwas genauer erklären, was hier geschieht?

Vielen Dank schonmal!

Marc

Autor: Naja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich kenne diese Typedefs...
Welche Typedefs. Ich sehe hier keines.

>... bis jetzt nur aus den herkömmlichen Variablendeklarationen
Typedefs werden in Typdeklarationen verwendet, nicht in 
Variablendeklarationen.
Der von Dir gezeigte Code aber ist eine Zuweisung; weder eine Variablen- 
noch eine Typdeklaration.

>..."(uint32_t) F_CPU/BAUDRATE" teilt dem Compiler mit, dass er 32 Bit für >den 
Wert reservieren...
Nein. Hier wird nichts "reserviert", sofern man unter reservieren das im 
Computerbereich übliche vorbehalten von RAM-Bereichen versteht.

Vielmehr wird gesagt, dass F_CPU ein uint32_t ist.


>...weiter links wird dann abgerundet.
Hier wird nirgends gerundet, weder links, noch rechts, noch oben, noch 
unten.

Aber das Ergebnis der Division von F_CPU durch BAUDRATE wird in ein 
uint16_t umgewandelt bevor es OCR1A zugewiesen wird.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>OCR1A  = (uint16_t) ((uint32_t) F_CPU/BAUDRATE);

>F_CPU/BAUDRATE
Berechnet eine Division.
Damit das Ergebnis auch noch sinnvoll ist, wird F_CPU auf uint32_t 
gecastet, also sein Zahlenbreich vergrößert.

Damit das Ergebnis auch wieder ins OCR1A-Register passt, wird zurück auf 
uint16_t gecastet. Sollte aber unnötig sein.
Sofern F_CPU und BAUDRATE keine Variablen sind, sollte man sich da 
Gecaste sparen können.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>... bis jetzt nur aus den herkömmlichen Variablendeklarationen
>Typedefs werden in Typdeklarationen verwendet, nicht in
>Variablendeklarationen.
>Der von Dir gezeigte Code aber ist eine Zuweisung; weder eine Variablen-
>noch eine Typdeklaration.

Typischer Fall von Verwechslung mangels soliden Grundwissens. Danke für 
die Richtigstellung - ich muss das alles dringend aufarbeiten.

>Damit das Ergebnis auch noch sinnvoll ist, wird F_CPU auf uint32_t
>gecastet, also sein Zahlenbreich vergrößert.

Ok, jetzt wird's langsam klar, vielen Dank! Und mit "casting" hab' ich 
das richtige Stichwort.

Eine Frage noch: Bezieht sich das casting allein auf F_CPU oder auf das 
Erebnis der Division?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marc schrieb:

> Ok, jetzt wird's langsam klar, vielen Dank! Und mit "casting" hab' ich
> das richtige Stichwort.
>
> Eine Frage noch: Bezieht sich das casting allein auf F_CPU oder auf das
> Erebnis der Division?

Operatoren Reihenfolge.(Stichwort für google: "operator precedence C")

http://www.difranco.net/cop2220/op-prec.htm

Casts stehen in der Hierarchie fast ganz oben, binden also sehr stark. 
Dementsprechend bezieht sich dieser Cast nur auf F_CPU


(Wobei diese Casts in diesem Ausdruck überflüssig sind. Der Ausdruck 
würde auch dann richtig berechnet, wenn keine Casts da wären. In diesem 
Fall sollte man sich an die Regel halten: Caste nur dann, wenn es 
wirklich unbedingt notwendig ist, ansonsten lass den Compiler seine 
Arbeit tun)

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>http://www.difranco.net/cop2220/op-prec.htm
>
>Casts stehen in der Hierarchie fast ganz oben, binden also sehr stark.
>Dementsprechend bezieht sich dieser Cast auf F_CPU

Ok!

Vielen Dank und einen sonnigen Tag noch!

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die division wird aber auch in 32bit durchgeführt? oder nicht? eine 
Komponente hat ja 32Bit, erst das ergebins wird auch 16Bit 
zurechtgestutzt..

PS:
die uart Routinen von hier sind wesentlich besser...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... ... schrieb:
> die division wird aber auch in 32bit durchgeführt? oder nicht? eine
> Komponente hat ja 32Bit, erst das ergebins wird auch 16Bit
> zurechtgestutzt..

Ja.

An dieser Stelle wird es Zeit den obligaten Hinweis zu geben:
Du brauchst vernünftige Literatur (zb einen Kernighan&Ritchie).
Da steht das alles (und noch viel, viel mehr) drinnen.

Ohne Unterlagen kann man eine Sprache wie C nicht vernünftig erlernen. 
Da gibt es viel zu viele kleine (und auch größere) Stolpersteine.

Autor: JojoS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define F_CPU 1000000UL

die Typisierung 'UL' würde das casten auch überflüssig machen, könnte 
aber zu Fehlern führen wenn es dann fehlt. Wenn man verschiedene 
Quelltext mixt dürfte das explizite casten im Makro narrensicherer sein.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
JojoS schrieb:

> aber zu Fehlern führen wenn es dann fehlt. Wenn man verschiedene
> Quelltext mixt dürfte das explizite casten im Makro narrensicherer sein.

Grundsätzlich ja.
Aber nicht in diesem konkreten Fall. Hier gibt es keine Möglichkeit 
eines Überlaufs. Durch die Division wird das Ergebnis ja nur kleiner als 
die Ausgansgzahlen. Wenn die Ausgangszahlen int sind, dann wird auch das 
Ergebnis in int reinpassen. Ist eine der Ausgangszahlen zu groß für 
einen int, dann hebt der Compiler diese Zahl sowieso von sich aus von 
int eine Stufe höher (auf long). Das einzige was passieren könnte ist, 
dass man mit signed/unsigned ein Problem bekommt. Allerdings wird nach 
menschlichem Ermessen weder F_CPU noch BAUDRATE je negativ werden, wobei 
dann allerdings die Frage interessant wäre was denn das richtige 
Ergebnis sei. Bleibt also nur noch der Fall, dass der Compiler eine der 
beiden Zahlen aufgrund des Zahlenwertes als long ansieht, obowhl er das 
nicht müsste, weil es sich in einem unsigned int noch ausgehen würde. 
Der Fall ist aber müssig, da durch den Cast die ganze Berechnung auf 
jeden Fall (selbst bei kleinen Zahlen, ok, geschenkt F_CPU wird höchst 
wahrscheinlich auf AVR immer einen int sprengen) auf long angehoben 
wurde.

Laufzeitproblem ist das allerdings auch keines. Sind alles konstante 
Zahlenwerte, die der Compiler im Constant-Folding auswerten wird.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
[OT]

>Vielen Dank und einen sonnigen Tag noch!

Bei uns regnet es...

[/OT]

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.