4 Bit LCD interfacing with Atmel AVR Microcontrollers

Most of the time in your project you have to interface some displaying unit. A 16×2 LCD is best solution for this purpose. There are three ways to interface a 16×2 LCD with a microcontroller.

  • 8 Bit Interfacing
  • 4 bit interfacing
  • I2C interfacing

8 Bit Interfacing

8 Bit interfacing is the most common method to interface your LCD with microcontrollers. But there is a big disadvantage of using this technique. You have to utilize at least 10 pins of microcontroller in which 2 pins for commands and 8 pins for data.

I2C Interfacing

I2C interfacing is the latest method to interface a 16×2 LCD. It needs only two wires to handle all communication. There are two ways to implement this method. Either you buy I2C 16×2 LCD direct or either buy a typical 16×2 LCD with I2C Converter. Both ways will lead you to little bit higher price as compared to other interfacing method.

4 Bit Interfacing

4 bit interfacing is best method to interface your typical 16×2 LCD with microcontrollers because it needs only 6 pins of microcontroller to work properly. Moreover this method does not need anything extra things. You just have to add some extra coding and that’s all. In this article I will focus on 4 bit LCD interfacing.

Pin Configuration and Connections

I am not going into useless details of LCD interfacing. Let’s just focus on the practical part of it. In the figure below you can watch the connections you have to do when using the LCD.  I used Atmega8 in this example which is from the family of Atmel AVR Microcontrollers. Here, most important part is the variable resistor present in the diagram. This resistor has no use in simulation software but in real system you have to adjust the value of this resistor properly.  Remember if your LCD code is perfectly working in simulation software then there is no reason that your LCD does not work in real system. There may be some loose connection, damaged LCD, or variable resistor problem.


Figure 1: Connections

In connection diagram, you can see that I grounded the R/W pin. It is basically read/write pin and normally we give zero level (0) to this pin. The remaining pins (D0-D7) are data pins. As you are learning 4 bit interfacing so you don’t have to worry about (D0-D3) pins.

Initializing LCD in 4 Bit Mode:

 There are commands through which LCD is initialized. I used an initialization function for this purpose. In normal case, you can use this function as it is. But if you want to alter your LCD according to your requirement then you have to study the table shown below and change your initialization code accordingly.

Figure 2: Control Commands

Now carefully understand the function below and match with the above table.

void lcd_iniit(void){
writecmd(0x02);// Return Home
writecmd(0x28);//4 bit initialization-2line display-
writecmd(0x0C);//Display on-Cursor off-Blink off
writecmd(0x01);//Clear All Display Data
writecmd(0x06);//after every character cursor will move to right

Difference Between Command and Data

Commands are that information which controls your LCD whereas Data is that information which displays on the LCD screen. But we have only data pins here. In fact “RS Pin” of LCD is used here to switch the command / data state. To send commands you have to set “LOW” the RS Pin as shown in function below.  To send data you have to set it to “HIGH”. The only difference between command and data function is this PIN position. Study this function carefully.

int writecmd(char z){     

ctrl &= ~(1<<RS);// To write Commands
char z1 = z << 4;// To shift 4 bits
z &= 0b11110000; //masking lower 4 bits
ctrl = (ctrl & 0x0F)|z; // sending data to LCD
ctrl |= (1<<E);//send falling edge to send data to LCD
ctrl &= ~(1<<3);
z1 &= 0b11110000;//Again masking lower 4 bits
ctrl = (ctrl & 0x0F)|z1;//Sending Remaining Data to LCD
ctrl |= (1<<E);//send falling edge to send data to LCD
ctrl &= ~(1<<E);
return 0;

Here, ctrl is the PORTB which I am using in this example. You have to send falling edge on Pin “E” of LCD to send data every time. Don’t worry you can get whole example code at the end of this article

Function to Control the Cursor Position

void LCD_XY(unsigned char x, unsigned char y){
unsigned char firstcharadrs[] = {0x80, 0xC0,0x94,0xD4};
writecmd(firstcharadrs[y-1] + x – 1);

This is the very beautiful function to control the cursor of the 16×2 LCD. As you know here 16 is the Columns and 2 is the Rows of LCD. So, if you want to go to the 2nd row and 10th column then you just have to right LCD_XY(10,2) in your coding.

Sending Strings to 16×2 LCD

You can’t send characters one by one to the LCD because it makes your code bulky. There must be some technique through which you can send whole strings at a time. The function below will help you in this matter.

void putstring(char const *str){
unsigned char z=0;
//Sending character by character to LCD
while (str[z]!=0){

This function will send strings to the LCD easily. Now download the example code and check the example code by yourself. Once you are able to run my code. Alter the code and check the effects. This code is written for the Atmega8 microcontroller and also can use for other Atmel AVR microcontrollers. I wrote this code on Atmel Studio.

I hope you understand now how to interface your 16×2 LCD with Atmel AVR Microcontrollers in 4 bit mode. In case of any queries feel free to comment below and don’t forget to like our facebook page.

To Download Complete Code click the button below:

 Complete Code


Electrical engineering is my profession, my hobby and my passion. I completed bachelors of electrical engineering in 2015. Currently I am working with a utility company which provides electricity to its consumers. Power Electronics, Embedded Systems and Energy Metering are my fields of specialization. In free time I listen music and watch movies.

What do you think?