Introduction
LCDs (Liquid Crystal Displays) are used for displaying status or parameters in embedded systems.
LCD 16x2 is a 16 pin device 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 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 Pin Diagram
LCD 16x2 Interfacing With PIC18F4550 Microcontroler
Programming LCD16x2 with PIC18F4550
Initialize LCD16x2: It is very easy to initialize LCD
- Power ON LCD
- Wait for 15ms, Power-on initialization time for LCD16x2.
- Send 0x38 command (initialize 2 lines, 5x8 matrix, 8-bit mode)
- Send any Display ON command (0x0E, 0x0C)
- Send 0x06 command (increment cursor)
void LCD_Init()
{
MSdelay(15); /* 15ms,16x2 LCD Power on delay */
LCD_Port = 0x00; /* set PORT as output PORT for LCD data(D0-D7) pins */
LCD_Control = 0x00; /* set PORT as output PORT LCD Control(RS,EN) Pins */
LCD_Command(0x38); /* uses 2 line and initialize 5*8 matrix of LCD */
LCD_Command(0x01); /* clear display screen */
LCD_Command(0x0c); /* display on cursor off */
LCD_Command(0x06); /* increment cursor (shift cursor to right) */
}
Command write function
- Send command to the data port
- Make RS pin low, RS=0 (command register)
- Make RW pin low, RW=0 (write operation) or connect it to ground.
- Give High to Low pulse at Enable (E).
When we give Enable pulse, LCD latches the data present at D0 to D7 & executes it as a command as RS is command register.
void LCD_Command(char cmd )
{
ldata= cmd; /* Send data to PORT as a command for LCD */
RS = 0; /* Command Register is selected */
EN = 1; /* High-to-Low pulse on Enable pin to latch data */
NOP();
EN = 0;
MSdelay(3);
}
Data write function
- Send command to the data port.
- Make RS pin high, RS=1 (data register)
- Make RW pin low or connect it to the ground.
- Give High to Low pulse at Enable (E)
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(char dat)
{
ldata= dat; /* Send data to LCD */
RS = 1; /* Data Register is selected */
EN=1; /* High-to-Low pulse on Enable pin to latch data */
NOP();
EN=0;
MSdelay(1);
}
Display String function
It takes a string (array of character) and sends one character at a time to the LCD data function till the end of the string. This is done by checking the NULL character at the end of the string.
void LCD_String(const char *msg)
{
while((*msg)!=0)
{
LCD_Char(*msg);
msg++;
}
}
Note:
- LCD16x2 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 providing commands to execute, LCD16x2 takes time in microseconds but for 0x01 command (Clear display), it takes 1.64ms to execute. So after giving this command, we need to give sufficient delay> 1.63 milliseconds.
LCD16x2 Program for PIC18F4550 MCU
/*
* Interfacing 16x2 LCD with PIC18F4550
* www.electronicwings.com
*/
#include <pic18f4550.h>
#include "Configuration_Header_File.h"
#define RS LATD0 /* PORTD 0 pin is used for Register Select */
#define EN LATD1 /* PORTD 1 pin is used for Enable */
#define ldata LATB /* PORTB is used for transmitting data to LCD */
#define LCD_Port TRISB
#define LCD_Control TRISD
void LCD_Init();
void LCD_Command(char );
void LCD_Char(char x);
void LCD_String(const char *);
void LCD_String_xy(char ,char ,const char*);
void MSdelay(unsigned int );
/*****************************Main Program*******************************/
void main(void)
{
OSCCON=0x72; /* Use Internal Oscillator with Frequency 8MHZ */
LCD_Init(); /* Initialize 16x2 LCD */
LCD_String_xy(1,5,"Hello"); /* Display string at location(row,location). */
/* This function passes string to display */
LCD_String_xy(2,0,"ElectronicWings"); /*Display string at location(row,location). */
/* This function passes string to display */
while(1);
}
/****************************Functions********************************/
void LCD_Init()
{
MSdelay(15); /* 15ms,16x2 LCD Power on delay */
LCD_Port = 0x00; /* Set PORTB as output PORT for LCD data(D0-D7) pins */
LCD_Control = 0x00; /* Set PORTD as output PORT LCD Control(RS,EN) Pins */
LCD_Command(0x38); /* uses 2 line and initialize 5*7 matrix of LCD */
LCD_Command(0x01); /* clear display screen */
LCD_Command(0x0c); /* display on cursor off */
LCD_Command(0x06); /* increment cursor (shift cursor to right) */
}
void LCD_Clear()
{
LCD_Command(0x01); /* clear display screen */
}
void LCD_Command(char cmd )
{
ldata= cmd; /* Send data to PORT as a command for LCD */
RS = 0; /* Command Register is selected */
EN = 1; /* High-to-Low pulse on Enable pin to latch data */
NOP();
EN = 0;
MSdelay(3);
}
void LCD_Char(char dat)
{
ldata= dat; /* Send data to LCD */
RS = 1; /* Data Register is selected */
EN=1; /* High-to-Low pulse on Enable pin to latch data */
NOP();
EN=0;
MSdelay(1);
}
void LCD_String(const char *msg)
{
while((*msg)!=0)
{
LCD_Char(*msg);
msg++;
}
}
void LCD_String_xy(char row,char pos,const char *msg)
{
char location=0;
if(row<=1)
{
location=(0x80) | ((pos) & 0x0f); /*Print message on 1st row and desired location*/
LCD_Command(location);
}
else
{
location=(0xC0) | ((pos) & 0x0f); /*Print message on 2nd row and desired location*/
LCD_Command(location);
}
LCD_String(msg);
}
/*********************************Delay Function********************************/
void MSdelay(unsigned int val)
{
unsigned int i,j;
for(i=0;i<val;i++)
for(j=0;j<165;j++); /*This count Provide delay of 1 ms for 8MHz Frequency */
}
Rolling Display
In order to roll string on LCD, we need to use the following commands.
Command | Meaning |
---|---|
0x1c | Shift entire display right |
0x18 | Shift entire display left |
For rolling display simply we have to put these commands in a loop.
Rolling Display
- Display string on LCD16x2
- Roll it to right using the ‘0x1C’ command
- Roll it to left using the ‘0x18’ command
LCD16x2 Rolling Display Code
Here, roll string Ewings on display from left to right and then right to left.
Main function code
void main(void)
{
char i,shift;
shift =15;
OSCCON = 0x72; /*use Internal Oscillator with Frequency 8MHZ*/
LCD_Init(); /*initialize 16x2 LCD*/
LCD_String_xy(1,0,"Ewings"); /*display string at location(row, location).
*This function passes string to display*/
while(1)
{
for(i=0;i<shift;i++)
{
LCD_Command(0x1c); /* Shift entire display to right */
MSdelay(1000);
}
for(i=shift;i>0;i--)
{
LCD_Command(0x18); /* Shift entire display to left */
MSdelay(1000);
}
}
}
Components Used |
||
---|---|---|
PICKit 4 MPLAB PICKit 4 MPLAB |
X 1 | |
PIC18f4550 PIC18f4550 |
X 1 | |
LCD16x2 Display LCD16x2 Display |
X 1 |