LPC2148 – Serial Communication Tutorial

This article is a continuation of the series of tutorials on the LPC2148 Microcontroller (ARM7). The aim of this series is to provide easy and practical examples that anyone can understand. In the previous tutorial, we have seen LPC2148 (ARM7) Timer and Counter. Now we are going to see the LPC2148 Serial Communication Tutorial. UART (Universal Asynchronous Receiver Transmitter) is one of the basic interfaces which provide a cost-effective simple and reliable communication between one controller to another controller or between a controller and PC.

Suggestion to read

If you are new to UART please go through our previous article about UART.

LPC2148 Serial Communication Tutorial

Coming to UART in LPC2148, the LPC214x series of MCUs have two UART blocks called UART0 and UART1. Each UART block is associated with two pins, one for transmission and the other for receiving.

In the UART0 block, the TXD0 (Transmit) and RXD0 (Receive) pins in the device are P0.0 and P0.1 respectively. In the case of UART1, the TXD1 and RXD1 pins are P0.8 and P0.9 respectively.

 UART 0UART 1
TX P0.0P0.8
RX P0.1P0.9

Both the UART modules are identical, except the UART1 block has an additional full modem interface. This includes all the pins for RS232 compatibility like flow control pins (CTS, RTS), etc. Both UART0 & UART1 blocks internally have a 16-byte FIFO (First In First Out) structure to hold the Rx and Tx data.  In this tutorial, we will see only UART0. But If you understand the UART0 obviously you can play with UART1.

Registers Used For UART

The below table shows the registers used for UART.

RegistersDescription
UxTHRContains the data to be transmitted
UxRBRContains the recently received Data
UxLCR Controls the UART frame formatting(Number of Data Bits, Stop bits)
UxFDRControls the clock pre-scaler for the baud rate generation
UxDLL Least Significant Byte of the UART baud rate generator value
UxDLM Most Significant Byte of the UART baud rate generator value
UxLSR Provides status information on the UART0 TX and
RX blocks
UxFCRControls the operation of the UART0 Rx and TX FIFOs

Note: x-> 0/1 (UART0/UART1)

UxTHR (UART 0/1 Transmit  Holding Register)

The UxTHR is the top byte of the UART0/1 TX FIFO. The top byte is the newest character in the TX FIFO and can be written via the bus interface. The LSB represents the first bit to
transmit.
The Divisor Latch Access Bit (DLAB) in UxLCR must be zero in order to access the
UxTHR. The UxTHR is always Write Only.

UxRBR (UART 0/1 Receiver Buffer Register)

The UxRBR is the top byte of the UART0/1 Rx FIFO. The top byte of the Rx FIFO contains the oldest character received and can be read via the bus interface. The LSB (bit 0) represents the “oldest” received data bit. If the character received is less than 8 bits, the unused MSBs are padded with zeroes.

The Divisor Latch Access Bit (DLAB) in UxLCR must be zero in order to access the
UxRBR. The UxRBR is always Read Only.

UxLCR (UART 0/1 Line Control Register)

The Line Control Register is used to set the format of the data which is transmitted or received. The value or settings in this register configure the UART0/1 block. As this is an 8-bit register. There are several parameters configured through this register such as word length, stop bit, parity enable, parity select, brake control, divisor latch access bit. This register set plays an important role while initializing UART0/1 before using it.

UxFDR (Fractional Divider Register)

This register is used to set the prescale value for baud rate generation. The input clock is the peripheral clock and output is the desired clock defined by this register. This register actually holds to different 4-bit values (a divisor and a multiplier) for prescaling which are:

Important: If the fractional divider is active (DIVADDVAL > 0) and DLM = 0, the value of the DLL register must be 3 or greater

DIVADDVAL: This is the Prescale Divisor value. If this value is 0 then the fractional baud rate generators have no effect on the UART0/1 baud rate.

MULVAL: This defines Prescale Multiplier value. Even if a fractional baud rate generator is not used the value in this register must be more than or equal to ‘1’.

UxDLL & UxDLM (UART 0/1 Divisor Latch registers)

These are standard UART0/1 baud rate generator divider registers. Each of these registers holds 8-bit values. Together these registers form a 16-bit divisor value which will be used for baud rate generation. UxDLM holds the upper 8-bits and UxDLL holds the lower 8-bits and the formation is “[UxDLM: UxDLL]“. Since these form a divisor value and division by zero is invalid, the starting value for UxDLL is 0x01 (and not 0x00) i.e the starting value in combined formation is “[0x00:0x01]” i.e 0x0001. Please keep this in mind while doing baud-rate calculations. In order to access and use these registers properly, the DLAB bit in UxLCR must be first set to 1.

UxLSR (UART 0/1 Line Status Register)

The Line Status Register gives us the information about the RX and TX blocks in UART0/1.

UxFCR (UART 0/1 FIFO Control Register)

The FIFO Control Register controls the operation of the RX and TX FIFOs in UART0/1.

LPC2148 Serial Communication Tutorial

Baud Rate Calculation

By using this below formula we will calculate the Baud Rate.

LPC2148 Serial Communication Tutorial

Example Calculation 1 (Baud Rate 9600 And PCLK = 60MHz)

First Assume U0DLM = 0 , DIVADDVAL = 0 & MULVAL = 1 with PCLK = 60 x 106 Hz

Substitute into that above formula.

U0DLL = 60000000/(16*9600)

U0DLL = 390.625 (~390)

Now the U0DLL value is greater than 255. So we cant store it into this U0DLL Register. Because it is 8-but register.

Now we will change our assumed values.

Now assume U0DLM =1

9600 = 60000000/(16*(256+U0DLL))

4096+16U0DLL = 60000000/9600

16U0DLL = 6250 - 4096

