Wednesday, August 12, 2009

LCD Interfacing with Atmega16

LCD Interfacing with Atmega16

LCD display:

The display used here is 16x2 LCD (Liquid Crystal Display); this means 16 characters per line by 2 lines. A very popular standard exists which allows us to communicate with the vast majority of LCDs regardless of their manufacturer. The standard is referred to as HD44780U, which refers to the controller chip which receives data from an external source (in this case, the Atmega16) and communicates directly with the LCD. The 44780 standard requires 3 control lines as well as either 4 or 8 I/O lines for the data bus. Here we are using 8-bit mode of LCD, i.e., using 8-bit data bus.


The three control lines are referred to as EN, RS, and RW.

The EN line is called "Enable." This control line is used to tell the LCD that we are sending it data. To send data to the LCD, our program should make sure this line is low (0) and then set the other two control lines and/or put data on the data bus. When the other lines are completely ready, bring EN high (1) and wait for the minimum amount of time required by the LCD datasheet (this varies from LCD to LCD), and end by bringing it low (0) again.

The RS line is the "Register Select" line. When RS is low (0), the data is to be treated as a command or special instruction (such as clear screen, position cursor, etc.). When RS is high (1), the data being sent is text data which should be displayed on the screen. For example, to display the letter "T" on the screen you would set RS high.

The RW line is the "Read/Write" control line. When RW is low (0), the information on the data bus is being written to the LCD. When RW is high (1), the program is effectively querying (or reading) the LCD. Only one instruction ("Get LCD status") is a read command. All others are write commands--so RW will almost always be low.

In our case of an 8-bit data bus, the lines are referred to as DB0, DB1, DB2, DB3, DB4, DB5, DB6, and DB7.

Fig: 16X2 LCD display


Pin Number


Logic State







Power supply









0 - Vdd

Control of operating




D0 – D7 are interpreted as commands
D0 – D7 are interpreted as data




Write data (from controller to LCD)
Read data (from LCD to controller)



From 1 to 0

Access to LCD disabled
Normal operating
Data/commands are transferred to LCD

Data / commands




Bit 0 LSB




Bit 1




Bit 2




Bit 3




Bit 4




Bit 5




Bit 6




Bit 7 MSB

Table: Pin description of LCD

LCD Circuit:


To Pin 4,5,6 To PortA

Of PortD

Fig: LCD Connections

Testing (D.C. Conditions):

  • PIN 7 to 14 are data pins.
  • Voltage at pin 2 is +5.00V
  • Pin 3 is connected to 10K variable resistance for contrast setting.

  • Pin 4, 5, 6 are control lines connected to PORT D.

Actual circuit diagram is similar to the LCD connections in this CIRCUIT.

LCD Basic Commands:






Function Set: 8-bit, 1 Line, 5x7 Dots




Function Set: 8-bit, 2 Line, 5x7 Dots




Function Set: 4-bit, 1 Line, 5x7 Dots




Function Set: 4-bit, 2 Line, 5x7 Dots




Entry Mode




Display off Cursor off
(clearing display without clearing DDRAM content)




Display on Cursor on




Display on Cursor off




Display on Cursor blinking




Shift entire display left




Shift entire display right




Move cursor left by one character




Move cursor right by one character




Clear Display (also clear DDRAM content)




Set DDRAM address or cursor position on display




Set CGRAM address or set pointer to CGRAM location



Programming Steps Sequence:

1) Initialize the LCD.

2) Select the command or instruction register (RS=0 or RS=1).

3) Set RW low (to write to LCD).

4) Send a high to low pulse on EN pin.

5) Check if the LCD is busy (Optional Step, it eliminates the delay issue).

6) Move to instruction or command function.

7) Repeat above steps.

The Source Code:

/*Every relevant command is included with a detailed and explanatory comment, if you still encounter any problem in the code feel free to post your queries*/

/* Platform: WINAVR*/

/*This code simply prints RoboZeal on LCD*/

#define F_CPU 12000000 //Change the F_CPU value to that you're using in your hardware, I used 12Mhz

#include <avr/io.h>

#include <util/delay. h>

#define dataport PORTA

#define commport PORTD

#define rs PD4

#define wr PD5

#define en PD6

int LCD_init(void);

int LCD_SendData(void);

int wrcomm(void);

int wrdata(void);

int main(void)


DDRA = 0xFF; //Set PortA as output port

DDRD = 0x70 //Set PortD 4, 5, 6 pin as output pins

LCD_init(); //Initialise LCD

LCD_SendData( ); //Write to LCD

return 1;


int LCD_init()


dataport = 0x38; //initialize LCD 2 lines, 5x7 matrix

wrcomm(); //Right the command byte to command register

dataport = 0x01; //Clear LCD

wrcomm(); //Right the command byte to command register

dataport = 0x0E; //Display on Cursor Blinking

