Interfacing a 16x2 LCD display with 8051 microcontrollers
Tags: embedded, lcd, 8051, display
Published: 2023-12-20 18:43:48

---
title: Interfacing a 16x2 LCD display with 8051 microcontrollers
published: true
cover_image: https://res.cloudinary.com/krypt9/image/upload/f_avif,q_100,c_lfill,g_auto,w_1100,h_582/madhusudanlive/images/lcd-16x2-interfaced-at89c52-8052.png
date: 2023-10-24 22:30:00 UTC
tags: embedded,lcd,8051,display
canonical_url: https://madhusudan.live/blog/interfacing-16x2-lcd-with-8051
---

## [Introduction](/blog/interfacing-16x2-lcd-with-8051#introduction)

LCDs are used for various applications in electronic systems, almost every kiosk, any kind of meter, signboards and almost all the systems we see, use smaller or bigger display. today we will cover how to interface a 16X2 Liquid Crystal Display with an 8051/52 microcontroller, the connections and code is provided below.

## [8051/8052 Family](/blog/interfacing-16x2-lcd-with-8051#_80518052-family)

Firstly let me brief you about the 8051 series, 8051 is a popular 8-bit microcontroller family developed by Intel, this family had 4KB of ROM or program memory and a 128 bytes of RAM, the 8052 family is also similar to 8051 just it has an additional ROM of 4KB i.e. total of 8KB and also additional RAM of 128 bytes, making a total of 256bytes, We will be using **AT89S52** , it is the widely popular microcontroller for small-scale projects with powerful hardware. it sports 8 KB of program memory (ROM) and 256 bytes of RAM and 4 ports, for peripherals. after its launch it became widely popular for various applications and currently it is available in multiple versions in market by different vendors, this hardware is more than enough for our use case, we can also use **AT89S51** as well.

## [Components](/blog/interfacing-16x2-lcd-with-8051#components)

- 1 - 16X2 LCD
- 1 - AT89S51/2 Microcontroller ( For controlling the LCD )
- 1 - Potentiometer ( For adjusting the Backlight of LCD )
- 12 Approx. - connecting wires

## [16X2 LCD](/blog/interfacing-16x2-lcd-with-8051#_16x2-lcd)

In your day to day life, you must have seen small green coloured displays from various appliances like DVD Players, Medical Devices, Industrial Control Panels, Energy Meters. those green coloured display are called as 16X2 LCD displays, The term LCD stands for Liquid Crystal Display the 16 refers to the number of rows and the 2 as number of columns. these are used in variety of applications like many consumer electronic devices, embedded systems, control panels, information kiosks, weighing machines at public places and the list goes on.

The 16X2 LCD can be configured in two modes i.e. 8-bit mode and 4-bit mode, for the sake of simplicity we will be using 8-bit mode. So connect the data pins to the desired port of the microcontroller, but be careful with the PORT 0, it doesn’t have internal pull-ups, so in order to use the PORT 0 you need to connect external pull-up resistors.

## [Pin configuration of 16x2 LCD](/blog/interfacing-16x2-lcd-with-8051#pin-configuration-of-16x2-lcd)

| sr no | name | function |
| --- | --- | --- |
| 1 | VSS | ground |
| 2 | VDD | power supply ( +5V ) |
| 3 | VEE | contrast |
| 4 | RS | register select |
| 5 | R/W | read / write 0=write 1=read |
| 6 | E | enable |
| 7-14 | Data | Data lines |
| 15 | A | Anode ( LCD Backlight ) |
| 16 | K | Cathode ( LCD Backlight ) |

Here I am connecting the LCD to PORT 1, and other pins i.e.

1. RS ( Register Select ) : PORT2\_0
2. R/W ( Read/Write ) : PORT2\_1
3. E ( Enable ) : and PORT2\_2.

