Hallo zusammen, in manchen Bibliotheken sehe ich öfter folgendes : In der Headerdatei: #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden In der C Datei folgendes: UBRR0H = (unsigned char)(UBRR_VAL>>8); // Baudrate einstellen UBRR0L = (unsigned char)(UBRR_VAL); Ich frage mich gerade was da wieso die das so Programmieren. Hat jemand ne Ahnung? Grüße Alex
Also dir zu helfen ist gerade nicht ganz einfach. Wenn man einfach auf deine Frage antwortet Älex schrieb: > Hat jemand ne Ahnung? käme wohl "ja" als Antwort. Verstehst du was an dem Code nicht? Und wenn nein: was? Gruß
Älex schrieb: > Ich frage mich gerade was da wieso die das so Programmieren. Hat jemand > ne Ahnung? Warum die was Programmieren? Meinst du warum man erst UBRR_VAL im Header ausrechnet und nicht direkt in die C-Datei einsetzt? Ganz einfach: Nicht jeder µC wird mit der gleichen Frequenz( und Baud-Rate) betrieben. So wie hier gezeigt wird der UBRR_VAL immer von der vorgegebenen Frequenz (und Baud-Rate) abhängen was wiederum bedeutet dass man immer den gleichen Code verwenden kann und nur die Freuquenz( und Baudrate) richtig einstellen muss. Arbeitserleichterung nennt man das auch ;)
Entschuldigt ich habe glaube ich die Frage falsch gestellt :). Ich meine warum die diese Formel für UBRR_VAL verwenden. Im Datenblatt steht ja UBRRn = (fCLKio / 16BAUD) - 1 das entspricht ja nicht ((F_CPU+BAUD*8)/(BAUD*16)-1) Warum also der Umweg. Danke euch schon mal für eure Antworten. Grüße Alex
Der Kommentar muss mit berücksichtigt werden.
1 | // clever runden
|
Der Rest ist Grundschulmathematik. Alles klar?
Ne leider ist nicht alles klar sonst würde ich nicht Fragen :). Stimmt schon das da ähnlich Ergebnisse rauskommen beim nachrechnen. Die Frage ist halt warum das ganze? Kann man damit später besser shiften,etc? Aber danke für eure Antworten. Grüße Alex
Älex schrieb: > Die Frage > ist halt warum das ganze? Kann man damit später besser shiften,etc? Es ist eine Integer-Rundung. Wenn z.B. eigentlich 3,7 rauskommen würde, kommt mit der Originalformel 3 heraus, und mit der modifizierten 4.
>Stimmt schon das da ähnlich Ergebnisse rauskommen beim nachrechnen.
Nun. Nimm mal an, das der in dem Wort "ähnlich" enthaltende Unterschied
der Ergebnisse hier relevant ist. Wieso ignorierst Du den? Deswegen auch
der Hinweis auf den Kommentar.
Älex schrieb: > Entschuldigt ich habe glaube ich die Frage falsch gestellt :). Ich meine > warum die diese Formel für UBRR_VAL verwenden. Im Datenblatt steht ja > UBRRn = (fCLKio / 16BAUD) - 1 > > > das entspricht ja nicht ((F_CPU+BAUD*8)/(BAUD*16)-1) Na ja, aber fast der einzige Unterschied besteht darin, dass zum Zähler noch mal die Hälfte des Nenners des Bruches dazugezählt wird. Exkurs. Was ergibt in C 5 / 5 da beides ganze Zahlen sind, ist das eine Integerdivision und das Ergebnis ist 1 Was ergibt 6 / 5? Die Antwort ist 1 7 / 5 1 8 / 5 1 9 / 5 1 10 / 5 2 findest du es nicht auch ein wenig unbefriedigend, wenn 9 / 5 den Wert von 1 ergibt? Immerhin, als Kommazahl gerechnet, wäre 9.0 / 5.0 ja 1.8 and das liegt als Zahlenwert ja doch schon wesentich näher an 2 als es an 1 liegt. Das man mit dieser Division 9 / 5 einen Fehler macht ist klar und unvermeidlich, denn 9 lässt sich nun mal nicht ganzzahlig durch 5 teilen. Aber der Fehler zum 'mathematisch korrekten' Ergebnis ist kleiner, wenn man als Ergebnis 2 rausbekommen würde, als wie wenn man 1 raus kriegt. Und genau diesen Zweck erfüllt dieser zusätzliche Term. Er verursacht, dass in solchen Fällen dasjenige Ergebnis erhalten wird, welches den 'kleineren Fehler' repräsentiert - den zur nächsten ganzen Zahl gerundeten Wert und nicht einfach nur den Wert, den man erhält wenn man Kommastellen ignoriert. Einfach mal mit Zahlen durchprobieren (Ich nehm jetzt eine gerade Zahl als Divisor, damit die Hälfte klar definiert ist) Original wäre es 6 / 6 1 7 / 6 1 8 / 6 1 9 / 6 1 10 / 6 1 11 / 6 2 mit der Modifikation 6: ( 6 + 3 ) / 6 = 9 / 6 1 7: ( 7 + 3 ) / 6 = 10 / 6 1 8: ( 8 + 3 ) / 6 = 11 / 6 1 9: ( 9 + 3 ) / 6 = 12 / 6 2 10: ( 10 + 3 ) / 6 = 13 / 6 2 11: ( 11 + 3 ) / 6 = 14 / 6 2 12: ( 12 + 3 ) / 6 = 15 / 6 2 und hier sehen die Ergebnisse dann schon weit besser aus. Ab der 9 aufwärts, wird das Divisionergebnis auf 2 aufgerundet, während es darunter zu 1 abgerundet wird.
1 | ( a + b/2 ) / b ist also die gerundete Version von a / b |
und das auf die im Datenblatt angegebene Formel angewendet .... ergibt genau das, was du im Code siehst.
Wenn Du einfach Clk/(16*Baud) rechnest, dann bekommst Du (weil Integer) die Ganzzahl, die am nächsten bei der theoretisch korrekten Zahl, aber kleiner ist. Du willst aber runden, also 674.7 soll 675 geben, nicht 674. Also musst Du eigentlich hinten noch ein +1/2 dranhängen. Das gibt's aber in Integer nicht. Der macht dann wieder 0 draus. Also machst Du zuerst *8, und dann wieder /16. So errechnet der Compiler zuerst mal'ne ganz grosse Ganzzahl und teil die dann wieder durch 'ne ganz grosse Ganzzahl. (clk + baud*8)/(baud*16) = clk/(baud*16) + 0.5. Mathematisch korrekt, aber das 0.5 kehrt der Compiler (oder preprozessor) unter den Teppich. Aber: Wenn er aber zuerst mal clk zu 8*baud addieren muss, darf er nichts unter den Teppich kehren. Und das dann halt entsprechend durch was grösseres dividieren, dann passt's wieder recht genau mit dem 0.5 Gruäss Simon ok, da waren andere schneller... :-)
Erklärung sind alle ganz nett aber ein wichtiges Detail wurde noch vergessen: Die 1%-Grenze. Deshalb macht man ja den ganzen Rundungskram, mal schaun ob ich es auf die Kette bekomme es halbwegs zu erklären: Du möchtest mit einer bestimmten Baudrate Daten übertragen. Damit die Gegenstelle (z.B. PC) auch weiß, was da ankommt, sagt man ihr mit welcher Baudrate der µC senden (bzw. empfängt, das spar ich mir im folgenden aber). Nun gebietet es die Technik, dass die Baudrate, um hier die einzelnen Bits noch korrekt unterscheiden zu können, um maximal 1% schwanken darf. Und daher kommt die obige Formel. Je nach gewünschter Baudrate und verwendeter Frequenz passt mal die Gleichung im Datenblatt und mal die obige Gleichung. Ihr Sinn ist hier lediglich die Abweichung der "echten" Baudrate zur Ganzzahl-Baudrate auf unter 1% zu halten. Ich hoffe dies ist verständlich, für Näheres google mal ein wenig mit den Worten "Baudrate, Abweichung, Fehler" zum Beispiel.
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.