Page 1 of 1

Setting Baud rates in Serial

Posted: Tue Apr 16, 2019 7:58 am
by bscholte
To communicate to several peripheral devices, I needed different baud rates. After building a brief spreadsheet based on the LPC manual, I optimized a list of settings for my target (LPC1769 with MCU.PCLK=30MHZ).
  • BaudRate DLM DLL DIVADDVAL MULVAL
  • 1200 6 27 0 1
  • 2400 3 13 0 1
  • 4800 1 135 0 1
  • 9600 0 195 0 1
  • 19200 0 98 0 1
  • 38400 0 49 0 1
  • 56700 0 33 0 1
  • 115200 0 15 1 12
  • 230400 0 7 1 6
  • 460800 0 4 0 1
  • 921600 0 2 0 1
  • 187500 0 1 0 1
I am sure one can make a nice iteration to calculate these values, but for now I put these manually optimized values in a simple procedure in the Serial module:

Code: Select all

PROCEDURE SetBaud*(Port:BYTE; VAR BaudRate:INTEGER);
VAR DLM, DLL, DIVVAL, MULVAL:BYTE;
    OKBaud:BOOLEAN;
    TimeOut:INTEGER;
BEGIN
  (*Numbers are valid when MCU.PCLK = 30000000*)
  TimeOut:=10000;
  REPEAT DEC(TimeOut) UNTIL SYSTEM.BIT(UART[DBPort]^.Base+ULSR, 5) OR (TimeOut<1); (*Wait for last transmit buffer to be empty*)
  IF SYSTEM.BIT(UART[DBPort]^.Base+ULSR, 5)
   THEN
      IF    BaudRate=  1200 THEN OKBaud:=TRUE; DLM:=6; DLL:= 27; DIVVAL:= 0; MULVAL:= 1;
      ELSIF BaudRate=  2400 THEN OKBaud:=TRUE; DLM:=3; DLL:= 13; DIVVAL:= 0; MULVAL:= 1;
      ELSIF BaudRate=  4800 THEN OKBaud:=TRUE; DLM:=1; DLL:=135; DIVVAL:= 0; MULVAL:= 1;
      ELSIF BaudRate=  9600 THEN OKBaud:=TRUE; DLM:=0; DLL:=195; DIVVAL:= 0; MULVAL:= 1;
      ELSIF BaudRate= 19200 THEN OKBaud:=TRUE; DLM:=0; DLL:= 98; DIVVAL:= 0; MULVAL:= 1;
      ELSIF BaudRate= 38400 THEN OKBaud:=TRUE; DLM:=0; DLL:= 49; DIVVAL:= 0; MULVAL:= 1;
      ELSIF BaudRate= 56700 THEN OKBaud:=TRUE; DLM:=0; DLL:= 33; DIVVAL:= 0; MULVAL:= 1; 
      ELSIF BaudRate=115200 THEN OKBaud:=TRUE; DLM:=0; DLL:= 15; DIVVAL:= 1; MULVAL:=12;
      ELSIF BaudRate=230400 THEN OKBaud:=TRUE; DLM:=0; DLL:=  7; DIVVAL:= 1; MULVAL:= 6;
      ELSIF BaudRate=460800 THEN OKBaud:=TRUE; DLM:=0; DLL:=  4; DIVVAL:= 0; MULVAL:= 1;
      ELSIF BaudRate=921600 THEN OKBaud:=TRUE; DLM:=0; DLL:=  2; DIVVAL:= 0; MULVAL:= 1;
      ELSE OKBaud:=FALSE
      END;
      IF OKBaud THEN SetFDR(Port, DLM, DLL, MULVAL, DIVVAL);
                     Out.Writeln("Serial Baudrate set")
                ELSE BaudRate:=0
                END;
   ELSE Out.Writeln("Baudrate set TimeOut");
        BaudRate:=0;             
   END;
END SetBaud;
I tested (almost) all settings and they seem to work well. Important is to wait for the buffer to be empty while otherwise the baud rate will change in the middle of a message. I also found that devices like an Espressif ESP8266 Wifi module will confirm a a baud rate change command with the OLD baud rate before switching to the new one. The LPC can theoretically run up to a baud rate of 1875000 but I haven't tried this. The proc sets the Baud rate to 0 in case the rate is unknown or the buffer remains loaded. In such cases, the baud rate is not changed.

Please note that UART[Port]^.Base simply refers to the MCU.UxBase, where x is the port number (0, 1, 2 or 3)

If you would like to get the calculation sheet, just drop a line in this forum for a link.

Re: Setting Baud rates in Serial

Posted: Tue Apr 16, 2019 11:24 am
by cfbsoftware
Thank you for your example.
bscholte wrote: I am sure one can make a nice iteration to calculate these values,
Yes indeed you can. Look for the Astrobe example called CalcBaudRate in your Astrobe Examples\General folder for an Oberon algorithm to calculate these values.