What is a 16×2 LCD?
A 16×2 LCD can display:
- 16 characters in each row
- 2 rows
Therefore, it can display a total of 32 characters at a time.
Most 16×2 LCD modules are compatible with the HD44780 LCD controller. The LCD contains data pins and control pins that allow a microcontroller to send commands and display characters.
LCD Pins
A typical 16×2 LCD has the following pins:
| Pin | Name | Function |
|---|
| 1 | VSS | Ground |
| 2 | VDD | +5V Supply |
| 3 | VEE | Contrast control |
| 4 | RS | Register Select |
| 5 | RW | Read/Write |
| 6 | EN | Enable |
| 7–14 | D0–D7 | Data lines |
| 15 | A | LED backlight anode |
| 16 | K | LED backlight cathode |
In this tutorial, the LCD is used in write mode, so the RW pin is connected to GND.

LPC1768 to LCD Pin Connection
We will use the following GPIO connections:
| LCD Pin | Function | LPC1768 Pin |
|---|
| RS | Register Select | P0.10 |
| RW | Write Mode | GND |
| EN | Enable | P0.11 |
| D0 | Data Bit 0 | P0.15 |
| D1 | Data Bit 1 | P0.16 |
| D2 | Data Bit 2 | P0.17 |
| D3 | Data Bit 3 | P0.18 |
| D4 | Data Bit 4 | P0.19 |
| D5 | Data Bit 5 | P0.20 |
| D6 | Data Bit 6 | P0.21 |
| D7 | Data Bit 7 | P0.22 |
The data pins are connected to consecutive GPIO pins, making the program easier to understand.

Important LCD Control Pins
RS – Register Select
The RS pin decides whether the LCD receives a command or character data.
RS = 0 → Command Register
RS = 1 → Data Register
For example, when we want to clear the LCD or move the cursor, we send a command.
When we want to display a character such as A, H, or 1, we send data.
RW – Read/Write
The RW pin determines whether the LCD is reading or writing.
RW = 0 → Write
RW = 1 → Read
Since this tutorial only sends data to the LCD, RW is permanently connected to GND.
EN – Enable
The Enable pin is used to latch the command or data.
The microcontroller places the required data on the LCD pins and then generates an Enable pulse:
EN = 1
Short delay
EN = 0
The LCD reads the data when the Enable pulse is applied.
LPC1768 GPIO Registers Used
The LPC1768 provides Fast GPIO registers for controlling GPIO pins.
FIODIR – Direction Register
The FIODIR register configures a pin as input or output.
0 → Input
1 → Output
For LCD interfacing, all RS, EN, and data pins are configured as outputs.
Example:
LPC_GPIO0->FIODIR |= (1 << 10);
This configures P0.10 as an output.

FIOSET – Set GPIO Pin
The FIOSET register makes a GPIO output pin HIGH.
LPC_GPIO0->FIOSET = (1 << 10);
This makes P0.10 logic HIGH.
For the LCD, this is useful when setting:
FIOCLR – Clear GPIO Pin
The FIOCLR register makes a GPIO output pin LOW.
LPC_GPIO0->FIOCLR = (1 << 10);
This clears P0.10.
For the LCD, this can be used when setting:
FIOPIN – Read or Write Pin Value
FIOPIN represents the current value of the GPIO pins.
It can be used to read inputs or write output values. However, when working with individual pins, FIOSET and FIOCLR are generally easier to understand.
LCD Initialization Commands
Before displaying data, the LCD must be initialized.
Some commonly used commands are:
| Command | Function |
|---|
| 0x38 | 8-bit mode, 2 lines, 5×7 font |
| 0x0C | Display ON, Cursor OFF |
| 0x01 | Clear LCD |
| 0x06 | Cursor increments automatically |
| 0x80 | Move cursor to first line |
| 0xC0 | Move cursor to second line |
These commands configure the LCD before normal data is displayed.
LPC1768 LCD Interfacing Program
The following program displays messages on a 16×2 LCD.
#include
#define RS (1 << 10)
#define EN (1 << 11)
#define DATA_MASK (0xFF << 15) void delay(unsigned int count); void lcd_cmd(unsigned char cmd); void lcd_data(unsigned char data); void lcd_string(char *str); void lcd_init(void); int main(void) { /* Configure P0.10 and P0.11 as GPIO */ LPC_PINCON->PINSEL0 &= ~((3 << 20) | (3 << 22)); /* Configure P0.15 to P0.22 as GPIO */ LPC_PINCON->PINSEL0 &= ~(3 << 30); LPC_PINCON->PINSEL1 &= ~((0x3FFF) << 0); /* Configure LCD pins as output */ LPC_GPIO0->FIODIR |= RS | EN | DATA_MASK;
lcd_init();
lcd_string("Embedded Empire");
lcd_cmd(0xC0);
lcd_string("LPC1768 LCD");
while(1);
}
void lcd_cmd(unsigned char cmd)
{
/* RS = 0 for command */
LPC_GPIO0->FIOCLR = RS;
/* Clear old data */
LPC_GPIO0->FIOCLR = DATA_MASK;
/* Send command */
LPC_GPIO0->FIOSET = ((unsigned int)cmd << 15); /* Enable pulse */ LPC_GPIO0->FIOSET = EN;
delay(100);
LPC_GPIO0->FIOCLR = EN;
delay(3000);
}
void lcd_data(unsigned char data)
{
/* RS = 1 for data */
LPC_GPIO0->FIOSET = RS;
/* Clear old data */
LPC_GPIO0->FIOCLR = DATA_MASK;
/* Send character data */
LPC_GPIO0->FIOSET = ((unsigned int)data << 15); /* Enable pulse */ LPC_GPIO0->FIOSET = EN;
delay(100);
LPC_GPIO0->FIOCLR = EN;
delay(3000);
}
void lcd_string(char *str)
{
while(*str)
{
lcd_data(*str++);
}
}
void lcd_init(void)
{
delay(50000);
lcd_cmd(0x38);
lcd_cmd(0x0C);
lcd_cmd(0x01);
lcd_cmd(0x06);
}
void delay(unsigned int count)
{
volatile unsigned int i;
for(i = 0; i < count; i++);
}
Program Explanation
Configuring the GPIO Pins
The RS and EN pins are configured as GPIO:
LPC_PINCON->PINSEL0 &= ~((3 << 20) | (3 << 22));
This selects the GPIO function for P0.10 and P0.11.
The data pins P0.15 to P0.22 are also configured for GPIO. After selecting the GPIO function, all the LCD pins are configured as output:
LPC_GPIO0->FIODIR |= RS | EN | DATA_MASK;
The LCD requires the microcontroller to send signals to it, so these pins must operate as output pins.
Sending a Command
The function lcd_cmd() is used to send LCD commands.
First:
LPC_GPIO0->FIOCLR = RS;
sets RS to 0, selecting the command register.
Then the command is placed on the eight data lines:
LPC_GPIO0->FIOSET = ((unsigned int)cmd << 15);
The value is shifted by 15 because the LCD data pins start from P0.15.
Finally, the Enable pin is pulsed HIGH and LOW so that the LCD accepts the command.
Sending Display Data
The function lcd_data() sends characters to the LCD.
LPC_GPIO0->FIOSET = RS;
sets RS to 1, selecting the data register.
For example, if the program sends:
lcd_data('A');
the ASCII value of the character A is placed on the data pins, and an Enable pulse transfers it to the LCD.
Displaying a String
The lcd_string() function sends one character at a time:
while(*str)
{
lcd_data(*str++);
}
If the string is:
"Embedded Empire"
each character is transmitted individually until the null character \0 is reached.
How LCD Interfacing Works
The overall process can be understood as:
Initialize GPIO Pins
↓
Configure LCD Pins as Output
↓
Initialize LCD
↓
RS = 0 → Send Command
↓
RS = 1 → Send Character Data
↓
Generate Enable Pulse
↓
LCD Displays the Character
