LCD16x2 Interfacing with AVR ATmega16/ATmega32

LCD16x2 Interfacing with AVR ATmega16/ATmega32

Introduction

LCDs (Liquid Crystal Displays) are used for displaying status or parameters in embedded systems.
LCD 16x2 is a 16 pin devices which has 8 data pins (D0-D7) and 3 control pins (RS, RW, EN). The remaining 5 pins are for supply and backlight for the LCD.
The control pins help us configure the LCD in command mode or data mode. They also help configure read mode or write mode and also when to read or write.
LCD 16x2 can be used in 4-bit mode or 8-bit mode depending on requirement of application. In order to use it we need to send certain commands to the LCD in command mode and once the LCD is configured according to our need, we can send the required data in data mode.
For more information about LCD 16x2 and how to use it, refer the topic LCD 16x2 display module in the sensors and modules section.

                    
LCD16x2 Pins
LCD16x2 Display

Interfacing Diagram


lcd16x2 Interfacing diagram
Interfacing LCD 16x2 With AVR ATmega16/ATmega32

Hardware Connections

LCD 162 Pins
ATmega16 Pins
Data pins D0-D7
PORTB
RS
PORTC.0
RW
PORTC.1
E
PORTC.2

Programming for LCD16x2 with AVR ATmega16/ATmega32

Initialize LCD16x2: It is very easy to initialize a LCD16x2
  1. Power ON the LCD
  2. Wait for 15 ms (‘Power ON’ initialization time for LCD16x2)
  3. Send 0x38 command to initialize 2 line, 5x8 matrix, 8-bit mode LCD16x2
  4. Send any ‘Display ON’ command (0x0E, 0x0C) to LCD16x2
  5. Send 0x06 command (increment cursor) to LCD16x2
void LCD_Init (void) /* LCD Initialize function */
{
 LCD_Command_Dir = 0xFF; /* Make LCD command port direction as o/p */
 LCD_Data_Dir = 0xFF; /* Make LCD data port direction as o/p */

 _delay_ms(20);  /* LCD Power ON delay always >15ms */
 LCD_Command (0x38); /* Initialization of 16X2 LCD in 8bit mode */
 LCD_Command (0x0C); /* Display ON Cursor OFF */
 LCD_Command (0x06); /* Auto Increment cursor */
 LCD_Command (0x01); /* clear display */
 LCD_Command (0x80); /* cursor at home position */
}
Now that we have initialized LCD, it is ready to accept data for displaying.

Command Write function
  1. Send the command value to the LCD16x2 data port.
  2. Make RS pin low, RS = 0 (command reg.)
  3. Make RW pin low, RW = 0 (write operation)
  4. Give high to low pulse at the Enable (E) pin of minimum delay 450 ns.
When we give an enable pulse, the LCD latches the data present at D0 to D7, and execute as command since RS is command reg.
void LCD_Command(unsigned char cmnd)
{
 LCD_Data_Port= cmnd;
 LCD_Command_Port &= ~(1<<RS); /* RS=0 command reg. */
 LCD_Command_Port &= ~(1<<RW); /* RW=0 Write operation */
 LCD_Command_Port |= (1<<EN); /* Enable pulse */
 _delay_us(1);
 LCD_Command_Port &= ~(1<<EN);
 _delay_ms(3);
}

Data write function
  1. Send command to the data port.  
  2. Make the RS pin High, RS = 1 (Data reg.)
  3. Make the RW pin Low, RW = 0 (Write operation)
  4. Give high to low pulse at the Enable (E) pin
When we give an enable pulse the LCD latches the data present (on the pins D0 to D7) and displays it on a 5x8 matrix, as RS is a data register.
void LCD_Char (unsigned char char_data) /* LCD data write function */
{
 LCD_Data_Port = char_data;
 LCD_Command_Port |= (1<<RS); /* RS=1 Data reg. */
 LCD_Command_Port &= ~(1<<RW); /* RW=0 write operation */
 LCD_Command_Port |= (1<<EN); /* Enable Pulse */
 _delay_us(1);
 LCD_Command_Port &= ~(1<<EN);
 _delay_ms(1);
}

Display String function
         This function takes a string (an array of characters) and sends one character at a time to the LCD data function till the end of the string. A ‘for loop’ is used for sending a character in each iteration. A NULL character indicates end of the string.
void LCD_String (char *str)  
{
 int i;
 for(i=0;str[i]!=0;i++)  /* send each char of string till the NULL */
 {
  LCD_Char (str[i]);  /* call LCD data write */
 }
}

Note:
  1. LCD Power-on delay: After the LCD16x2 powers ON, we cannot send commands immediately to it since it needs self-initialization time of 15-ms. Therefore, while programming, we need to take care of providing sufficient power ON delay (> 15 ms), and then send command to the LCD.
  2. After proving commands, LCD16x2 takes time (in microseconds) to execute it. But for 0x01 command (i.e. clear display), it takes 1.64-ms to execute. Therefore, after sending 0x01 command sufficient delay (> 1.63milliseconds) needs to be provided.

