Forum: Mikrocontroller und Digitale Elektronik UART BSEL berechnen[ATxmega]


von jojo (Gast)


Lesenswert?

Guten Tag,

seit einigen Tagen beschäftige ich mich mit den ATxmegas. Habe ein 
bisschen mit dem UART herumgspielt und jetzt versucht ein Header File zu 
schreiben, dass ich immer als Debug-Ausgabe einsetzen kann.

Allerdings habe ich noch ein Problem bei der Initialisierung des BSEL 
Wertes. Ich benutze die interne Baudratenerzeugung, wobei der Bscale 
Wert auf 0 steht:
1
void InitDebug(uint32_t FPER)
2
{
3
PORTE.DIRSET = PIN3_bm;
4
PORTE.DIRCLR = PIN2_bm;
5
6
USARTE0.CTRLC = (USART_CHSIZE_8BIT_gc | USART_PMODE_DISABLED_gc);
7
8
uint16_t BSELT;
9
BSELT = round(((FPER/(16*9600))-1));
10
11
USARTE0.BAUDCTRLA = BSELT;                                           
12
USARTE0.BAUDCTRLB =(0 << USART_BSCALE0_bp)|(BSELT >> 8);
13
14
USARTE0.CTRLB |= USART_RXEN_bm;
15
USARTE0.CTRLB |= USART_TXEN_bm;
16
}

Das Problem tritt bei der Berechnung des Wertes auf. FPER übergebe ich 
als 2.000.000, als Ergebnis müsste 12 herauskommen. Leider ist es so, 
dass wenn die Berechnung ablaufen müsste, im Debugger immer die 2 
nachfolgenden Anweisungen übersprungen werden. Wenn ich BSELT gleich 12 
setze, erhalte ich das korrekte Ergebnis (es funktioniert dann auch mit 
der Hardware).

Viele Grüße und vielen Dank im Vorraus,

jojo

PS: Ich weiß, dass es nicht sonderlich sinnvoll ist, das ganze ohne 
Fehlerbetrachtung zu machen, jedoch hält sich der prozentuale Fehler bei 
9600Baud im Allgemeinen (ganz krumme Werte habe ich jetzt noch nicht 
getestet) im Rahmen.

von Hans-jürgen H. (hjherbert) Benutzerseite


Lesenswert?

Hier stört die funktion "round()", die es in der Library gibt, aber im 
Compiler möglicherweise nicht eingebaut ist. Diese Funktion will double 
und gibt double zurück.

Siehe: http://www.nongnu.org/avr-libc/user-manual/group__avr__math.html

Oder Google:"round libc"


Sieh zu, dass du eine Formel "erfindest", die nur Integer braucht. Für 
meinen ATMega8 / ATMega32 habe ich

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

Also
anstatt : round(((FPER/(16*9600))-1))
besser : (FPER+(16*9600)/2)/(16*9600))-1

Dabei wird dadurch gerundet, dass zum Zähler der halbe Nenner 
hinzuaddiert wird.

von jojo (Gast)


Lesenswert?

Hallo,

vielen Dank für die Antwort. Das mit dem round() war ein guter 
Hinweis...da wäre ich so schnell nicht draufgekommen.
Im Endeffekt funktioniert die Berechnung auch nur über ein Define, was 
mich letztendlich aber nicht stört, ist so viel ordentlicher^^

Viele Grüße

jojo

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.