wrcomm(); //Right the command byte to command register

dataport = 0x80; //Cursor at line 1, position 1

wrcomm(); //Right the command byte to command register

dataport = 0x1C; //Shift Entire Display To Right

wrcomm(); //Right the command byte to command register

return 1;


/*********** **** <<Sending Data To LCD Display>> ************ ***/

int LCD_SendData(void)


unsigned char j[] = "RoboZeal";

int i;

for(i = 0; i < sizeof j; i++)


dataport = j[i];



return 1;


/******* <<Righting the command byte to command register>> ********/

int wrcomm(void)


commport &= ~(1 << rs); //Setting RS = 0, selecting command register

commport &= ~(1 << wr); //Setting RW = 0

commport |= (1 << en); //EN = 1

commport &= ~(1 << en); //EN = 0, thus giving high to low pulse on Enable pin

_delay_ms(10); //10ms delay

return 1;


/********** <<Righting the Data byte to Data register>> **********/

int wrdata(void)


commport |= (1 << rs); //Setting RS = 1, selecting data register

commport &= ~(1 << wr); //Setting RW = 0

commport |= (1 << en); //EN = 1

commport &= ~(1 << en); //EN = 0, thus giving high to low pulse on Enable pin

_delay_ms(10) ; //10ms delay

return 1;



  1. Only one command that is “Get LCD status” is a read command all others are write command.

  1. The LCD interprets and executes our command at the instant the EN line is brought low. If you never bring EN low, your instruction will never be executed. Additionally, when you bring EN low and the LCD executes your instruction, it requires a certain amount of time to execute the command. The time it requires to execute an instruction depends on the instruction and the speed of the crystal which is attached to the 44780's oscillator input. (So watch the delay function in the code).

For Compiling & Burning the Program refer to: WinAVR for Parallel Port Programmer

For Building simple Parallel Port Programmer refer to: Programmer For Atmega 16/32


Aditya Sharma

Robotics INDIA


vijaykarthickonline said...

dear sir,
i have to make a robot named "time machine". the basic track consists of two concentric circles and diameters each spaced equally.(so that the entire set-up forms a clock like appearance.). the robot can go round either in the inner or the outer circle and sense both the hands(hour hand-107cm and minute hand-77cm, which are placed manually at various time settings) and display the time in a lcd screen. i have an atmega16 chip readily assembled. i have provisions to use two empty ports(as i have already used two for motors and sensors). i need to interface lcd to the remaining ports. your program will just print one word in the screen. can you please help me with a program to sense the hands and display the time.
and then select "robotics" from the side menu and then "time machine".

vijaykarthickonline said...


Design a robot to automatically detect the time and display it using a seven segment display or LCD.

The arena consists of 2 black coloured circles, of radii 90cm and 120 cm respectively and having a width of 3 cm each.
The circles are painted against a white background.
12 equally spaced lines are drawn inside the circles representing the 12 numerals in the clock. Each line has a thickness of 3 cm.
Minute hand is represented by a block of dimensions 107 cm X 8 cm X 8 cm.
The hour hand is represented by another block of dimensions 77 cm X 8 cm X 8 cm.
The blocks are white in colour.

Bot Specifications
Maximum allowed size of the base : 20 cm X 20 cm X 20 cm
Voltage restriction: 12 V (External power supply can also be used)

The Game
The bot will be placed on the 12 o' clock line along the outer circle, at the start of the run.
The two blocks representing the minute hand and hour hand respectively will be aligned by the event co-ordinators to show a particular time.
For the sake of avoiding complications, the hour hand will be made to point exactly along the appropriate line, and will not be in between 2 lines. ie. for 5:15 and 5:45, the hour hand will be pointing along the 5 o' clock line in both cases.
The bot can traverse along either the outer circle or inner circle, or along any of the line indicating the numbers on the clock.
Once the bot has computed the time, it has to align itself along the 12 o' clock line (can be on the inner circle or the outer circle) and display the time.

Aditya Sharma said...

Hi Vijay,

You need to design an appropriate algorithm First, displaying on LCD is not a big thing once you get your LCD correctly interfaced.

You can try with the following algo,

I am assuming that you are using digital sensors;

Firstly we will examine minute hand as robot is placed on outer circle, by moving robot from 12 0'clock line in clockwise direction.

1. Take a variable "Minute_value=0" and increment it by 5 every time (i.e Minute_Value = Minute_Value+5) you encounter a black line on floor, that is you will monitor the no. of times your sensors will give some logic change.

2. Now the moment you encounter the minute hand, increment "Min_value" one more time and store it in some other variable say "Min_Final_Value".

3. Now turn the robot towards inner circle, its logic will be similar to basic line follower.

4. Now again move the robot in clockwise direction with a variable declared as "Hour_Value = Minute_Value/5", increment the Hour_Value variable as "Hour_Value = Hour_value + 1" every time robot detects a black line.