LCD16x2 Program


/*  
   LCD16x2 8 bit AVR ATmega16 interface
   http://www.electronicwings.com
*/



#define F_CPU 8000000UL   /* Define CPU Frequency e.g. here 8MHz */
#include <avr/io.h>   /* Include AVR std. library file */
#include <util/delay.h>   /* Include inbuilt defined Delay header file */

#define LCD_Data_Dir DDRB  /* Define LCD data port direction */
#define LCD_Command_Dir DDRC  /* Define LCD command port direction register */
#define LCD_Data_Port PORTB  /* Define LCD data port */
#define LCD_Command_Port PORTC  /* Define LCD data port */
#define RS PC0    /* Define Register Select (data/command reg.)pin */
#define RW PC1    /* Define Read/Write signal pin */
#define EN PC2    /* Define Enable signal pin */
 

void LCD_Command(unsigned char cmnd)
{
 LCD_Data_Port= cmnd;
 LCD_Command_Port &= ~(1<<RS); /* RS=0 command reg. */
 LCD_Command_Port &= ~(1<<RW); /* RW=0 Write operation */
 LCD_Command_Port |= (1<<EN); /* Enable pulse */
 _delay_us(1);
 LCD_Command_Port &= ~(1<<EN);
 _delay_ms(3);
}

void LCD_Char (unsigned char char_data) /* LCD data write function */
{
 LCD_Data_Port= char_data;
 LCD_Command_Port |= (1<<RS); /* RS=1 Data reg. */
 LCD_Command_Port &= ~(1<<RW); /* RW=0 write operation */
 LCD_Command_Port |= (1<<EN); /* Enable Pulse */
 _delay_us(1);
 LCD_Command_Port &= ~(1<<EN);
 _delay_ms(1);
}

void LCD_Init (void)   /* LCD Initialize function */
{
 LCD_Command_Dir = 0xFF;  /* Make LCD command port direction as o/p */
 LCD_Data_Dir = 0xFF;  /* Make LCD data port direction as o/p */
 _delay_ms(20);   /* LCD Power ON delay always >15ms */
 
 LCD_Command (0x38);  /* Initialization of 16X2 LCD in 8bit mode */
 LCD_Command (0x0C);  /* Display ON Cursor OFF */
 LCD_Command (0x06);  /* Auto Increment cursor */
 LCD_Command (0x01);  /* Clear display */
 LCD_Command (0x80);  /* Cursor at home position */
}

void LCD_String (char *str)  /* Send string to LCD function */
{
 int i;
 for(i=0;str[i]!=0;i++)  /* Send each char of string till the NULL */
 {
  LCD_Char (str[i]);
 }
}

void LCD_String_xy (char row, char pos, char *str)/* Send string to LCD with xy position */
{
 if (row == 0 && pos<16)
 LCD_Command((pos & 0x0F)|0x80); /* Command of first row and required position<16 */
 else if (row == 1 && pos<16)
 LCD_Command((pos & 0x0F)|0xC0); /* Command of first row and required position<16 */
 LCD_String(str);  /* Call LCD string function */
}

void LCD_Clear()
{
 LCD_Command (0x01);  /* clear display */
 LCD_Command (0x80);  /* cursor at home position */
}
 
int main()
{

 LCD_Init();   /* Initialize LCD */

 LCD_String("ElectronicWINGS"); /* write string on 1st line of LCD*/
 LCD_Command(0xC0);  /* Go to 2nd line*/
 LCD_String("Hello World"); /* Write string on 2nd line*/

 return 0;
}
 

Rolling Display

To roll the string or character on the LCD, we need to use following commands
Command
Command meaning
0x1c
Shift entire display right
0x18
Shift entire display left

For rolling the display, simply we have to put these command in loops.
Rolling Display:
  • Display string on the LCD
  • Roll it to the right using the ‘0x1C’ command
  • Roll it to the left using the ‘0x18’ command

Main Function Code for rolling display

int main()
{

int shift,i;

 LCD_Init();  /* Initialize LCD*/
 LCD_String("ElectronicWINGS");/* Write string on 1st line of LCD*/

  shift = 15; /* Number of time shifts count=15 */
  while(1)
  {
   for(i=0;i<shift;i++)
   {
    LCD_Command(0x1c);/* shift entire display right */
    _delay_ms(300);
   }   
   shift=30;/* number of time shifts 30 */
   
   for(i=0;i<30;i++)
   {
    LCD_Command(0x18);/* shift entire display left */
    _delay_ms(300);
   }
  }
 
 return 0;
}

No comments:

Post a Comment