![Block diagram of LCD interfaced with AT89s52 microcontroller](https://res.cloudinary.com/krypt9/image/upload/f_avif,q_auto:good,c_lfill,g_auto,w_2400/madhusudanlive/images/arduino-with-lcd.png "Block Diagram of 16x2 interfaced with AT89s52 MCU")
_Block Diagram of 16x2 interfaced with AT89s52 MCU_

<meta itemprop="name" content="Madhusudan Babar">

For simplicity, here I have not shown the LCD contrast, `VCC`, `GND`, and pins but make their connections too, connect the `VCC` to +5V, `GND` to ground and the contrast to the Ground through a potentiometer. As our Connections part is done, we will write a program to print "KRYPTON" on this LCD.

## [16X2 LCD Commands](/blog/interfacing-16x2-lcd-with-8051#_16x2-lcd-commands)

LCD Commands are the crucial instructions for the Display to perform certain tasks, these commands needs to be sent to LCD in order to work properly

| sr no. | Command | Purpose |
| --- | --- | --- |
| 1 | 0x01 | Clear Screen |
| 2 | 0x02 | Return Home |
| 3 | 0x04 | Decrement/Shift Cursor Left |
| 4 | 0x05 | Shift Display Right |
| 5 | 0x06 | Increment/Shift Cursor Right |
| 6 | 0x07 | Shift Display Left |
| 7 | 0x08 | Display Off, Cursor Off |
| 8 | 0x0A | Display Off, Cursor On |
| 9 | 0x0C | Display On, Cursor Off |
| 10 | 0x0E | Display On, Cursor On |
| 11 | 0x0F | Display On, Cursor Blink |
| 12 | 0x10 | Shift cursor position to left |
| 13 | 0x14 | Shift cursor position to Right |
| 14 | 0x18 | Shift entire display to left |
| 15 | 0x1C | Shift entire display to Right |
| 16 | 0x80 | Force cursor to beginning of 1st line |
| 17 | 0xC0 | Force cursor to beginning of 2nd line |
| 18 | 0x38 | 2 lines 5x7 matrix |

## [C Program for AT89S52 (8052) Microcontroller](/blog/interfacing-16x2-lcd-with-8051#c-program-for-at89s52-8052-microcontroller)

```
#include<AT89X52.h> //header file
#define RS P2_0 //register select pin
#define RW P2_1 //read/write pin
#define EN P2_2 //enable pin
#define PORT P1
void delay(); //delay function
void com(char ); //to send command to LCD
void dat(char ); //to send data to LCD
void print(char ); //our function to print the name.

void main(){
    while(1){
        char text[]="KRYPTON";
        int i,n=0;
        com(0x0c); // display on cursor off
        com(0x01); //clear screen
        while(text[i]!='\0'){ //continue to print till we get the null character
      // this block is intentionally commented. to be used when printing more than 16 characters
      /* if(i>15){
                com(0x1c); //shift display left
                com(0x0c);
            }
      */
            print(text[i]);
            i++;
        }
        while(9);
    }
}

void print(char c){
    com(0x06); // shift cursor to right >>>>>>
    dat(c); // pass the character to LCD
}

void delay(){
    short int i;
    for(i=0;i<=255;i++);
}

void com(char m){
    PORT=m;
    RS=0;
    RW=0;
    EN=1;
    delay();
    EN=0;
    delay();
}

void dat(char m){
    PORT=m;
    RS=1;
    RW=0;
    EN=1;
    EN=0;
    delay();
}
```

In the code above, we have defined few macros for the connections to the PORTS of our microcontroller, we have included the `AT89X52.h` header file to interact with the microcontroller, the same code works for at89s52, at89c52 or other 8052 family of microcontrollers, after that we have declared prototypes of few functions, that we have provided definitions after the `main` function. the `delay` function adds a short delay which is necessary as this LCD requires a High To Low pulse of ~10ms,function `com` is for command and `dat` is for passing data or text to our display, the function `print` is responsible for shifting the cursor and printing characters.

So in the function `main`, we have defined an array of characters to store our name, next lines are to initialize the LCD, i.e. turn on the display and clear the screen (initialization process). Now we have a function `print` that simply takes the character and displays it on the LCD by incrementing the cursor (i.e. shifting the cursor to the right). So calling the print function will take one character at a time and then do the cursor shifting operation and finally pass the character to the data function that displays it.

But as our LCD has some speed limitations, we cannot pass the values repeatedly in a short span, we need to add some delay otherwise the LCD will ignore the input, thus we are calling our delay function after every command or data function call, actually, there is a proper way to do so by checking the LCD busy flag, then sending the data else waiting till the busy flag clears, but this becomes very much complex, so we are not using the actual busy flag method instead we have used a simple for loop to clear the delay. the last line `while(9)` is intentionally placed there, as we don't want to perform any operation once our name is printed, the `while(9)` is an infinite loop so there will be no operation after printing "KRYPTON".

If you read the code, you'll find that there is a commented block, which you can use if you want to print longer words, this block will shift the display making you space available for the new characters.

## [Preview of LCD interfaced with 8051](/blog/interfacing-16x2-lcd-with-8051#preview-of-lcd-interfaced-with-8051)

![Photo of LCD with KRYPTON written on it](https://res.cloudinary.com/krypt9/image/upload/f_avif,q_auto:good,c_lfill,g_auto,w_2400/madhusudanlive/images/lcd-with-krypton.heic "16x2 LCD with krypton written on it")
_16x2 LCD with krypton written on it_

<meta itemprop="name" content="Madhusudan Babar">

## [Code for AT89S51 (8051) microcontroller](/blog/interfacing-16x2-lcd-with-8051#code-for-at89s51-8051-microcontroller)

The only change here is header file changed to AT89S51 specific, rest of the code is similar and you can use it with AT89X51 microcontroller.

```
#include<AT89X51.h> //header file is changed to **AT89X51.h**
#define RS P2_0 //register select pin
#define RW P2_1 //read/write pin
#define EN P2_2 //enable pin
#define PORT P1
void delay(); //delay function
void com(char ); //to send command to LCD
void dat(char ); //to send data to LCD
void print(char ); //our function to print the name.

void main(){
    while(1){
        char text[]="KRYPTON";
        int i,n=0;
        com(0x0c); // display on cursor off
        com(0x01); //clear screen
        while(text[i]!='\0'){ //continue to print till we get the null character
      // this block is intentionally commented. to be used when printing more than 16 characters
      /* if(i>15){
                com(0x1c); //shift display left
                com(0x0c);
            }
      */
            print(text[i]);
            i++;
        }
        while(9);
    }
}

void print(char c){
    com(0x06); // shift cursor to right >>>>>>
    dat(c); // pass the character to LCD
}

void delay(){
    short int i;
    for(i=0;i<=255;i++);
}

void com(char m){
    PORT=m;
    RS=0;
    RW=0;
    EN=1;
    delay();
    EN=0;
    delay();
}

void dat(char m){
    PORT=m;
    RS=1;
    RW=0;
    EN=1;
    EN=0;
    delay();
}
```

## [Additional Links:](/blog/interfacing-16x2-lcd-with-8051#additional-links)

- [16x2 Datasheet](https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf)
- [AT89S52 Datasheet](https://pdf1.alldatasheet.com/datasheet-pdf/view/82390/ATMEL/AT89S52.html)
- [Intel 8051 Family](https://en.wikipedia.org/wiki/Intel_8051)

## [conclusion](/blog/interfacing-16x2-lcd-with-8051#conclusion)

16X2 display can be used to print the useful information/status for small scale project, embedded systems, these displays operate on 3.3V to 5V DC source and doesn't require much configuration, also these displays comes with an option to adjust the contrast levels so one can increase/decrease the contrast of the display for proper viewing experience. overall these displays can be a great choice for small texts like status informations, etc, also we can emulate scrolling text behaviour to display characters more than 16 in length.

[Interface Dot Matrix Display with Arduino: Code & Connections](https://madhusudan.live/blog/interfacing-dot-matrix-display-with-arduino), [Secarmy CTF 2.0 junior walkthrough - team krypton](/blog/secarmy-ctf-2-0)
Keywords:
[embedded](https://madhusudan.live/tag/embedded), [lcd](https://madhusudan.live/tag/lcd), [8051](https://madhusudan.live/tag/8051), [display](https://madhusudan.live/tag/display), [electronics](https://madhusudan.live/tag/electronics), [programming](https://madhusudan.live/tag/programming), [microcontroller](https://madhusudan.live/tag/microcontroller)
<meta itemprop="keywords" content="embedded, lcd, 8051, display, electronics, programming, microcontroller, pin, guide, 8051 lcd, 8051 lcd interfacing, interfacing lcd with 8051, 4 bit, 8 bit, AT89S51, AT89S52, tutorial, lcd 16x2, code in c, C program, datasheet, lcd display, step by step, lcd commands, lcd pin configuration, configuration, lcd 16x2 pinout, embedded systems, lcd 16x2 datasheet, lcd display interfacing with 8051, 8051 Microcontroller, liquid crystal display" data-v-de991c7a=""><meta itemprop="about" content="embedded, lcd, 8051, display, electronics, programming, microcontroller, pin, guide, 8051 lcd, 8051 lcd interfacing, interfacing lcd with 8051, 4 bit, 8 bit, AT89S51, AT89S52, tutorial, lcd 16x2, code in c, C program, datasheet, lcd display, step by step, lcd commands, lcd pin configuration, configuration, lcd 16x2 pinout, embedded systems, lcd 16x2 datasheet, lcd display interfacing with 8051, 8051 Microcontroller, liquid crystal display" data-v-de991c7a="">