Saturday, July 27, 2013

LCD interfacing in 4 bit mode using AT89s52

   Today I am going to make you learn to interface LCD(based on HD44780 LCD controller) in four bit mode using AT89s52 MCU. First, I will tell some basic knowledge about 16*2 LCD, then I will go with all the process required while interfacing this device with MCU. This paper will provide all the knowledge required like sending command , sending data which is required to display and reading data from display
RAM(DRAM) of LCD. The data sheet of HD44780 controller can be downloaded by clicking here.


HARDWARE DESCRIPTION:-
First, I am going to start with the pin configuration of LCD which is shown below in figure a.



lcd pin configuration


lcd pin description
figure a:- pin configuration of 16*2 LCD
REGISTER:-

HD44780 based LCD consists of two 8 bit registers. One is Instruction register which consists of instruction given to LCD while another is called Data register which temporarily stores data to be written or read fro  DDRAM (Display Data RAM) or CGRAM(character generation RAM).

BUSY FLAG:-

D7 pin of LCD can be used to read the status of busy flag. when busy flag is at logic HIGH state, it means it is busy doing its internal operation and during this period neither an instruction is send to LCD nor a data can be send to LCD. When this flag is at logic LOW state it is free from its internal operation and this is the time when we send an instruction or data which has to be displayed tin LCD. 

DDRAM:-

DDRAM which stands for display data RAM stores the data which has to be displayed in LCD. The first line of DDRAM begins with address 80h and second line begins with C0h in 16*2 LCD.

INTERFACING LCD WITH MCU:-

In this section, i will give a brief explanation on interfacing LCD which can be interfaced in 8 bit mode or in 4 bit mode. Since we are focused in interfacing in 4 bit mode , technique of interfacing in 8 bit mode will not be discussed here.

While interfacing in 4 bit mode only four upper bit data pins of LCD will be used i,e D4 to D7 pins and the lower bit data pins are disabled. Since the data send by the MCU is 8 bit in length, data needs to be send twice by breaking it into two 4 bits data while interfacing in this mode.

INSTRUCTION FOR VARIOUS FUNCTIONS OF LCD :-

The instructions which will be used in 16*2 LCD for functions like clearing display, returning home, setting pointer to lines(selecting first or second line) and so on are shown below in figure b. and figure c.


figure b:- Instruction codes



figure c:- Instruction codes continued.





Function set instruction can be used to interface length, no of display lines and the display font.
When DL=1 then the interface will be in 8 bit mode and when DL=0 it will be in 4 bit mode which is our desired interface length at the moment.
When N=1 then 2 lines will be selected else 1 line will be selected.
When F=1 the characters will be displayed in 5*10 matrix else it will be displayed in 5*8 matrix.


SOFTWARE DESCRIPTION:-

Source code is written in keil uvision software. The crystal used is of 11.0592MHZ. Major routines used are described below.

ROUTINES DESCRIPTION:-

Now, I am going to describe the initialization process for LCD in 4 bit mode, writing data in LCD and reading data from LCD.

INITIALIZING LCD:-

The initialization process is shown in the flowchart below.
figure d:-Initializing LCD in 4 bit mode


Routine for initializing LCD in 4 bit mode:-


Figure e:- Initialization Routine



WRITING TO LCD:-



Data are written in Instruction Register(IR) and Data register(DR). Data written in IR are used to send command to the LCD and data send to DR are used to display in LCD. 

While writing data in IR of LCD, RS and RW pin should be at LOW logic level and the logic state of en pin should change from HIGH to LOW logic state.The routine of writing data i,e instruction in IR is shown below in figure f. 


figure f:- routine for writing data in IR

Here, out is defined for the PORT in which the data pins of LCD are connected. delay(arg); is the function to generate millisecond delay approx.

While writing data in DR of LCD, RS and RW pin should be at HIGH and LOW logic level respectively and the logic state of en pin should change from HIGH to LOW logic state.The routine of writing data in DR is shown below in figure g. 

figure g:- routine for writing data in DR

NOTE:- Since at a time only four bit data can be send to LCD it is required to broke an 8 bit data into two 4 bit data and the broken data containing lower 4 bit should be shifted 4 position left.

