#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
5
6
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
7
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
8
#endif
Nun würd ich aber gerne die Baudrate zur Laufzeit ändern können.
Also brauch ich eine Funktion welche mir aus einer Baudrate den
UBRR-Wert errechnet.
Einfach nur obigen Präprozessorschnippsel auf "richtige" Anweisungen
umändern wäre zwar einfach, würde aber unter anderem die Lib für 32-Bit
Division nach sich ziehn.
Eine LookUp-Tabelle würde sich ja sogar im Datenblatt der ATmegas
finden. Aber die zu übernehmen macht bei deren Größe wohl auch keinen
Sinn.
Wie würdet ihr das lösen?
Viele Grüße,
Masl
> Wie würdet ihr das lösen?
Für festes F_CPU und veränderliche Baudrate: vom Präprozessor generieren
lassen. Für feste Baudrate und veränderliches F_CPU: vom Präprozessor
generieren lassen. Wenn beides veränderlich dann vermutlich der
Einfachheit halber zur Laufzeit berechnen, sonst auch vom Präprozessor
generieren lassen.
Vielleicht kannst Du die Tabellen stutzen. Ich kann mir kaum vorstellen,
dass Du alle, möglichen Kombinationen brauchst.
- Dein Quarz ist, normalerweise, nicht austauschbar. Und wenn Du
doch verschiedene Wackler einbauen musst, so kannst Du eine
Fall-Zu-Fall-Tabelle abhängig von F_CPU implementieren. Deine
Software muss ja sowieso wissen wie schnell sie ist.
- Ich glaube nicht, dass wirklich alle Geschwindigkeiten ausgewählt
werden, schau mal in das Auswahlmenü deines Windoofs.
- Die Hälfte der Einträge ist sowieso für den Halbteiler.
warum nicht einfach rechnen? Die Formel steht im Datenblatt dafür muss
man zwar auf 32bit gehen aber ich denke das ganze wird nicht mehrmals in
der Sekunde gemacht. Damit sollte die Zeit egal sein. Wenn es doch
Zeitkritisch ist, kann man beim Programmstart sich seinen baudraten
ausrechnen und dann nur noch eintragen.
Masl schrieb:> Eine LookUp-Tabelle würde sich ja sogar im Datenblatt der ATmegas> finden. Aber die zu übernehmen macht bei deren Größe wohl auch keinen> Sinn.
Wieso? Wieviele unterschiedliche Baudraten meinst Du denn unterstützen
zu müssen? Müssen das mehr sein als 20?
Ich vergaß: Mul 8 und Div 8 dürften wohl durch einfache Schiebebefehle
zu implementieren sein ... aber bei den Hauptdivision kommst Du wohl
nicht um "echte" Division herum.
Wenn Du die 32-Bit Division nur für diesen Fall brauchst, schnapp' Dir
die Sourcen der Bibliothek und extrahiere Dir das Teil. Mehr als 30
Bytes werden das wohl nicht sein.
Rufus Τ. Firefly schrieb:> Wieso? Wieviele unterschiedliche Baudraten meinst Du denn unterstützen> zu müssen? Müssen das mehr sein als 20?
Das nicht. Aber ich wär eben gerne flexibel, dazu fällt auch eine
variable F_CPU.
Und 10 Baudraten bei 20 verschiedenen Quarzen ist auch schon ne menge
Holz.
Das Umschalten ist auch nicht zeitkritisch, d.h. eine 32-Bit Berechnung
wäre akzeptabel. Ich habe da eher Bedenken wegen der resultierenden
Codegröße.
> Das Umschalten ist auch nicht zeitkritisch
..sach das doch gleich.. zur Laufzeit berechnen!
> Ich habe da eher Bedenken wegen der resultierenden Codegröße.
Optimierungen nicht ausschalten, dann sind keine Probleme zu erwarten.
Hi
>Das nicht. Aber ich wär eben gerne flexibel, dazu fällt auch eine>variable F_CPU.
Und wie teilst du dem Controller mit, welche Baudrate und welcher
Controllertakt gerade angesagt ist? Ich sehe keinen reellen Nährwert in
deinem Vorhaben.
MfG Spess
>Und 10 Baudraten bei 20 verschiedenen Quarzen ...
Mit einem Makro gesteuert durch F_CPU (oder wie das Teil bei deinem
Compiler auch heißt) brauchst Du gerade mal 20 Bytes bzw. 10 Worte.
Ist das denn wirklich ein Problem?
Wohl gemerkt: Deine Software muss ja auf jeden Fall wissen welchen Takt
Du ihr spendierst.
Daraus folgt: Ein Einfaches umlöten des Quarzes ist nicht möglich.
Spielst Du aber die "passende" Software wieder ein, stimmt deine "neue"
Tabelle auch wieder.
Mit variablen Baudrates zu arbeiten habe ich über eine
einfache automatische Baudratenerkennung gelöst.
Wird bei mir beim Programmstart aufgerufen.
Funktioniert ganz einfach:
Die Gegenseite sendet ein definiertes Zeichen, z.B. 0x30 oder 0x20.
Aus der Länge der zwei Bits (bei 0x30) oder dem einen einen Bit (bei
0x20)
kann man die Baudrate ermitteln. Grundidee stammte ursprünglich
aus einer Intel-Anwendung für die 8051-Family. Funktioniert aber
auch bei anderen µC.
Diese Methode hat den Vorteil daß mit dem originalen Takt,
es wird die Anzahl der Takte pro Bit ermittelt, gerechnet wird.
Da stand ich wohl auf dem Schlauch.
F_CPU ist natürlich zur Compile-Zeit bekannt und unveränderlich. D.h.
ich lasse den Präprozessor meine LookUp Tabelle berechnen, diese wäre
dann insgesamt nur z.B. 10*2 Byte (UBRR hat 16 Bits) groß.
Das Ganze würde wohl in einem Array resultieren, das vom Präprozessor
initialisiert wird?
Masl schrieb:> Das Ganze würde wohl in einem Array resultieren, das vom Präprozessor> initialisiert wird?
Genau, und zwar sinnvollerweise in den Flash per PROGMEM.
Ich habe vor ein paar Jahren, wegen Platzproblemen selber mal die
Division extrahiert. Hatte sie noch.
Mit minimalen Anpassungen brauchst Du sie nur in eine .S-Datei packen
und kannst glücklich werden. Die Aufrufkonventionen entsprechen denen
des GNU-Compilers.
Damit dürftest Du auch die Baudrate eines 6,66MHz Quarzes berechnen
können:-)
Masl schrieb:> Das Umschalten ist auch nicht zeitkritisch, d.h. eine 32-Bit Berechnung> wäre akzeptabel. Ich habe da eher Bedenken wegen der resultierenden> Codegröße.
Wenn du die ~30 Bytes nicht mehr hast, dann hast du sowieso gröbere
Probleme.
Masl schrieb:> Wie würdet ihr das lösen?
Woher kommt denn die Vorgabe für die Baudrate?
Die gängigen Fälle sind doch mit 10 Parametersätzen abgedeckt. Die
Alternative wäre eine automatische Baudratenbestimmung per Timer, die
dann auch beliebig krumme Werte frißt. Das kommt dann auf Prozessor,
Taktfrequenz/Baudratengenerator, Baudratenbereich, verfügbare
Prozessorzeit und nicht zuletzt auf das Datenübertragungsszenario drauf
an.