dynamische Baudrate

Gast #2960510
Lesenswert?

Hallo,

Zur Einstellung des UBRR-Registers des ATmega-USART gibts ja folgenden 
beliebten Codeschnippsel hier im Forum:
1
// Berechnungen
2
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
3
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
4
#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
Gast #2960527
Lesenswert?

> 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.
Gast #2960539
Lesenswert?

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.
Gast #2960542
Lesenswert?

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.
Gast #2960549
Lesenswert?

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.
Gast #2960559
Lesenswert?

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.
Gast #2960564
Lesenswert?

> 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.
Gast #2960570
Lesenswert?

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
Gast #2960582
Lesenswert?

>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.
Gast #2960584
Lesenswert?

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.
Gast #2960597
Lesenswert?

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?
Gast #2960610
Lesenswert?

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:-)
Angehängte Dateien:
Gast #2960776
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren