Liquid crystal displays (LCD) are widely used in various electronic applications. It is commonly used in different systems to indicate different states and parameters. LCD16x2 has 2 lines with 16 characters on each line. Each character consists of a 5×8 (column x line) pixel matrix.

LCD16x2 Pin Description

Pin 3 – VEE pin 

This pin is used to adjust the contrast of the display. The voltage on this pin defines the contrast on the screen; the lower the voltage, the higher the contrast. We can hook up a 4.7k potentiometer to adjust the contrast or connect this pin to the ground for maximum contrast.

Pin 4 –RS: Register Select pin

            RS = 0: Data on the D0 to D7 pins is considered as a command.

            RS = 1: Data on the D0 to D7 pins is considered as data to display on LCD16x2.

Pin 5 – RW: Read / Write pin

             RW = 0: Write data to the LCD

             RW = 1: Read data from the LCD

Pin 6 –E: Enable

This pin is used to block the data present at data pins D0 to D7. To lock the data on the screen, a high to low pulse with a minimum width of 450 ns is required.

Pins 7:14 – DATA pins D0 to D7

Data pins are used to send data/commands to the LCD16x2 as parallel 8 data bits.

Pin 15:16 – LED + and LED –

Liquid crystal displays do not have their own light like seven-segment displays. Therefore the module has a backlight LED. This LED is supplied via these pins.

LCD16x2 Commands

While we have an LCD16x2 interacting with any microcontroller, we need to initialise the LCD first. To do this, we need to send some commands in a similar way to clear the screen or change the position we need to send commands, so we can basically say that LCD16x2 is controlled by commands.

Commonly Used LCD16x2 Commands

Code (HEX)Command to LCDExecution Time
0x01Clear the display screen1.64ms
0x06Shift the cursor right (e.g. data gets written in an incrementing order, left to right)40 us
0x0CDisplay on, cursor off40 us
0x0EDisplay on, cursor blinking40 us
0x80Force the cursor to the beginning of the 1st line40 us
0xC0Force the cursor to the beginning of the 2nd line40 us
0x10Shift cursor position to the left40 us
0x14Shift cursor position to the right40 us
0x18Shift the entire display to the left40 us
0x1CShift the entire display to the right40 us
0x382 lines, 5×8 matrix, 8-bit mode40 us
0x282 lines, 5×8 matrix,4-bit mode40 us
0x301 line, 8-bit mode40us
0x201 line, 4-bit mode40us

Printing a character to LCD16x2, we need to send the ASCII code of that character to LCD16x2. Suppose we want to print the character ‘H’ on the LCD, then we need to send 0x48 data (ASCII code of ‘H’) to LCD16x2. The LCD16x2 has its own controller, which takes over the printing work on the LCD16x2.

Custom Character in LCD16x2

Print the character symbol on the LCD. We need to send the ASCII code. LCD16x2 also has a feature that allows us to print our custom character that is not in the ASCII character set.


LCD16x2 has a 64-byte storage space called CGRAM (Character Generator RAM). It is used to create custom patterns. We just need to write custom pixel values ​​to this space.

While we are providing the CGRAM address, we must always keep the DB6 line high. This means that the address starts at 0x40 to store user-defined characters in the CGRAM.

Building custom character

In LCD16x2, a character is made up of a 5×8 pixel matrix; imagine we need to design a custom bell-shaped character, like in the diagram, we need to define pixel values, 0 for OFF pixels and 1 for ON pixels.