LPC1768 UART Programming Tutorial
LPC1768 UART Programming Tutorial
Here is an example of single Packet/Frame using 8 data bits, even parity and 1 stop bit:
All UART blocks internally have a 16-byte FIFO (First In First Out) structure to hold data. Each byte in this FIFO
represents a
character which was sent or received in order. All blocks also contain 2 registers each, for data
access and assembly as given below:
1. Bit [3 to 0] – DIVADDVAL: This is the prescale divisor value. If this value if 0 then fractional baud rate generator wont
have any effect on Uart Baud rate.
2. Bit [7 to 4] – MULVAL: This is prescale multiplier value. Even if fractional baud rate generator is not used the value in
this register must be more than or equal to 1 else UART0 will not operate properly.
3. Other Bits reserved.
Remark from User-manual:” If the fractional divider is active (DIVADDVAL > 0) and DLM = 0, the value of the DLL register
must be 2 or greater!”
1. Bit [1 to 0] – Word Length Select: Used to select the length of an individual data chunk. [00] for 5 bit character length.
Similarly [01] , [10] , [11] for 6 , 7 , 8 bit character lengths respectively.
2. Bit 2 – Stop bit select: 0 for using 1 stop bit and 1 for using 2 stop bits.
3. Bit 3 – Parity Enable: 0 to disabled Partiy generation & checking and 1 to enable it.
4. Bit [5 to 4] – Parity Select: [00] to Odd-parity , [01] for Even-parity , [10] for forced “1”(Mark) parity and [11] for forced
“0”(Space) parity.
5. Bit 6 – Break Control: 0 to disable break transmission and 1 to enable it. TxD pin will be forced to logic 0 when this bit is
1!
6. Bit 7 – Divisior Latch Access bit: 0 to disable access to divisor latches and 1 to enable access.
3) UxLSR – Line Status Register: used to read the status of Rx and Tx blocks. Bits 1 to 4 get cleared after reading UxLSR.
1. Bit 0 – Receiver Data Ready(RDR): 0 means UxRBR is empty(i.e Rx FIFO is empty) and 1 means UxRBR contains valid
data.
2. Bit 1 – Overrun Error(OE): 1 means Overrun has occured, 0 otherwise. Overrun is the condition when RSR(Receive
Shift Register) has new character assembled but the RBR FIFO is full and the new assembled character was eventually
lost since no data is written into FIFO when its full.
3. Bit 2 – Parity Error(PE): 1 means a parity error has occured else not. When the value of the parity bit in the recieved
character is in wrong state then a parity error occurs.
4. Bit 3 – Framing Error(FE): 1 means that a framing error has taken place else not. Framing error occurs when the stop bit
of a received character is zero.
5. Bit 4 – Break Interrupt: 1 means that it has occured else not. A Break Interrupt occurs when the RxD line is pulled low
(i.e all 0s) i.e held in spacing state for 1 full character after which Rx Block goes into Idle state. Rx Block gets back to
active state when RxD pin is pulled high (i.e all 1s) i.e held in marking state for 1 full character.
6. Bit 5 – Transmit Holding Register Empty(THRE): 0 means UxTHR has valid data and 1 means its empty.
7. Bit 6 – Transmitter Empty(TEMT): 0 means UxTHR and/or UxRSR has valid data and 1 means that both UxTHR and
UxRSR are empty.
8. Bit 7 – Error in RX FIFO(RXFE): 0 means that UxRBR has no Rx Errors or Rx FIFO is disabled(i.e 0th bit in U0FCR is 0)
and 1 means that UxRBR has at-least one error. Note: This bit is cleared only if UxLSR is read and there are no other
subsequent errors in Rx FIFO, else this bit will stay 1
4) UxTER – Transmit Enable Register: This register is used to enable UART transmission. When bit-7 (i.e TXEN) is set to 1 Tx
block will be enabled and will keep on transmitting data as soon as its ready. If bit-7 is set to 0 then Tx will stop transmission. Other
bits are reserved.
1. Bit 0 – Interrupt Pending : 0 means at-least one interrupt is pending, 1 means no interrupts are pending. Note: This bit is
ACTIVE LOW!
2. Bits [3 to 1] – Interrupt Identification : [011] implies Receive Line Status(RLS) , [010] implies Receive Data
Available(RDA) , 110 implies Character Time-out Indicator(CTI) , [001] implies THRE Interrupt.
3. Bits [7 to 6] – FIFO Enable.
4. Bit 8 – ABEOInt : 1 means Auto Baud Interrupt has successfully ended and 0 otherwise.
5. Bit 9 – ABTOInt : 1 means Auto Baud Interrupt has Timed-out.
6. All others bits are reserved.
Where DIVADDVAL & MULVAL are part of “Fractional Rate Divider” or “Baud-Prescaler” which is used in Baud-Rate generation.
This “Fractional Divider” is only active when DIVADDVAL > 0. This formula is pretty common for LPC ARM micro-controllers.
which can be further simplified to :
Baud =
This Fraction Part i.e. the Fractional Divider or the “Baud Rate Prescaler” can be used to scale down or keep the base value as it is
(when disabled). Hence, its very useful for fine-tuning and getting the baudrate as accurate as possible.
Note: In real world there are very less chances that you will get the actual baudrate same as the desired baudrate. In most cases
the actual baudrate will drift a little above or below the desired baud and also, as the desired baudrate increases this drift or error
will also increase – this is because of the equation itself and the limitations on MULVAL , DIVADDVAL! For e.g. if the desired baud
rate is 115200 and depends on the variables you may get a bauds like 114300, 115470, 116050 .. and so on. But in almost all cases
it will work as required if the error is not significant. A small amount of error in actual baudrate is generally tolerable in most systems
which must be <1.1% (relative error).
In my opinion, if possible, you must stay away from above method as it works only for particular bauds & specific PCLK value and
moreover computed UxDLL might get out of range i.e. > 255 in which case you have to start increasing DLM and recompute a new
value for DLL.
Now, lets write a function “InitUART0()” which we can use initialize and configure UART0:
#define MULVAL 14
#define DIVADDVAL 2
#define Ux_FIFO_EN (1<<0)
#define Rx_FIFO_RST (1<<1)
#define Tx_FIFO_RST (1<<2)
#define DLAB_BIT (1<<7)
void InitUART0(void)
{
LPC_PINCON->PINSEL0 |= (1<<4) | (1<<6); //Select TXD0 and RXD0 function for P0.2 & P0.3!
//LPC_SC->PCONP |= 1<<3; //Power up UART0 block. By Default it is enabled after RESET.
1. Your PC/Laptop(older ones) already has a serial port. In this case you will need a RS232 to TTL converter.
2. Your PC/Laptop doesn’t have a serial port and you are using USB to Serial converter(FTDI ones, etc..).
If you are using a separate converter then in both cases the TTL side of the converter have to use a minimum of 3 pins for basic
UART communication which are: TxD, RxD and GND. Connect your MCU RxD to TxD of converter and MCU TxD to RxD of
converter. Finally connect GND on both sides. Make sure you module supports 3.3v voltage-levels.
Please refer to the connection diagrams & terminal software configuration(and COM ports) as given in Basic Uart Tutorial.
Here is a configuration screenshot for terminal software PuTTYtel which we will be using for examples :
Note: You can get PuTTYtel from Here. Direct download link: Here. You can also use other similar terminal software as well.
#include <lpc17xx.h>
void initUART0(void);
void U0Write(char data);
int main(void)
{
//SystemInit(); //This already gets called by CMSIS Startup Code.
char msg[] = { 'H','e','l','l','o',' ','f','r','o','m',' ','L','P','C','1','7','6','8','\0' };
int count=0;
initUART0();
while(1)
{
while( msg[count]!='\0' )
{
U0Write(msg[count]);
count++;
}
//Send NEW Line Character(s) i.e. "\n"
U0Write(CARRIAGE_RETURN); //Comment this for Linux or MacOS
U0Write(LINE_FEED); //Windows uses CR+LF for newline.
count=0; // reset counter
}
//return 0; //This won't execute normally
}
void initUART0(void)
{
/*Assuming CCLK = 100Mhz and PCLK = 25Mhz!*/
LPC_PINCON->PINSEL0 |= (1<<4) | (1<<6); //Select TXD0 and RXD0 function for P0.2 & P0.3!
//LPC_SC->PCONP |= 1<<3; //Power up UART0 block. By Default it is enabled after RESET.
#include <lpc17xx.h>
void initUART0(void);
char U0Read(void);
void U0Write(char data);
int main(void)
{
initUART0();
char data = 0;
while(1)
{
data = U0Read(); //Read Data from Rx
if(data == ENTER) //Check if user pressed Enter key
{
//Send NEW Line Character(s) i.e. "\n"
U0Write(CARRIAGE_RETURN); //Comment this for Linux or MacOS
U0Write(LINE_FEED); //Windows uses CR+LF for newline.
}
else
{
U0Write(data); //Tx Read Data back
}
}
//return 0; //Normally this won't execute
}
char U0Read(void)
{
while(!(LPC_UART0->LSR & RDR)); //wait until data arrives in Rx FIFO
return LPC_UART0->RBR;
}
KEIL ARM uV5 Project for Example #2 on GitHub @ Example 1 [Successfully tested on Keil uV5.23], Download Project
Zip @ Example_2.Zip. You can find the HEX file inside objects folder.