5. Finally when you get the Hour_hand, store the value in some variable say "Hour_Final_value".

6. Now move the robot in opposite direction i.e. anticlockwise by continuously decrementing the value of Hour_hand by 1 each time a black line is encountered, you can also keep on moving the robot in same direction i.e clockwise until Hour_value=12 (if arena conditions permit it).

7. For displaying the time on LCD use the given code with these commands in the main loop.

dataport = Hour_Final_value;
dataport = "0x20" //For a space
dataport = Minute_Final_value;

Get back to me after designing the code if you face any problems.


vijaykarthickonline said...

dear aditya sharma,
thank you for the valuable algorithm. i've started to write the algorithm. i'll surely contact you if i have any doubts. thank you a million times... :)

vijaykarthickonline said...

in your example program, you have written

int main(void)
DDRA = 0xFF; //Set PortA as output port
DDRD = 0x07; //Set PortD 4, 5, 6 pin as output pins

but to set 4,5,6 pins as output, shouldn't we put "DDRD=0x0E" instead of "DDRD=0x07" ?

Aditya Sharma said...

Hi Vijay,

Thanks for pointing out the mistake, it will be "0x70" instead of "0x07", i have corrected it now.

It will not be 0xE0. Lets see how-


we are setting 4,5 and 7th bit, so in HEX we write "0x70".

whereas for 0x0E it will be..

means for 0x0E you are setting 1,2 and 3 bit.

Hope you got it.

vijaykarthickonline said...

yes, i got that right. i thought it was in the order D0, D1, D2....
but you made it clear that the order for initializing is D7, D6, D5....

vijaykarthickonline said...

hi adithya,
i have successfully accomplished the task of displaying the word on the lcd screen. thanks a lot.
but as per my requirement, i need to display numbers on the lcd.
i tried the following code,

int LCD_SendData(void)

int k=5;
dataport=k; //or even dataport=5;
return 1;

but unfortunately this gave me some unknown symbol instead of the number 5.

i just want to know if there is any hexadecimal code for printing number. please tell me the entire code.

Aditya Sharma said...

Hi Vijay,

Good work..

probably dataport = '5' (single qotes to specify 5 as character) will do the trick.

But in your application what you need to do is convert the value into decimal form, this is done by adding 48 to every digit of the number individually.

Means first you have to separate digit at unit place, tens place and hundredths place and the add 48 to them individually and then recombine them and then display.
Look at the ASCII table on this link.

Think over the method if you can achieve it or not... Some work for your Sunday...!!

vijaykarthickonline said...

thanks again. i will surely finish this off by tomorrow. i will surely get in touch with you if i have further doubts.


vijaykarthickonline said...

i don't understand what this means:
"But in your application what you need to do is convert the value into decimal form, this is done by adding 48 to every digit of the number individually.

Means first you have to separate digit at unit place, tens place and hundredths place and the add 48 to them individually and then recombine them and then display."

why should i add 48 and why should i add the units digit, tens digit and hunderds digit???
i'm puzzled... please help as soon as possible... i'm stuck with the code...

i just displayed the word on the lcd screen.
i'm planning to use switch case to check if:

dataport='1'; //as you instructed me to use single quotes..//

and another switch case for minute.

do you think this program is efficient or not...

i will post the entire program after success surely for your survey...!!!

venkat said...

Hi aditya,

am a friend of vijay karthick , me and him only were studying your responses thanks alot for it.

I very understood wat you said lastly and we are so thankful to you.
i informed this to vijay also. adding 48 gives the ascii value of the decimal no so we have to use it right...

thanks alot

vijay karthick said...

hi aditya,
yup. finally i understood what you said. we are working on the code...
its almost over...

Aditya Sharma said...

Hope you finish it as soon as possible, still here is something for your reference-

Its for a 3digit number display, for two digit or 4 digit you have to do slight modifications and it will be easy if you understand it.

temp = Computed Value;
unit = (temp%10) + 48;
temp = temp/10;
tens = (temp%10) + 48;
hundred = (Computed Value/100) + 48;
write to LCD(hundred)
write to LCD(tens);
write to LCD(unit);


venkat said...

hi aditya ,
this is venkat using atmega16 micro controller for my robot.unknowingly I enabled the jtag while writing the fuses in tat microcontroller.can me help me to disable it. i really don know how to disable it.

plz reply me with the answer as soon as you see the message.

waiting for your reply.......

Aditya Sharma said...

Hi Venkat,

Plz specify what do you mean by tat microcontroller.

Anonymous said...

In function set, what does 8 bit, 2lines 5 x 7 dots mean? Does it mean for 16 x 2 lcd we are using only 5 x 7 portion?
Please help..- DJ, Jaipur

Aditya Sharma said...

8-bits... It means each character is represented by eight bit binary number (e.g. 10101101).