U0DLL = 2154/16

U0DLL = 134.625 (~135)

This U0DLL (135) gives a 9591 Baud Rate. This is less than 9600. But we can take this value. Because less difference only.

Finally,

PCLK = 60MHz

U0DLL = 135

DIVADDVAL = 0

MULVAL =1

U0DLM = 1

Baud Rate = 9600

Example Calculation 2 (Baud Rate 9600 And PCLK = 30MHz)

First Assume U0DLM = 0 , DIVADDVAL = 0 & MULVAL = 1 with PCLK = 30 x 106 Hz

U0DLL = 30000000/(16*9600)

U0DLL = 195.3125 (~195)

This U0DLL (195) gives 9615.38 Baud Rate. This is greater than 9600. But we can take this value. Because less difference only.

PCLK = 30MHz

U0DLL = 195

DIVADDVAL = 0

MULVAL =1

U0DLM = 0

Baud Rate = 9600

Note : 9600 is a pretty famous Baud rate in embedded projects. Some of the standard Baud rates that can be used are : 2400 , 4800 , 7200 , 9600 , 14400 , 19200 , 28800 , 38400 , 57600 , 115200 , 230400 , etc..

Programming Explanation – LPC2148 Serial Communication Tutorial

Initializing UART

Below are the steps for configuring the UART0.

  1. .Configure the GPIO pin for the UART0 function using the PINSEL register.
  2. .Configure LCR for 8-data bits, 1 Stop bit, Disable Parity and Enable DLAB.
  3. .Update the DLM, DLL with the calculated values.
  4. .Finally clear DLAB to disable the access to DLM, DLL.

After this, the UART will be ready to Transmit/Receive Data at the specified baud rate.

void ser_int()
{
	PINSEL0=0X5;
	U0LCR=0X83;            //8-data bits, 1 Stop bit, Disable Parity and Enable DLAB
	U0DLL=135;
	U0DLM=1;
	U0LCR=0X03;            //cleared DLAB
}

Transmit (TX)

  1. Wait till the previous char is transmitted ie. till THRE becomes high in U0LSR Register.
  2. Load the new char to be transmitted into U0THR.

void tx(unsigned char c)
{
	while((U0LSR&(1<<5))==0);    //Checking THRE bit
	U0THR=c;
}

Receive (RX)

  1. Wait till the character is received ie. till RDR becomes high in U0LSR.
  2. Copy the received data from receive buffer(RBR).

char rx()
{
	unsigned char a;
	while((U0LSR&(1<<0))==0);         //Checking RDR bit
	a=U0RBR;
	return a;
}

Code 1

This is like an echo program. Whatever typing it will resend via UART. Here PCLK = 60MHz, BaudRate=9600.

#include<lpc214x.h>

void pll()
{
	PLL0CON=0X01;
	PLL0CFG=0X24;
	PLL0FEED=0XAA;
	PLL0FEED=0X55;
	while((PLL0STAT&(1<<10))==0);
	PLL0CON=0X03;
	PLL0FEED=0XAA;
	PLL0FEED=0X55;
	VPBDIV=0x01;						 //pclk=60mhz
}

void ser_int()
{
	PINSEL0=0X5;
	U0LCR=0X83;
	U0DLL=135;
	U0DLM=1;
	U0LCR=0X03;
}

void tx(unsigned char c)
{
	while((U0LSR&(1<<5))==0);
	U0THR=c;
}

char rx()
{
	unsigned char a;
	while((U0LSR&(1<<0))==0);
	a=U0RBR;
	return a;
}

int main(void)
{
	unsigned char b;
	pll();
	ser_int();
	while(1) {
		b=rx();
		tx(b);
	}
}

Code 2

This is also the same echo program. But Here PCLK = 30MHz, BaudRate=9600.

#include<lpc214x.h>

void pll()
{
	PLL0CON=0X01;
	PLL0CFG=0X24;
	PLL0FEED=0XAA;
	PLL0FEED=0X55;
	while((PLL0STAT&(1<<10))==0);
	PLL0CON=0X03;
	PLL0FEED=0XAA;
	PLL0FEED=0X55;
	VPBDIV=0x02;						 //pclk=30mhz
}

void ser_int()
{
	PINSEL0|=0x05;
	U0LCR=0x83;
	U0DLL=195;
	U0DLM=0;
	U0LCR=0x03;

}

void tx(unsigned char c)
{
	while((U0LSR&(1<<5))==0);
	U0THR=c;
}

char rx()
{
	unsigned char a;
	while((U0LSR&(1<<0))==0);
	a=U0RBR;
	return a;
}

int main(void)
{
	unsigned char b;
	pll();
	ser_int();

	while(1) {
		b=rx();
		tx(b);
	}
}

That is all guys…..You can also try this with UART1.

In our next tutorial, we will see LPC2148 (ARM7) ADC. If you want to use FreeRTOS on LPC2148, then please refer FreeRTOS series.

You can also read the below tutorials.

Linux Device Driver TutorialsC Programming Tutorials
FreeRTOS TutorialsNuttX RTOS Tutorials
RTX RTOS TutorialsInterrupts Basics
I2C Protocol – Part 1 (Basics)I2C Protocol – Part 2 (Advanced Topics)
STM32 TutorialsLPC2148 (ARM7) Tutorials
PIC16F877A Tutorials8051 Tutorials
Unit Testing in C TutorialsESP32-IDF Tutorials
Raspberry Pi TutorialsEmbedded Interview Topics
Reset Sequence in ARM Cortex-M4BLE Basics
VIC and NVIC in ARMSPI – Serial Peripheral Interface Protocol
Bootloader TutorialsRaspberry PI Pico Tutorials
3.7 7 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
9
0
Would love your thoughts, please comment.x