READING FROM LCD:-

Reading data from DDRAM or CGRAM of LCD can be accomplished when RS and RW are both at HIGH logic state and when EN changes its logic state from LOW to HIGH. Data should be read twice since only 4 bit data can be received at once. After receiving data two four bits data should be concated to make it eight bit long. Before concating two 4 bit data, data containing lower four bit data should be shifted 4 position to its right.

figure h:- routine to read data from DDRAM and CGRAM

NOTE:- 4 bit data which we receive first while reading data is the upper nibble of desired 8 bit data and next received 4 bit data  is lower nibble of desired 8 bit data.


Source code

#include<reg52.h>
#define out P2
sbit rs=P1^0;
sbit rw=P1^1;
sbit en=P1^2;
sbit busy=P2^7;
void delay(unsigned int );
void lcdinit();
void lcdfirst();
void lcdsec();
void lcdshift();
void lcdcmd(unsigned char );
void lcddata(unsigned char);
unsigned char lcdread(unsigned char);
void usdelay(unsigned int);
void lcdstr(unsigned char *s);
void main()
{
unsigned char rec[32],i,j;
out=0;
lcdinit();
lcdcmd(0x28);   //4 bit interfacing mode, 2 lines, 5*8 dots
lcdcmd(0x01); //clear lcd
lcdcmd(0x0c); //display on, cursor off,blink off
lcdcmd(0x06); //move to right
lcdfirst(); // set pointer to lcd first line
lcdstr("bhatraisummit");
lcdsec();
lcdstr(".blogspot.com");
delay(20);
for(i=0;i<16;i++)
rec[i]=lcdread(0x80+i);
for(i=16,j=0;i<32;i++,j++)
rec[i]=lcdread(0xc0+j);
lcdcmd(0x01);
for(i=0;i<16;i++)
lcddata(rec[i]);
lcdsec();
for(i=16;i<32;i++)
lcddata(rec[i]);
while(1);
}


void delay(unsigned int mstim)
{
unsigned int i,j;
for(i=0;i<mstim;i++)
for(j=0;j<1275;j++);
}
void lcdinit()
{
rs=0;
rw=0;
out=0; //making port as an output port
delay(15); //wait for 15 ms
out&=0x0f;
out|=0x30;
en=1;
delay(1);
en=0;
delay(5); //waiting for more than 4.1 ms
out&=0x0f;
out|=0x30;
en=1;
delay(1);
en=0;
delay(1); //waiting for more than 100 us
out&=0x0f;
out|=0x30;
en=1;
delay(1);
en=0;
delay(1); //wait for more than execution time

out&=0x0f;
out|=0x20;
en=1;
delay(1);
en=0;
delay(1); //wait for more than execution time
}

 void lcdfirst()
 {
 lcdcmd(0x80);
 }
void lcdsec()
{
lcdcmd(0xc0);
}
void lcdcmd(unsigned char value)
{
rs=0;
rw=0;
out&=0x0f;  
out=(value & 0xf0); // writing upper nibble
en=1;
delay(1);
en=0;
out &=0x0f;
value<<=4;   // shift lower nibble left to upper nibble
out=(value & 0xf0);   // write lower nibble
en=1;
delay(1);
en=0;
}
void lcddata(unsigned char value)
{
rs=1;
rw=0;
out&=0x0f;
out=(value & 0xf0);
en=1;
delay(1);
en=0;
value<<=4;
out&=0x0f;
out=(value & 0xf0);
en=1;
delay(1);
en=0;

}
unsigned char lcdread(unsigned char addrs)
{
unsigned char temp=0,rec=0;
lcdcmd(addrs);
rs=1;
rw=1;
out=255;
en=0;
delay(1);
en=1;
rec=out;
rec&=0xf0;
en=0;
delay(1);
en=1;
temp=out;
temp&=0xf0;
temp>>=4;
rec|=temp;
return rec;

}

void lcdstr(unsigned char *s)
{
while(*s)
lcddata(*s++);
}


To download complete source code with proteus simulation file, click here.

No comments: