UART communication protocol using ARM LPC1768

Introduction: UART in LPC1768

The LPC 1768 micro-controller consists of 4 UART peripherals. (UART0, UART1, UART2, and UART3). Few of the striking features of these peripherals are:

  • Like any other UART peripheral, they can handle data sizes of 5 to 8 bits.
  • They support 16 bytes receive and transmit FIFOs. Which means that they can store 16-bytes of data in a first in first out fashion without overwriting existing data in the FIFO buffer before it gets filled.
  • It has a built-in baud rate generator.
  • It supports built-in DMA (Direct Memory Access) for transmission and reception which is ideal when data of byte size has to be transmitted and the controller has to be relieved from basic data communication to perform other tasks.
  • It has multi-processor addressing modes and has an IrDA mode to support infrared communication as well.

In this tutorial, we will be learning how to interface the UART0 peripheral to understand the set up of a basic UART communication on the LPC 1768 micro-controller.

 

UART_ARM_cxPin configuration of UART0 module and connection diagram to RS232 level converter

 

Firmware

  • The definitions that are used in the program are as follows:
#define  BAUDRATE            9600
#define  PC_UART0            3

/* CR - Control Register, SR - Status Register, DR - Data Ready */

#define FIFO_CR                LPC_UART0->FCR    
#define LINE_CR                LPC_UART0->LCR
#define LINE_SR                LPC_UART0->LSR

#define TX_BUFFER              LPC_UART0->THR
#define RX_BUFFER              LPC_UART0->RBR

#define WORDLEN_LCR            (0x03<<0)            // 8-bit word length
#define DLAB_LCR               (1<<7)

#define EN_FIFOCR              (1<<0)
#define R0_RESET_FIFOCR        (1<<1)
#define T0_RESET_FIFOCR        (2<<1)

#define RX_DR                  0
#define TX_DR                  5

#define DLLSB                  LPC_UART0->DLL
#define DLMSB                  LPC_UART0->DLM
  • POWER: This is a register that is used to switch on or off the different peripherals in the LPC 1768 module to increase the power efficiency. A particular peripheral block will be turned on or off by gating on or gating of the clock source to that particular block.
    The bit in the PCONP register that controls the clock source to the UART0 peripheral, is PCUART0 or bit 3 in the PCONP register. The reset value of this bit in the power control register is 1. Therefore, it is already powered on reset and even if this step is skipped, the program will work.
    Note: However, the reset value will be 0 for PCUART2 (bit 24) and PCUART3 (bit 25) and therefore, the respective bits must be set before using UART2 and UART3.
LPC_SC->PCONP |= (1<<PC_UART0);
  • CLOCK FREQUENCY: The peripheral clock frequency is set in the peripheral clock selection register (PCLKSEL0). The pair of bits that control the UART0 clock frequency is bits <7:6> named as PCLK_UART0.
    On reset, the value of PCLK_UART0 is 00.
    The following are the functions of the peripheral for different values for PCLK_UART0. In our program, we will be using the default value which is case 1. Therefore the clock frequency is SystemFrequency/4.

Freq Table

Clock_Frequency = SystemFrequency/4;
  • BAUD RATE: There are a few bits that must be set in the U0LCR or the Line Control Register of UART0.
    • The baud rate calculation is done on the basis of values entered in the DLL and DLM registers.
      The formula for baud rate is:
      UART0baudrate = (Clock Frequency/(16*(256 * (U0DLM + U0DLL))*(1+(DivAddVal/MulAddVal))))
      But first, we must gain access to these registers by enabling the DLAB bit in the U0LCR register which is bit 7.
    • The 8-bit character length must also be selected through the U0LCR register by entering values <1,1> for bits 0 and 1.
 LINE_CR = WORDLEN_LCR + DLAB_LCR;

LPC1768 ARM Bit Length

    • Bit 2 in the U0LCR register selects the number of stop bits. Value is set as 0 for 1 stop bit and 1 for 2 stop bits. In our case, we will be setting it as 0 for 1 stop bit.
    • Now that we have access to the U0DLL (UART0 Divisor Latch LSB) register and U0DLM (UART0 Divisor Latch MSB) register, the clock frequency can be entered into the registers.
      Both these registers share 8 bits each of the total 16 bits.
Clock_Frequency = SystemFrequency/4;
Divisor_Latch_Val = (Clock_Frequency/(16 * BAUDRATE )); 
        
DLLSB =  Divisor_Latch_Val & 0xFF;                                //Lower 8 bits of the divisor
DLMSB =  (Divisor_Latch_Val>>8) & 0xFF;                        //Higher 8 bits of the divisor
LINE_CR &= ~DLAB_LCR;  // Clear DLAB after setting DLL,DLM
  • UART FIFO: FIFO is enabled by enabling the FIFO bit in the U0FCR register. Next, both the R0 FIFO and T0 FIFO must be set to 1 to clear the bytes in the respective buffers.
FIFO_CR = EN_FIFOCR + R0_RESET_FIFOCR + T0_RESET_FIFOCR ; // Enable FIFO and reset Rx/Tx FIFO buffers
  • UART0 PINS: The PINSEL0 register controls the functions in the lower half of PORT0. The bits that must be set for UART0 function are as follows.PINSEL0 BITS: <5:4> FUNCTION WHEN: <0:1> is TXD0
    PINSEL0 BITS: <7:6> FUNCTION WHEN: <0:1> is RXD0
    PinSelect &= ~0x000000F0;                        //CLEAR THE TX and RX PINS
    PinSelect |= 0x00000050;            // Enable the tx and rx pins for UART0
  • UART Interrupt: We will not be using the interrupt procedure in our example. But if you want to access the UART interrupt enable register or U0IER, the DLAB bits set for accessing the divisor latch register to enter the baud rate, must be set to 0. In the interrupt register, the lower three bits are set to enable the receive data interrupt (bit 0), THRE interrupt (bit 1) and RX line status interrupt (bit 2).

Transmission and Reception

While transmitting a character, the THRE bit in the Line Status Register or U0LSR is cleared when a valid data is entered in the U0THR register or the UART transmit holding register. Otherwise, it is set to 1.

void UART0_WriteChar(char ch)
{
    while(!((LINE_SR)&(1<<TX_DR)));  // The THRE Bit is 1 when THR is clear and is 0 when a write occurs on UnTHR
    TX_BUFFER = ch; 
}

In the case of receiving a character, it is important to note that the divisor latch access bit (DLAB) must be set to 0 in order to access the U0RBR register which contains the received data. This has already been done in a previous step.

char UART0_ReadChar()
{
    char ch; 
    while(!((LINE_SR)&(1<<RX_DR)));  // 0-UART FIFO EMPTY, 1-UART FIFO FILLED
        ch = RX_BUFFER;                // Read the received data    
    return ch;
}

Summary

A basic serial communication using the UART0 module in the LPC1768 microcontroller has been discussed that runs at a baud rate of 9600. The sample code for UART based on this tutorial is available in the Code Library under the section ARM.