Forum: Mikrocontroller und Digitale Elektronik kann der Präprozessor runden?


von Randomize (Gast)


Lesenswert?

Hallo,

ich habe mir meinen UBRR Wert per define erstellt:
1
#define UART0_BAUD_RATE   9600
2
#define UBRR0_val        (F_CPU / (UART0_BAUD_RATE * 16L) - 1)
habe aber das problem, dass z.B. bei F_CPU = 3.68MHz durch integer 
abschneiden nur 22 rauskommt und nicht 23, wie es eigentlich sein 
sollte.
Versuche wie die folgenden verliefen leider ins Leere
1
#define UART0_BAUD_RATE   9600
2
#define UBRR0_val        (uint16_t) ((float) (F_CPU / (UART0_BAUD_RATE * 16L) - 1 + 0.5)))
3
#define UBRR0_val        (uint16_t) ((double) (F_CPU / (UART0_BAUD_RATE * 16L) - 1 + 0.5)))
4
[...]
Hat jemand 'ne idee für mich?
Besten Dank,
Martin

von Tobi (Gast)


Lesenswert?

Hi!

Versuchs mal a la:

#define UBBR_1200 (uint)((((20*F_CPU / (1200   << 4) ) +5 ) / 10) - 1)

MfG Tobi

von Falk B. (falk)


Lesenswert?

@ Randomize (Gast)

>habe aber das problem, dass z.B. bei F_CPU = 3.68MHz durch integer
>abschneiden nur 22 rauskommt und nicht 23, wie es eigentlich sein

F_CPU wird als Integer in der Einheit Hz angegeben!

#define F_CPU 3686400L

MfG
Falk

von Tobi (Gast)


Lesenswert?

Der Code gilt nur, wenn U2X gesetzt ist!

von Tobi (Gast)


Lesenswert?

Aber prinzipiell rundet man Ganzzahlig: (achte aber auf die 
Wertebereiche!)
(10*x + 5) / 10

von Randomize (Gast)


Lesenswert?

Moin Tobi,
dank Dir für den tip, das sollte fast klappen, ich vermute, Du meinst 
statt der 20 eine 10. Auf die Idee hätt man ja auch noch mal kommen 
können...

@Falk, das ist mir klar, hab mich da etwas ungenau ausgedrückt, sonst 
wär ich aber auch nicht auf die Werte 22 bzw 23 gekommen

von Simon K. (simon) Benutzerseite


Lesenswert?

Im übrigen hat die "Rundungsproblematik" nichts mit dem Präprozessor zu 
tun. Zumindest nicht, dass ich wüsste ;)

von Falk B. (falk)


Lesenswert?

@ Randomize (Gast)

>dank Dir für den tip, das sollte fast klappen, ich vermute, Du meinst
>statt der 20 eine 10. Auf die Idee hätt man ja auch noch mal kommen
>können...

Das ist Quark. Alle Welt macht das erfolgreich so

#define F_CPU 3686400L
#define BAUD 1200
#define UBRR (F_CPU / (16 * BAUD) -1)

rechnet immer richtig. Was nicht heisst, dass mit jedem Quarz jede 
Baudrate möglich ist.
Wichtig ist dabei das L am Ende, damit der Compiler mit long statt mit 
int rechnet.

MFG
Falk

von Tobi (Gast)


Lesenswert?

Da wird aber nicht gerundet. Bei F_CPU von z.B. 8 MHz kommt 416 raus. 
Die 2/3 sind abgeschnitten. Gerundet wären es also 417! Das kann 
entscheidend sein, ob eine Übertragung funktioniert, oder nicht!
Allerdings hätte das hier schon funktionieren müssen.

von Tobi (Gast)


Lesenswert?

Natürlich hab ich jetzt die -1 vergessen..

von Falk B. (falk)


Lesenswert?

@ Tobi (Gast)

>Da wird aber nicht gerundet. Bei F_CPU von z.B. 8 MHz kommt 416 raus.
>Die 2/3 sind abgeschnitten. Gerundet wären es also 417! Das kann
>entscheidend sein, ob eine Übertragung funktioniert, oder nicht!

Ja, aber dein Beispiel war mit ner Baudratenfrequenz!

>Allerdings hätte das hier schon funktionieren müssen.

MfG
Falk

von Emperor_L0ser (Gast)


Lesenswert?

ganz unabhängig von präprozessor, wenn man bei ganzzahligen datentypen 
ein mathematisch richtiges runden erreichen will rechnet man einfach 
IMMER + 0,5

bsp:
 2,3 + 1,1 = 3,4 -> 3 als ganzzahl
  wenn man jetzt noch 0,5 aufrechnet: 3,4 + 0,5 = 3,9
  das wird immer noch zu 3 abgeschnitten, also weiterhin richtig

 2,3 + 1,3 = 3,6 -> 3 als ganzzahl
  wieder +0,5 -> 4,1, das wird zu 4 verkürzt und siehe da, richtig
  gerundet

mfg Emperor_L0ser

von crazy horse (Gast)


Lesenswert?

der gute Falk macht doch in letzter Zeit gerne mal "immer" und 
"100%"-Aussagen, sind meist mit Vorsicht zu geniessen :-)

von Falk B. (falk)


Lesenswert?

Aber für die Berechnung von UBBR wird das komplizierter. So vielleicht?

#define UBRR ((F_CPU + (8*BAUD)) / (16 * BAUD ) -1)

Aber das entbindet den Programmierer noch nicht von der Prüfung des 
Frequenzfehlers! Vielleicht ein Makro?

MfG
Falk

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.