Forum: Mikrocontroller und Digitale Elektronik EFM8BB1 UART und Timer1


von Max M. (maxmicr)


Lesenswert?

Guten Tag,

aktuell versuche ich UART auf einem EFM8BB1 zum laufen zu bekommen, nun 
funktioniert es auch allerdings nicht mit der von mir erwarteten 
BAUD-Rate, mein aktueller Code sieht so aus:
1
void setLowSysFreq(){
2
  CLKSEL = 0x02; //Set internal low frequency (80KHz) oscillator
3
}
4
5
void initUART(){
6
  XBR0 |= (1<<0); //UART TX&RX routed to P0.4 & P0.5
7
  CKCON0 |= (1<<3); //Timer 1 uses system clock
8
  TMOD = 0x20; //Timer1 8-bit with Auto-Reload
9
  TH1 = 252;  //Reload value for Timer 1
10
  TL1 = 252;  //Set reload value
11
  TCON |= (1<<6); //Timer1 enable
12
}
13
14
void sendByte(uint8_t byte){
15
   SBUF0 = byte;
16
}

Timer1 hat also einen Reload-Wert von 252. Nach der Formel auf S. 195 
des Reference Manuals 
(http://www.silabs.com/documents/public/reference-manuals/EFM8BB1-RM.pdf) 
ergibt sich damit ein F_timer1 von:
1
80.000 / (256 - 252) = 20.000
 Auf S. 214 des selbigen Manuals steht, dass die BAUD-Rate die 
Overflow-Rate / 2 ist, demnach würde sich eine BAUD-Rate von 10.000 
ergeben. Ich sende permanent 0x5A über die Leitung, die 
"Auto-Baud"-Funktion von Saleae Logic hat eine BAUD-Rate von 1258 
erkannt, das konnte ich auch mit einem Terminal-Programm verifizieren, 
hier wird durchgehend 0x5A angezeigt (passt also). Ich frag mich nun, 
wie man auf diese Baud-Rate kommt?

Grüße

: Bearbeitet durch User
von Florian (Gast)


Lesenswert?

Beim enable der CLK Quelle auf lfo hast du
Den sysclk divider in clksel auf 1 gesetzt, okay.
Die divider Bits würden durch die direkte Zuweisung an
Clksel auf null gesetzt -> divider 1.

Wie hast du den lfo aktiviert (lfo0cn) dieser
hat per power Up Default lfoprediv zwar 1 aber
dazu sind hier die Bits gesetzt, bei einer direkten
Register Zuweisung nur mit dem enable Bit, Rest null, würdest
du den lfo prescaler auf 8 setzen,... Kannst das ja mal prüfen.

By the way bei mir ist der lb1 Typ im Moment in Gebrauch
Der bb3 ist sehr ähnlich und hoffe der bb1 ist es hier auch

von Max M. (maxmicr)


Lesenswert?

Danke für deine Antwort,

Florian schrieb:
> bei einer direkten
> Register Zuweisung nur mit dem enable Bit, Rest null, würdest
> du den lfo prescaler auf 8 setzen,... Kannst das ja mal prüfen.

Ah, da hab ich wohl ein Register übersehen, ich hab die Funktion wie 
folgt geändert:
1
void setLowSysFreq(){
2
  LFO0CN = 0xC3; //Enable low frequency oscillator and set divider to '1'
3
  CLKSEL = 0x02; //Set internal low frequency (80KHz) oscillator
4
}

Jetzt ist der Divider auf '1'. Nun erhalte ich eine Auto-Baud rate von 
"12903". Ist schon deutlich näher an den errechneten 10.000 aber immer 
noch nicht ganz.

von Florian (Gast)


Lesenswert?

Servus,


Lfo0cn |= 0x80
// divider bleibt erhalten, oder 0x8x x nur für die gewünschten
//divider Bits 0 und 1 dazu aber vorher die Bits sicher zurück setzen zb
//entsprechende Bits mit null verunden.

While (  !(lfo0cn & 0x40) ) // wait OSC stabilized
{
Ggf. Timeout;
}

Dann setze deine clksrc und sysclk divider Bits.

Bei deiner direkten Zuweisung veränderst du das lfosc Tuning Word...
Sprich du änderst die Frequenz des osc.. und das sehr grob...
Die Bits 5 bis 2 bilden das Tuning/ Frequenz control  word

von Florian (Gast)


Lesenswert?

Irgendwie werden meine linefeeds hier geschluckt oder es liegt am Tab

von Max M. (maxmicr)


Lesenswert?

Florian schrieb:
> Bei deiner direkten Zuweisung veränderst du das lfosc Tuning Word...
> Sprich du änderst die Frequenz des osc.. und das sehr grob...
> Die Bits 5 bis 2 bilden das Tuning/ Frequenz control  word

Danke für deine Hilfe, so funktioniert das nun:
1
void setLowSysFreq(){
2
  CLKSEL = 0x02; //Set internal low frequency (80KHz) oscillator
3
  LFO0CN |= 0x80; //Enable low frequency oscillator
4
  while((!LFO0CN & 0x40)) //Wait to stabilize
5
    ;
6
  LFO0CN |= 0x03; //Set divider to '1'
7
}

Wenn ich 251 als Reload-Wert benutze (BAUD = 8000) klappt das 
wunderbar mit meinem Terminal Programm, bei 252 (BAUD = 10.000) dauert 
es ca ~ 3s bis die richtigen Werte erkannt werden. Ist das ein Zeichen, 
dass noch irgendwo ein Fehler ist?

: Bearbeitet durch User
von Florian (Gast)


Lesenswert?

Mich wundert es das überhaupt was läuft gut ich kenne deinen Code nicht.
Normal nach Reset ist der lfo aus... Du schaltest jetzt erst den lfo als
Systemtakt Quelle bevor er eingeschaltet wird. Normal führt das zu
einem hangup.
Außer der Missing CLK Detektor ist an dann würde aber ein restet folgen.
Wird das lfo Register zuvor schon irgendwo im Code zugewiesen?
Clksel wird erst auf lfo als Quelle modifiziert wenn der lfo 
eingeschaltet
wurde und stabil läuft.

Was sagt denn dein logic analyzer zur baudrate.
Und bedenke der lfo hat eine recht große Toleranz, ist im Datenblatt
von 75khz bis 85khz angegeben, das kann als Taktgeber für den UART
u.u. zu weit abweichen muss aber natürlich nicht.. auch deine
Gegenstelle muss deine eigentlich non Standard baudraten ausreichend
gut einstellen können.

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.