In this tutorial we shall explore how to connect 16 X 2 LCD with ATMEGA 16 on Development board.

By 2 ways we can connect , first one is 8 bit mode & the second is 4 bit mode

 

DEMO_BOARD

This post is on 8 BIT MODE

In 8 bit mode all port pins of a Port , say PORT B is assigned for DATA communication.

For CONTROL we need 3 more pins RS , RW & EN

RS is REGISTER SELECT RS=0 Command Register of LCD selected , RS=1 DATA Register is selected

RW is READ/WRITE pin when RW=1 LCD is in Read mode , when RW=0 LCD is in WRITE mode

Generally LCD is used to display data.So mostly RW is connected to GND ( RW=0)

PB0 to PB7 – D0 to D7 of LCD

PD4 (PIN 18) — > RS

PD5 (PIN 19)– > RW

PD6 (PIN 20) — > EN

The backlight connection & Contrast pot are taken care in the development board.

 

LCD_DATA_CTRL_PIN_CON

 

We use PROGRAMMERS NOTEPAD of WINAVR to develop the C code & Hex file .

WINAVR is a lightweight excellent tool for AVR Programming compared to the AVR STUDIO ( which is a huge download)

You can download WINAVR

https://sourceforge.net/projects/winavr/files/latest/download?source=files

Its only 29MB download & easy to install.

Once WINAVR is installed , you can see the Programmers Notepad & MFILE inside the WINAVR Folder.

winavr

Open Programmers Notepad to type in the C code.

To start with the code , include the 2 Header files on the top . avr/io.h defines all Port Registers & port pins of AVR IC & the util/delay.h is responsible for the Delay we use in the code.

 

#include <avr/io.h>

#include <util/delay.h>

 

Next we define the LCD Function definitions like

 

void LCD_send_command(unsigned char cmnd);

void LCD_send_data(unsigned char data);

void LCD_init(void);

 

Above all are user defined Functions & we’ve to write code for these functions.

For better code readability & reuse of coded we use # define statements

 

#define DATA_PORT PORTB

#define DATA_DDR DDRB

#define CNTRL_PORT PORTD

#define CNTRL_DDR DDRD

#define RS_PIN 4

#define RW_PIN 5

#define ENABLE_PIN 6

 

PORTB is defined as DATA_PORT & PORTD is defined as CNTRL_PORT , DDRB as DATA_DDR, DDRD as CNTRL_DDR

In the code , wherever DATA_PORT is mentioned it is replaced with PORTD & wherever CNTRL_PORT is mentioned is replaced with PORTD.

Also pins PD4 is defined as RS_PIN , PD5 as RW_PIN , PD6 as ENABLE_PIN .Its enough to mention only the pin number. Instead of PD5 you can mention only 5.

Later if you decide to change the port pins assigned to LCD , you need to change it in the #define statements and the rest of the code is left as it is.

First let us see the LCD_init() function which initializes the LCD

 

void LCD_init()

{

_delay_ms(10);

LCD_send_command(0x38);

LCD_send_command(0x0E);

LCD_send_command(0x01);

_delay_ms(10);

LCD_send_command(0x06);

}

 

To initialize the LCD we send the HEX values as command.The HEX command codes are

clip_image002

We send HEX value 0x38 to define 16 x 2 LCD 2lines & character size is 5 x 7

0x0E forDisplay ON & cursor blinking

0x06 to increment cursor

& 0x01 to Clear Screen

We send Command using Function LCD_sendcommand

Which accepts parameter as unsigned char

—————————————————–

void LCD_send_command(unsigned char cmnd)

{

DATA_PORT = cmnd;

CNTRL_PORT &= ~(1<< RW_PIN);

CNTRL_PORT &= ~(1<< RS_PIN);

 

CNTRL_PORT |= (1<< ENABLE_PIN);

_delay_us(2);

CNTRL_PORT &= ~(1<< ENABLE_PIN);

_delay_us(100);

}

————————————————–

Command received as unsigned char is assigned to DATA_PORT

RW pin is made LOW to enable Write operation

RS pin is made LOW to select COMMAND REGISTER

ENABLE pin is made HIGH & after a small delay made LOW ( pulse)

In the same way DATA is sent to LCD for Display using the following function :

——————————————–

void LCD_send_data(unsigned char data)

{

DATA_PORT = data;

CNTRL_PORT &= ~(1<< RW_PIN);

CNTRL_PORT |= (1<< RS_PIN);

 

CNTRL_PORT |= (1<< ENABLE_PIN);

_delay_us(2);

CNTRL_PORT &= ~(1<< ENABLE_PIN);

_delay_us(100);

}

—————————————

 

Data received as unsigned char is assigned to DATA_PORT

RW pin is made LOW to enable Write operation

RS pin is made HIGH to select DATA REGISTER

ENABLE pin is made HIGH & after a small delay made LOW ( pulse)

The next function takes 2 variables y & x & moves the cursor to that location on LCD

——————————————-

void LCD_goto(unsigned char y, unsigned char x)

{

unsigned char firstAddress[] = {0x80,0xC0,0x94,0xD4};

LCD_send_command(firstAddress[y-1] + x-1);

_delay_ms(10);

}

