UART

Using UART of LPC2148

Theory

The RS-232 serial communication protocol is a standard protocol used in asynchronous serial communication.  An interface chip known as the universal asynchronous receiver/transmitter or UART is used to implement serial data transmission.  The output from the UART is a standard TTL/CMOS logic level of 0 or 5 volts. In order to improve bandwidth, remove noise, and increase range, this TTL logical level is converted to an RS-232 logic level of -12 or +12 volts before being sent out on the serial channel.

DTE and DCE

DTE stands for Data Terminal Equipment. A computer is a DTE. DCE stands for Data Communication Equipment. A modem is a DCE.

RS-232 Pin outs (DB-9)

DB9 pinout for RS232
DB9 pinout for RS232

The graphic above illustrates a typical RS-232 logic waveform (Data format: 1 Start bit, 8 Data bits, No Parity, 1 Stop bit). The data transmission starts with a Start bit, followed by the data bits (LSB sent first and MSB sent last), and ends with a “Stop” bit. The voltage of Logic “1” (Mark) is between -3VDC to -15VDC, while the Logic “0” (Space) is between +3VDC to +15VDC. RS-232 connects the Ground of 2 different devices together, which is the so-called “Unbalanced” connection. An unbalanced connection is more susceptible to noise, and has a distance limitation of 50 ft (which is around 15 meters).

U0TX: The UART0 transmitter block, U0TX, accepts data written by the CPU or host and buffers the data in the UART0 TX Holding Register FIFO (U0THR). The UART0 TX Shift Register (U0TSR) reads the data stored in the U0THR and assembles the data to transmit via the serial output pin, TXD0.

 

U0BRG:The UART0 Baud Rate Generator block, U0BRG, generates the timing enables used by the UART0 TX block. The U0BRG clock input source is the APB clock (PCLK). The main clock is divided down per the divisor specified in the U0DLL and U0DLM registers. This divided down clock is a 16x oversample clock, NBAUDOUT.

 

U0RX: The UART0 receiver block, U0RX, monitors the serial input line, RXD0, for valid input. The UART0 RX Shift Register (U0RSR) accepts valid characters via RXD0. After a valid character is assembled in the U0RSR, it is passed to the UART0 RX Buffer Register FIFO to await access by the CPU or host via the generic host interface.

U0LCR: The U0LCR determines the format of the data character that is to be transmitted or received.

UART_2

UART0 Divisor Latch Registers: The UART0 Divisor Latch is part of the UART0 Fractional Baud Rate Generator and holds the value used to divide the clock supplied by the fractional prescaler in order to produce the baud rate clock, which must be 16x the desired baud rate (Equation 1). The U0DLL and U0DLM registers together form a 16 bit divisor where U0DLL contains the lower 8 bits of the divisor and U0DLM contains the higher 8 bits of the divisor. A 0x0000 value is treated like a 0x0001 value as division by zero is not allowed. The Divisor Latch Access Bit (DLAB) in U0LCR must be one in order to access the UART0 Divisor Latches.

UART_4
UART0 Fractional Divider Register

The UART0 Fractional Divider Register (U0FDR) controls the clock pre-scaler for the baud rate generation and can be read and written at user’s discretion. This pre-scaler takes the APB clock and generates an output clock per specified fractional requirements. Important: If the fractional divider is active (DIVADDVAL > 0) and DLM = 0, the value of the DLL register must be 3 or greater. 

UART_3

UART0 baud rate can be calculated as:

UART_5

Where PCLK is the peripheral clock, U0DLM and U0DLL are the standard UART0 baudrate divider registers, and DIVADDVAL and MULVAL are UART0 fractional baudrategenerator specific parameters.The value of MULVAL and DIVADDVAL should comply with the following conditions:

  1. 0 < MULVAL <=15

2. 0 <= DIVADDVAL <= 15

If the U0FDR register value does not comply with these two requests then the fractional divider output is undefined. If DIVADDVAL is zero then the fractional divider is disabled and the clock will not be divided. The value of the U0FDR should not be modified while transmitting/receiving data or data may be lost or corrupted.


UART0 Receiver Buffer Register (U0RBR)

The U0RBR is the top byte of the UART0 Rx FIFO. The top byte of the Rx FIFO containsthe 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, theunused MSBs are padded with zeroes.

The Divisor Latch Access Bit (DLAB) in U0LCR must be zero in order to access theU0RBR. The U0RBR is always Read Only.Since PE, FE and BI bits correspond to the byte sitting on the top of the RBR FIFO (i.e.the one that will be read in the next read from the RBR), the right approach for fetching thevalid pair of received byte and its status bits is first to read the content of the U0LSRregister, and then to read a byte from the U0RBR.

 UART0 Transmit Holding Register (U0THR)