2 lines... Means two rows of the LCD,i.e, LCD we are using have two rows.

5x7... It represents each block of the row is constituted of 5 coloums and 7 rows (like pixels).

See this link...

dinesh said...

we have performed all the connections as shown only with the difference that our output port is port C (0-7).our pin connection s for port A are PA5-RS, PA4-RW, PA3-EN.THE CODE HAS BEEN COMPILED WITH NECESSARY CORRECTIONS.we have changed the frequency to 10 mhz.we have a output such that only the second line of LCD shows black boxes and the first line is blank.please suggest any corrections in the hardware or in software.thankyou.

dinesh said...

according to the first dig.where you have written lcd is shown by black boxes this was a mistake in the previous comment

Anonymous said...

i want interface a colour lcd (nokia 6100)with atmega 32 will u plz help me out how to done it.i have alredy interfaced nokia 3310 lcd and JHD12864E graphical lcd with atmega 32.if u could help me out i will bwe grateful to u.
my id is

High Regards

Anonymous said...

आदित्य शर्मा जी , मई तहे दिल से आपको धन्यावाद प्रेषित करता हूँ ... एक आप ही का कोड है जो पूरा इन्टरनेट छानने के बाद मुझे मिला, पहली बार में चला (as per my H /W configuration ) और सबसे बड़ी बात की लाइन बी लाइन समझ में भी आया . मेरी परेशानी दूर करने के लिय आपका धन्यवाद , भनवान आपको खूब सफलता दे!

Pratik Shukla

Anonymous said...

आदित्य शर्मा जी , मै तहे दिल से आपको धन्यवाद प्रेषित करता हूँ ... एक आप ही का कोड है जो पूरा इन्टरनेट छानने के बाद मुझे मिला, पहली बार में चला (as per my H /W configuration ) और सबसे बड़ी बात की लाइन बाय लाइन समझ में भी आया . मेरी परेशानी दूर करने के लिय आपका धन्यवाद , भनवान आपको खूब सफलता दे!
Pratik Shukla

Anonymous said...

Sir, Thank you... because of this site...i can now finish my project...about LCD Display..


pls can u help in doing this project..i have to interface a rotary encoder with the dc motor shaft and to microcontoller so that the display of wat speed it is rotating have to come on lcd....pls..can u help

Aditya Sharma said...

Hi Rajesh,

Post all your queries related to this project, i will provide the inputs at by best of knowledge.



Hello sir....i am kiran....
i am doing my project on DIGITAL IC TESTER.I am interfacing LCD to my project.I am using ATMEGA16 MCU.I have seen the article LCD INTERFACING WITH ATMEGA16.But what i need is i have only one port available.I have to use that only port to interface LCD to my project.I tried many libraries,but i couldn't.So please tell me how to do this by using only one port(PORTD).
Hope i will get the reply soon...
Thanks in advance.....

Aditya Sharma said...

You can interface the LCD in 4-bit mode. Search for this, you will be done with a single PORT with that.


I tried many libraries with 4 data bits but all these uses different ports.I also tried to change the lcd.h file to use single port.But the result is nothing.
Finally i did it with Peter Fleury's library....
Thanks for your reply.....

mehul said...

I am making a project of controlling the intensity of 3w power leds using the pwm channel of atmega16. I need to connect 13 blue leds with 1 pwm channel and 12 white leds with 1 pwm channel. please suggest me the way to for such type of connection. please mail me the reply at

Anonymous said...

i think the ckt diagram is little bit wrong. the 16th and 15th pin must be interchanged i.e 15th pin should go to vcc through a 330ohm resistor and 16th pin to be grounded.

laxmi gayathri said...

when we are running your atmega16 led interface code we are getting just black blocks in the display..please help us.

laxmi gayathri said...

its lcd not led sry

bunny said...

hi sir,
how to give a voltage sensor output to a atmega16 uc and display its value in lcd.

thanks in advance

chinu0904 said...

how to make the project on led blinking with the help of atmega16

Anonymous said...

I am facing some trouble to display some data on lcd.....
here in this code there is no time delay after the setting the en signal 1.....
is it mendatory??
please p

Wawhal Soniya said...

Here i am facing problem i interfacing LCD with ATmega do i interface??????

Dheeraj Bisht said...

sir i m interfacing atmega16 and lcd. i m using the code that u have written in your website but i m not getting any answer

jaguar 009 said...

sir i am trying to display a computed value on lcd display using atmega16
but i m facing a problem to display numerical value to character string input for your program strig
help please me to solve the problem or sm alternate solution!

rex danim said...

This is a treasure, thanks for this visual guide, I have a problem like this that occurred in my LCD monitor.
lcd screens some more new screens how is my idea....???

Online Electronic Component Store said...

Very well explained Interfacing 16x2 LCD with Atmega16