Guten Tag, kenn jemand eine International geltende Regel zum Runden der UART Baudrate? Im konkreten Fall komm als UBBR = Systemtakt / 16* Baud -1 = 218,5 Wird nun auf 219 aufgerundet oder auf 218 abgerundet indem die Nachkommastgelle einfach abgeschnitten wird? Ich brauche eine Handfeste Regel. Danke Gruß Thomas
Thomas Nurul schrieb: > Ich brauche eine Handfeste Regel. dann schau in einem C buch nach. Dort steht je nach Datentyp drin wie gerechnet wird. Wichtig dazu ist dann die Operator-Reihenfolge. > Systemtakt / 16* Baud -1 = 218,5 Systemtakt wird wohl int sein dann erfolgt die Division durch 16 was als Int augeführt wird. dann wird Baud multipliziert was auch als int gemacht wird und dann wird die 1 abzogen. Dabei kommt also überhaupt keine Nachkommestellen raus, weil alles als int gerechnet wird.
@Thomas Nurul (Gast) >kenn jemand eine International geltende Regel zum Runden der UART >Baudrate? Gibt es nicht, braucht auch keiner. >Im konkreten Fall komm als UBBR = Systemtakt / 16* Baud -1 = 218,5 Jo mei, was passiert, wenn du auf 218 oder 219 rundest? Es entsteht ein sagenhafter Fehler von +/-0,228%. UARTs sollten nach Möglichkeit mit weniger als +/-1% Fehler laufen, in bestimmten Fällen geht es auch bis +/-3%. Siehe Baudratenquarz >Wird nun auf 219 aufgerundet oder auf 218 abgerundet indem die >Nachkommastgelle einfach abgeschnitten wird? Als Integerrechung wird immer abgeschnitten. >Ich brauche eine Handfeste Regel. Du brauchst mal Entspannung.
Du denkst falsch rum... Die Baudrate ergibt sich aus UBBR und dem Systemtakt, und ist immer ganzzahlig. Da kann und muß überhaupt nichts gerundet werden. Oliver
Hallo Thomas, ich programmiere gerade mit Assembler und schreibe deshalb:
1 | .set F_CPU = 20000000 |
2 | .set BAUDRATE = 115200 |
3 | .set BAUD_SETTING = long( (F_CPU + BAUDRATE*4) /(BAUDRATE*8) -1 ) |
Hier wird der für das 16Bit Register UBBR der Wert BAUD_SETTING direkt berechnet und schon eine Aufrundung mit dem Faktor 0.5 einbezogen. Wenn der Preprozessor Float unterschützt, schreibt man einfach:
1 | const uint32_t F_CPU = 20000000UL; |
2 | const uint32_t BAUDRATE = 115200; |
3 | const uint16_t BAUD_SETTING = uint32_t((1.0 *F_CPU /8 /BAUDRATE +.5) -1); |
Das Ergebnis ist in beiden Fällen BAUD_SETTING = (22 -1).
Nachtrag, // UCSR0A - U2X0: Double the USART Transmission Speed der Uart0 läuft im Modus UCSR0A.U2X0 = 1;
Thomas Nurul schrieb: > kenn jemand eine International geltende Regel zum Runden der UART > Baudrate? Belege das Baudratenregister so, dass der Baudratenfehler minimal wird. Dafür braucht man nur ein bisschen Menschenverstand und keine internationale Vereinbarung.
Falk B. schrieb: > Als Integerrechung wird immer abgeschnitten. ... was einen aber nicht daran hindern kann, vor der Division zum Dividend die Hälfe des Divisors hinzu zu addieren. De facto läuft das dann etwa auf das Gleiche wie eine Rundung bei der Division reeller Zahlen hinaus.
Ich würde bei INT immer mit der etwas höheren Rate abtasten. Allerdings ist das nicht nötigt, wenn man es richtig programmiert: Man benutzt einen höher Aufgelösten Timer, von dem man immer nur die oberen BITs anschaut, um zu Teilen. So ist es möglich automatisch durch z.B. 133.1/3 zu teilen. Der Zähler macht einmal 134 und zweimal 133.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.