How to manually set LPC11U24 USART baudrate?

17 Feb 2012

Hi,

I'm trying to set UART manually (without using mbed lib) for LPC11U24.

Pls read code below:

#include "mbed.h"

extern "C" {

extern void serial_baud(LPC_USART_Type *, unsigned int);

}

static void my_set_br(void)
{
   	LPC_SYSCON->UARTCLKDIV = 1;
	
	LPC_USART->LCR |= 0x80;
	// given that PCLK = 48M, baudrate = 9600
        // FR_est = 1.929, divadd = 13, mul = 14, dl_est = 162
	LPC_USART->DLM = 0x00000000;
        LPC_USART->DLL = 0x000000a2;
        LPC_USART->FDR = 0x000000ed;
	LPC_USART->LCR &= ~0x80;
	
}

static void
my_serial_init(void)
{
	LPC_SYSCON->SYSAHBCLKCTRL |= 0x1000;
	
	LPC_IOCON->PIO0_19 &= ~0x7; // clear mode bits
	LPC_IOCON->PIO0_18 &= ~0x7;
	
	LPC_USART->FCR = 1;
	LPC_USART->DLM = 0;
	
	serial_baud(LPC_USART, 9600); // this is OK
	//my_set_br(); // this is NOT OK
	
	LPC_USART->LCR = 0x3; // set 8 bits, non-parity and 1 stop
	LPC_IOCON->PIO0_19 |= 0x1; // set func to 1 and mode to 0
	LPC_IOCON->PIO0_18 |= 0x1;	
}

int main() {  
    const char *s = "Hello World!\n";
    int i;
    
    my_serial_init();
    
    for (i = 0; i < 14; i++)
        LPC_USART->THR = s[i];
        
    while (1) ;
}

If I use mbed-lib function serial_baud to set the baudrate, then the "Hello World!" is printed to terminal perfectly.

However, if I use my_set_br to set baudrate, the "Hello World!" is printed twice.

As I understood, the official function serial_baud does nothing but set DLL/DLM/FDR. According to algo in the LPC11U24 user manual, I can caculate manually all the values:

PCLK = 48M, baudrate = 9600, FR_est = 1.929, divadd = 13, mul = 14, dl_est = 162

But why the string is printed twice with my baudrate setting?

I also noted that, if I keep the call to serial_baud, and un-comment the next line, i.e., my_set_br, the "Hello World!" is also printed once and only once.

This is a hint that my DLL/DLM/FDR values are correct, isn't it?

thanks in advance

17 Feb 2012

Finally got it fixed. It seems that there has to be a long enough delay between setting UARTCLKDIV and DLL/DLM/FDR. But I'm not sure. I just calculated DLL/DLM/FDR before setting the values, and it is done. Is it a bug of mbed-interface or sth.?

18 Feb 2012

Confirmed that a delay is necessary between setting UARTCLKDIV and DLM/DLL/FDR. This behavior is not documented in user manual, thus maybe a mbed specific "feature"?

27 Feb 2012

With baudrate 9600, a delay of 100k NOPs is enough; While with baudrate 921600, 1000k NOPs are required, otherwise the scenario (double prints) happens again.

It's another hint that the delay has to conform with the speed of mbed-interface's algo for DLL/FDR calculation, coz the default algo takes more time with higher baudrate.

It could be fixed by using a much faster algo, e.g., look-up-table.

Besides, it is not only about speed, but also size of target, coz float point calculation spends a lot of ROM space. It's better to avoid float point when possible.

Hopefully mbed team could take a look at it.

13 Oct 2016

I did that for lpc1549, that worked perfect without any delay.