UART BSEL berechnen[ATxmega]

Gast #1604688
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.
Persönliche Seite #1605390
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.
Gast #1606884
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

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