Overview of LCD 16x2
LCDs (Liquid Crystal Displays) are used for displaying status or parameters in embedded systems.
LCD 16x2 is a 16-pin device that has 8 data pins (D0-D7) and 3 control pins (RS, RW, EN). The remaining 5 pins are for the 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 the requirement of the 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 to the topic LCD 16x2 display module in the sensors and modules section.
LCD 16x2 Pinout:
Connection Diagram of LCD 16x2 with ATmega16/32
Hardware Connections
LCD 162 Pins | ATmega16 Pins |
---|---|
Data pins D0-D7 | PORT B |
RS | PORTC.0 |
RW | PORTC.1 |
E | PORTC.2 |
Programming for LCD16x2 with AVR ATmega16/ATmega32
Initialize LCD16x2: It is very easy to initialize an LCD16x2
- Power ON the LCD
- Wait for 15 ms (‘Power ON’ initialization time for LCD16x2)
- Send 0x38 command to initialize 2 lines, 5x8 matrix, 8-bit mode LCD16x2
- Send any ‘Display ON’ command (0x0E, 0x0C) to LCD16x2
- 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
- Send the command value to the LCD16x2 data port.
- Make RS pin low, RS = 0 (command reg.)
- Make RW pin low, RW = 0 (write operation)
- Give high to low pulse at the Enable (E) pin of a minimum delay of 450 ns.
When we give an enable pulse, the LCD latches the data present at D0 to D7, and execute as a 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
- Send command to the data port.
- Make the RS pin High, RS = 1 (Data reg.)
- Make the RW pin Low, RW = 0 (Write operation)
- Give high to low pulse at the Enable (E) pin
When we give an enable pulse the LCD latches the data present (on 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:
- LCD Power-on delay: After the LCD16x2 powers ON, we cannot send commands immediately to it since it needs a 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 a command to the LCD.
- After proving commands, LCD16x2 takes time (in microseconds) to execute it. But for the 0x01 command (i.e. clear display), it takes 1.64-ms to execute. Therefore, after sending the 0x01 command sufficient delay (> 1.63 milliseconds) needs to be provided.
LCD16x2 Code for ATmega16/32
/*
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 the following commands
Command | Command meaning |
---|---|
0x1c | Shift the entire display right |
0x18 | Shift the entire display left |
For rolling the display, simply we have to put these commands 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 LCD 16x2 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;
}
Components Used |
||
---|---|---|
LCD16x2 Display LCD16x2 Display |
X 1 | |
ATmega 16 ATmega 16 |
X 1 | |
Atmega32 Atmega32 |
X 1 |