The U0THR is the top byte of the UART0 TX FIFO. The top byte is the newest character inthe TX FIFO and can be written via the bus interface. The LSB represents the first bit totransmit.The Divisor Latch Access Bit (DLAB) in U0LCR must be zero in order to access theU0THR. The U0THR is always Write Only.

Schematic

uart_LPC2148

Source Code:

 #include <LPC214X.H>
void UART0_Init(void);
void UART0_Write(unsigned char value);
void UART0_Write_String(unsigned char *CPtr);
unsigned char UART0_ReadByte(void);
void delay(unsigned long val);
voidwrite_command(intcmd);
voidwrite_data(int data);
voidlcd_command(char cmd);
voidlcd_data(char data); 
voidinit_lcd(void);
voidprintlcd(char *CPtr);

int main()
{
UART0_Init();
init_lcd();
printlcd("RX::");
UART0_Write_String("UART0 TEST1");
while(1)
{
lcd_data(UART0_ReadByte());
UART0_Write(UART0_ReadByte());
}
}

void UART0_Init()
{
PINSEL0 |= ((1<<0) | (1<<2));
U0LCR = 0x83;
U0DLL = 0X4e;
U0DLM = 0X00;
U0LCR = 0X03;
}

void UART0_Write(unsigned char value)
{
while((U0LSR&0x20) == 0);
U0THR = value;
}

unsigned char UART0_ReadByte()
{
while((U0LSR&0x01) == 0);
return U0RBR;
}

void UART0_Write_String(unsigned char *CPtr)
{
while(*CPtr!='\0')
{
UART0_Write(*CPtr);
CPtr++;
delay(20000);
}}

void delay(unsigned long val)
{
while (val>0)
{val--;}
}

voidprintlcd(char *CPtr)
{
while(*CPtr!='\0')
{
lcd_data(*CPtr);
CPtr++;
delay(20000);
}}
voidinit_lcd(void)
{
IO1DIR  = 0x00fe0000;
lcd_command(0x03);
delay(100000);
lcd_command(0x03);
delay(100000);
lcd_command(0x02);
delay(100000);
lcd_command(0x01);
delay(10000);
lcd_command(0x60);
delay(10000);
lcd_command(0x0c);
delay(10000);
lcd_command(0x80);
delay(10000);
}

voidlcd_data(char data)
{
char shift_data2;
shift_data2= data & 0XF0;
write_data(shift_data2);
shift_data2= (data<<4) & 0XF0;
write_data(shift_data2);
}
voidlcd_command(char cmd)
{
char shift_data1;
shift_data1= cmd& 0XF0;
write_command(shift_data1);
shift_data1= (cmd<<4) & 0XF0;
write_command(shift_data1);
}
voidwrite_command(intcmd)
{
IO1CLR=0x00fe0000;
IO1CLR=0x00060000;//RS=RW=0
cmd=cmd<<16;
IO1SET=cmd;
IO1SET=0x00080000;
delay(100000);
IO1CLR=0x00080000;
delay(10000);
}
voidwrite_data(int data)
{
IO1CLR=0x00fe0000;
IO1SET=0x00020000;//RS=1
data=data<<16;
IO1SET=data;
IO1SET=0x00080000;
delay(100000);
IO1CLR=0x00080000;
delay(10000);
}

 

Sending data from UART

void UART0_Write(unsigned char value)
{
while((U0LSR&0x20) == 0);
U0THR = value;
}

To send the data using UART we have used a function names UART0_write. In this function we check the status of U0LSR register. If the value of the 5th bit of this register is 0 then U0THR consists of the valid data.  After the 5th bit is 0 we put the value to send on U0THR.

Receiving Data from UART

unsigned char UART0_ReadByte()
{
while((U0LSR&0x01) == 0);
return U0RBR;
}

While receiving the data we check the first bit of U0LSR register and if the bit is 0 U0RBR register is empty and if it is 1 then the register will have valid data .

Steps to read data from UART0 and display on the HyperTerminal

  1. Configure the microcontroller on the baud rate that we are going to select in computer for the serial communication.
  2. Send data from the microcontroller.
  3. Configure hyper terminal software by setting 8 data bits 1 stop bit, no parity bit and flow control to none.
  4.  Set the baud rate in HyperTerminal as configures in the microcontroller.
  5. Reset the microcontroller to observe the data transfer.

Share