————————————————-

 

 

Following is the Function to print String characters on LCD

We put a string in memory location & use it as a Pointer

While String is greater than 0 , all the characters represented or pointed by the string variable is sent to LCD for printing

 

void LCD_print(char *string)

{

while(*string > 0)

{

LCD_send_data(*string++);

}

}

 

In the LCD_blink() function we send command , a hex value 0x08 to make the display OFF & after a delay we send a command Hex 0x 0C to ON the display, thus generating a blink effect

 

void LCD_blink()

{

LCD_send_command(0x08);

_delay_ms(250);

LCD_send_command(0x0C);

_delay_ms(250);

}

 

To clear the display we send command Hex 0x01 as seen in the LCD_clear function below

 

void LCD_clear(void)

{

LCD_send_command(0x01);

_delay_ms(100);

}

 

Finally in the main Function we declare PORTD as Output , as well as PORTC as OUTPUT.

This is done by assigning 0x FF to CNTRL_DDR ( PORTD) & DATA_DDR (PORTB)

Then we clear the LCD , Initialize it & go to first position & print the String

 

int main(void)

{

CNTRL_DDR = 0xFF;

CNTRL_PORT = 0x00;

DATA_DDR = 0xFF;

DATA_PORT = 0x00;

 

LCD_clear();

LCD_init();

LCD_goto(1,2);

LCD_print(“ALSELECTRO.COM”);

LCD_goto(2,3);

LCD_print(“16×2 LCD DEMO”);

 

 

Complete code for 8bit LCD MODE is as below :

—————————————————

 

#include <avr/io.h>

#include <util/delay.h>

#define F_CPU 8000000UL // FCPU Definition for util/delay used in AVR STUDIO only

 

/*LCD function declarations */

void LCD_send_command(unsigned char cmnd);

void LCD_send_data(unsigned char data);

void LCD_init(void);

void LCD_goto(unsigned char y, unsigned char x);

void LCD_print(char *string);

void LCD_blink(void);

void LCD_clear(void);

 

#define DATA_PORT PORTB

#define DATA_DDR DDRB

#define CNTRL_PORT PORTD

#define CNTRL_DDR DDRD

#define RS_PIN 4

#define RW_PIN 5

#define ENABLE_PIN 6

 

int main(void)

{

CNTRL_DDR = 0xFF;

CNTRL_PORT = 0x00;

DATA_DDR = 0xFF;

DATA_PORT = 0x00;

 

LCD_clear();

LCD_init();

LCD_goto(1,2);

LCD_print(“ALSELECTRO.COM”);

LCD_goto(2,3);

LCD_print(“16×2 LCD DEMO”);

 

while(1)

{

}

}

 

/* This function sends a command ‘cmnd’ to the LCD module*/

void LCD_send_command(unsigned char cmnd)

{

DATA_PORT = cmnd;

CNTRL_PORT &= ~(1<< RW_PIN);

CNTRL_PORT &= ~(1<< RS_PIN);

 

CNTRL_PORT |= (1<< ENABLE_PIN);

_delay_us(2);

CNTRL_PORT &= ~(1<< ENABLE_PIN);

_delay_us(100);

}

 

/* This function sends the data ‘data’ to the LCD module*/

void LCD_send_data(unsigned char data)

{

DATA_PORT = data;

CNTRL_PORT &= ~(1<< RW_PIN);

CNTRL_PORT |= (1<< RS_PIN);

 

CNTRL_PORT |= (1<< ENABLE_PIN);

_delay_us(2);

CNTRL_PORT &= ~(1<< ENABLE_PIN);

_delay_us(100);

}

 

void LCD_init()

{

_delay_ms(10);

LCD_send_command(0x38);

LCD_send_command(0x0E);

LCD_send_command(0x01);

_delay_ms(10);

LCD_send_command(0x06);

}

 

/* This function moves the cursor the line y column x on the LCD module*/

 

void LCD_goto(unsigned char y, unsigned char x)

{

unsigned char firstAddress[] = {0x80,0xC0,0x94,0xD4};

LCD_send_command(firstAddress[y-1] + x-1);

_delay_ms(10);

}

void LCD_print(char *string)

//put a string in memory location & use it as POINTER

{

while(*string > 0)

{

LCD_send_data(*string++);

}

}

 

void LCD_blink()

{

LCD_send_command(0x08);

_delay_ms(250);

LCD_send_command(0x0C);

_delay_ms(250);

}

 

void LCD_clear(void)

{

LCD_send_command(0x01);

_delay_ms(100);

}

—————————————–

Download code from here

Save the file inside a folder with .C extension.

Now open the MFILE of WINAVR & set the MCU as ATMEGA16 , Port as usb , Programmer as usbasp.

To make programmer as usbasp , you need to enable editing & type in usbasp against Programmer.

If the C code is saved as main.c , then you need not change the Target in Makefile.

Save the Makefile inside the same folder where .c file exists.

Click on Tools à MakeALL to generate HEX file & then click on Program to upload the HEX file on to the ATMEGA16 chip.

To create a Header file , watch the following video :

 

cooltext753793315  cooltext753790696