16×2 Character LCD Interfacing using LPC1768

Introduction

In this tutorial, we will be learning how to interface a 16 x 2 character LCD display (HD44780U )with the LPC 1768 micro-controller. The 16 x 2 character LCD display is one of the most basic display module used by beginners while learning embedded systems.
16 characters can be displayed on the screen at a time across two lines. Each of these 16 characters is displayed using pixels that are arranged in a 5 x 7 matrix format.

LCD_model

LCD interface on ARM Base board

 

Features

  • The LCD module has 16 pins.
  • It can be configured either in 4-bit or 8-bit mode. The 4-bit mode helps in saving an extra 4-pins in the circuitry.
  • Controller and driver are automatically reset after power on.
  • Instruction functions that include: Display clear, cursor home, display on/off, cursor on/off, display character blink, cursor shift, display shift

LCD_

Connection diagram for data port and control port of LCD

 

Pin Functions

This is a list of pin functions interfaced with the micro-controller.

16x2 Character LCD Control

Registers

The two 8-bit registers in the HD44780U 16 x 2 character LCD display are

  • Instruction Register (IR)
    Instruction functions are written from the micro-controller to this register for Display Data RAM (DDRAM) and Character Generator RAM (CGRAM).
  • Data Register (IR)
    This register temporarily holds the data to be written into the DDRAM or the CGRAM from the micro-controller. It also temporarily holds the data that is being read from the two registers.

Programming

Interfacing the LCD module with any micro-controller is very easy. It involves only a few functions that instruct the LCD to perform specific tasks and read or write data in the LCD.
Here, we will be doing an 8-bit interfacing with the LPC1768 micro-controller and only perform a write operation on the LCD.

DEFINITIONS:

//*****************************************************************************************************
// Default DATA PORT in OpenLab is PORTB. P0[16:23]
// Default CONTROL PORT in OpenLab is PORTC  P1[16:23]
//*****************************************************************************************************
#define DATA_BUS                              LPC_GPIO0->FIODIR
#define CONTROL_BUS                           LPC_GPIO1->FIODIR
//*****************************************************************************************************

//*****************************************************************************************************
// Control Port definitions
//*****************************************************************************************************
#define CONTROL_SET                           LPC_GPIO1->FIOSET
#define CONTROL_CLEAR                         LPC_GPIO1->FIOCLR
#define RS              18    
#define RW              17    
#define EN           16    
//*****************************************************************************************************

//*****************************************************************************************************
// Data Port definitions
//*****************************************************************************************************
#define DATA_SET                             LPC_GPIO0->FIOSET
#define DATA_CLEAR                           LPC_GPIO0->FIOCLR
#define DATA0      16    
#define DATA1      17    
#define DATA2      18    
#define DATA3      19    
#define DATA4      20    
#define DATA5      21    
#define DATA6      22    
#define DATA7      23    
//*****************************************************************************************************

//*****************************************************************************************************
//Control and Data Mask
//*****************************************************************************************************
#define CONTROL_MASK     ((1<<RS)|(1<<RW)|(1<<EN))
#define DATA_MASK       ((1<<DATA7)|(1<<DATA6)|(1<<DATA5)|(1<<DATA4)|(1<<DATA3)|(1<<DATA2)|(1<<DATA1)|(1<<DATA0))
//*****************************************************************************************************

 

PORT INITIALIZATION: The directions of the three instruction register pins and the 8 data register pins must be set as output.
We have defined mask bits to achieve this.

void INIT_PORTS()
{
    DATA_BUS = DATA_MASK;        
    CONTROL_BUS    =    CONTROL_MASK;        
    INIT_LCD();
}

COMMAND FUNCTION: The LCD has to be configured using certain commands in the instruction register. These commands or any data for that matter has to be written to the registers of the LCD by signaling a high to low transition on the enable pin. The delay between the transition varies based on each command or data written. For a general function, a 1-millisecond delay would be good enough. Every command should be sent with the RS and RW pins cleared.

void SEND_CMD(unsigned char cmd)
{
    SEND_BITWISE(cmd);                                                                              
    CONTROL_CLEAR = (1<<RS)|(1<<RW);
    CONTROL_SET = (1<<EN);                                          
    delay_ms(1);
    CONTROL_CLEAR = (1<<EN);
}

COMMANDS: A basic set of commands that must be written to the LCD for initialization are as follows. This will set the LCD in 8-bit mode. It can access both the lines and display matrix is 5*7.

void INIT_LCD()
{
    SEND_CMD(0x38);              //Initialize LCD in 8-bit mode. 2 Lines. 5*7 mode
    SEND_CMD(0x0C);              //Display ON cursor OFF
    SEND_CMD(0x01);              // Clear display
    SEND_CMD(0x06);              //Shift cursor to the right
    SEND_CMD(0x80);              //Force the cursor to the beginning of the line
}

WRITE FUNCTIONS: Similar to writing the commands in the instruction register, the functions for data write is pretty much the same with the exception that the RS pin must be kept high before the high to low transition. The programmer can develop functions that can send characters as well as strings. A function to write the characters is shown below

void SEND_CHAR_DATA(unsigned char data)
{
    SEND_BITWISE(data);    
    CONTROL_CLEAR =  (1<<RS)|(1<<RW);
    CONTROL_SET = (1<<RS)|(1<<EN); 
    delay_ms(1);
    CONTROL_CLEAR = (1<<EN);
    CONTROL_CLEAR = (1<<RS);    
}

The character LCD can be used to display sensor values, count values or display any kind of texts.

Another write function is created in order to send a string of data to the LCD controller.

void SEND_STRING_DATA(char *str)
{
    while(*str!='\0')
    {
        SEND_CHAR_DATA(*str);
        str++;
    }
}

Summary

The above tutorial will guide you to interface a 16*2 Character LCD using a 32 bit LPC1768 ARM Cortex M3 microcontroller. The sample code based on this tutorial is available in the Code Library under the section ARM.