I'm using a USART in asynchronous mode with an EFM32HG. The peripheral is clocked with the internal 24Mhz oscillator.
/* Prepare struct for initializing UART in asynchronous mode*/ uartInit.enable = usartDisable; /* Don't enable UART upon intialization */ uartInit.refFreq = 0; /* Provide information on reference frequency. When set to 0, the reference frequency is */ uartInit.oversampling = usartOVS4; /* Oversampling. Range is 4x, 6x, 8x or 16x */ uartInit.databits = usartDatabits8; /* Number of data bits. Range is 4 to 10 */ uartInit.parity = usartNoParity; /* Parity mode */ uartInit.stopbits = usartStopbits1; /* Number of stop bits. Range is 0 to 2 */ uartInit.mvdis = false; /* Disable majority voting */ uartInit.prsRxEnable = false; /* Enable USART Rx via Peripheral Reflex System */ uartInit.prsRxCh = usartPrsRxCh0; /* Select PRS channel if enabled */ uartInit.baudrate = 115200;
Measuring the real baudrate with an Oscilloscope I found a baud rate of ~117000. So I investigate the emlib function implementation and I see that in function USART_BaudrateAsyncSet() CLK_DIV register is not fully used. DIVEXT (bits 3-5) are not used.
Is a reason to do this? Or I could set the register directly through the reference manual formula:
So with 24MHz; oversample = 4; and desiredbr = 115200 => CLKDIV = 13077.33
Rounding and removing 3bits => CLKDIV = 13072
With this value using the reference manual formula I found a baudrate = 115177.
Sounds like a bug in emlib to me. The baudrate calculation masks the calculated baudrate using _USART_CLKDIV_DIV_MASK but on EFM32HG the CLKDIV register is divided into two register fields DIV and DIVEXT.
Sorry but I don't understand your statment. What do you mean when write "i guess below KB may helps, though the KB focus on sychrounous mode."?
According the reference manual, page 330 (section 18.104.22.168) the asynchronous mode use 15 bit value, with a 3 bit integral part and a 2-bit fractional part.
Which value the register was really set when you get 117000 baud rate? Do you have a chance to monitor the HFPERCLK, you could route it out to a pin and check if it was 24000000Hz. But basically 117000 (target 115200) is not reasonable. If you set the CLKDIV equals 51*256 (only integral part valid), I think you should get 115384 BR. If you set CLKDIV equals 51.25*256, the BR should be 24M/4/52.25 = 11483 BR.
BR = HFPERCLK/Oversample/(CLKDIV/256+1).
My views are my own and do not necessarily represent the views of Silicon Labs
I've checked all the things you mentioned and this is my configuration:
USART0_CLKDIV = 0x3300
OVR = 4
Measured HFPERCLK in an external pin = 24.150 MHz
Measured BaudRate = 116200
It's all ok.
Thank you for your support.
Thanks, that make sense to me:
BR = HFPERCLK/Oversample/(CLKDIV/256+1)
The error in em_usart.c has been located and the fix will be part of the Gecko SDK 5.2.0 release. Thanks for reporting this.
Both the USART_BaudrateAsyncSet() function and the USART_BaudrateCalc() function had to be updated in order to use the extra fractional bits on the EFM32HG.