In this blog post, we will learn 4 bit LCD interfacing with PIC Microcontroller (PIC16F877A). In my previous blog post, we discussed “how to interface 16×2 LCD with PIC Microcontroller (PIC16F877A) in an 8-bit Mode“.
Here I assume that you already know how to interface LCD in 8-bit mode. Here we will also see the C program to interface LCD in 4-bit mode with circuit diagram.
As we know microcontroller has a fixed number of GPIO pins. So generally, LCD is interfaced in 4-bit mode with microcontrollers to save I\O pins of microcontrollers. Before beginning any further I assume that you know the difference between 4-bit and 8-bit LCD interfacing mode with microcontrollers.
Note: In LCD 4-bit data write only on the upper nibble of the data bus, means that only D4, D5, D6, and D7 data bus are useful.
Pin Configuration of 16*2 Alphanumeric LCD:
A 16×2 Liquid Crystal Display has two rows and each row contains 16 columns. There are 16 pins in the LCD module, the pin configuration us given below,
Ground pin | ||
Power supply pin of 5V | ||
Used for adjusting the contrast commonly attached to the potentiometer. | ||
RS is the register select pin used to write display data to the LCD (characters), this pin has to be high when writing the data to the LCD. During the initializing sequence and other commands, this pin should low.RS = 0; Select command resistor.
RS = 1; Select data resistor. |
||
Reading and writing data to the LCD for reading the data R/W pin should be high (R/W=1) to write the data to LCD R/W pin should be low (R/W=0).R/W = 0; write operation.
R/W = 1; Read operation. |
||
Enable pin is for starting or enabling the module. A high to the low pulse of about 450ns pulse is given to this pin. | ||
D0-D7 Data pins for giving data(normal data like numbers characters or command data) which is meant to be displayed | ||
Back-light of the LCD which should be connected to Vcc | ||
Back-light of LCD which should be connected to ground. |
Some useful commands for 16×2 Alphanumeric LCD:
Below I am mentioning few commands related to the 16×2 LCD. You can interface 16×2 LCD in two-mode 8bit and 4bit.
For switching on LCD, blinking the cursor. | |
Clearing the screen | |
Return home. | |
Decrement cursor | |
Increment cursor | |
Display on and also cursor on | |
Force cursor to the beginning of the first line | |
Force cursor to the beginning of the second line | |
Use two lines and 5×7 matrix | |
Cursor line 1 position 3 | |
Activate the second line | |
Jump to second-line position 3 | |
Jump to the second line position1 |
Steps to send command on 16×2 LCD:
- E=1; enable pin should be high.
- RS=0; Register select should be low.
- R/W=0; Read/Write pin should be low.
Steps to send the character on 16×2 LCD:
- E=1; enable pin should be high.
- RS=1; Register select should be high.
- R/W=0; Read/Write pin should be low.
Connection of 16×2 LCD in 4-bit mode
In 4-bit mode, the only upper nibble of the data bus is used for reading and writing. So D4, D5, D6, and D7 will only attach with GPIO of the microcontroller for reading and writing. In below Image LCD data pins attached with PORT 2. Another connection of LCD 4-bit is the same as in the 8-bit mode.
In this blog post, I have written codes to display a moving message “Hello world!”. I have used MPLAB v8.85 with the HI-TECH C v9.83 compiler to creating this project “16*2 Character LCD Interfacing with PIC Microcontroller in 4-bit Mode”.
/* Name : main.c * Purpose : Main file for LCD 4 bit-mode. * Author : Amlendra Kumar * Website : https://aticleworld.com */ #include<htc.h> #include<string.h> // Configuration word for PIC16F877A __CONFIG( FOSC_HS & WDTE_OFF & PWRTE_ON & CP_OFF & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF); // Define CPU Frequency // This must be defined, if __delay_ms() or // __delay_us() functions are used in the code #define _XTAL_FREQ 20000000 // Define Pins #define LCD_E RB0 // Enable pin for LCD #define LCD_RS RB1 // RS pin for LCD #define LCD_Data_Bus_D4 RB4 // Data bus bit 4 #define LCD_Data_Bus_D5 RB5 // Data bus bit 5 #define LCD_Data_Bus_D6 RB6 // Data bus bit 6 #define LCD_Data_Bus_D7 RB7 // Data bus bit 7 // Define Pins direction registrers #define LCD_E_Dir TRISB0 #define LCD_RS_Dir TRISB1 #define LCD_Data_Bus_Dir_D4 TRISB4 #define LCD_Data_Bus_Dir_D5 TRISB5 #define LCD_Data_Bus_Dir_D6 TRISB6 #define LCD_Data_Bus_Dir_D7 TRISB7 // Constants #define E_Delay 500 // Function Declarations void WriteCommandToLCD(unsigned char); void WriteDataToLCD(char); void InitLCD(void); void WriteStringToLCD(const char*); void ClearLCDScreen(void); int main(void) { CMCON = 0x07;// Turn comparator off InitLCD(); // Initialize LCD in 8bit mode int siLoop; int msgLen = 0; const char *msg ="Hello World!"; msgLen = strlen(msg); while(1) { WriteCommandToLCD(0x8f); /*Address of DDRAM*/ WriteStringToLCD(msg); // Write Hello World on LCD for(siLoop=0; siLoop < msgLen; siLoop++) { WriteCommandToLCD(0x1c); __delay_us(100000); // so that LCD can latch the } } return 0; } void ToggleEpinOfLCD(void) { LCD_E = 1; // Give a pulse on E pin __delay_us(E_Delay); // so that LCD can latch the LCD_E = 0; // data from data bus __delay_us(E_Delay); } void WriteCommandToLCD(unsigned char Command) { LCD_RS = 0; // It is a command PORTB &= 0x0F; // Make Data pins zero PORTB |= (Command&0xF0); // Write Upper nibble of data ToggleEpinOfLCD(); // Give pulse on E pin PORTB &= 0x0F; // Make Data pins zero PORTB |= ((Command<<4)&0xF0); // Write Lower nibble of data ToggleEpinOfLCD(); // Give pulse on E pin } void WriteDataToLCD(char LCDChar) { LCD_RS = 1; // It is data PORTB &= 0x0F; // Make Data pins zero PORTB |= (LCDChar&0xF0); // Write Upper nibble of data ToggleEpinOfLCD(); // Give pulse on E pin PORTB &= 0x0F; // Make Data pins zero PORTB |= ((LCDChar<<4)&0xF0); // Write Lower nibble of data ToggleEpinOfLCD(); // Give pulse on E pin } void InitLCD(void) { // Firstly make all pins output LCD_E = 0; // E = 0 LCD_RS = 0; // RS = 0 LCD_Data_Bus_D4 = 0; // Data bus = 0 LCD_Data_Bus_D5 = 0; // Data bus = 0 LCD_Data_Bus_D6 = 0; // Data bus = 0 LCD_Data_Bus_D7 = 0; // Data bus = 0 LCD_E_Dir = 0; // Make Output LCD_RS_Dir = 0; // Make Output LCD_Data_Bus_Dir_D4 = 0; // Make Output LCD_Data_Bus_Dir_D5 = 0; // Make Output LCD_Data_Bus_Dir_D6 = 0; // Make Output LCD_Data_Bus_Dir_D7 = 0; // Make Output ///////////////// Reset process from datasheet ////////////// __delay_ms(40); PORTB &= 0x0F; // Make Data pins zero PORTB |= 0x30; // Write 0x3 value on data bus ToggleEpinOfLCD(); // Give pulse on E pin __delay_ms(6); PORTB &= 0x0F; // Make Data pins zero PORTB |= 0x30; // Write 0x3 value on data bus ToggleEpinOfLCD(); // Give pulse on E pin __delay_us(300); PORTB &= 0x0F; // Make Data pins zero PORTB |= 0x30; // Write 0x3 value on data bus ToggleEpinOfLCD(); // Give pulse on E pin __delay_ms(2); PORTB &= 0x0F; // Make Data pins zero PORTB |= 0x20; // Write 0x2 value on data bus ToggleEpinOfLCD(); // Give pulse on E pin __delay_ms(2); /////////////// Reset Process End //////////////// WriteCommandToLCD(0x28); //function set WriteCommandToLCD(0x0c); //display on,cursor off,blink off WriteCommandToLCD(0x01); //clear display WriteCommandToLCD(0x06); //entry mode, set increment } void WriteStringToLCD(const char *s) { while(*s) { WriteDataToLCD(*s++); // print first character on LCD } } void ClearLCDScreen(void) // Clear the Screen and return cursor to zero position { WriteCommandToLCD(0x01); // Clear the screen __delay_ms(2); // Delay for cursor to return at zero position }
Proteus Simulation of 4 bit LCD interfacing with PIC:
Code Analysis:
InitLCD():
This function is used to initialize the LCD with proper commands. Below I am mentioning some commands which are used in LCD initialization.
0x28 is used for 4-bit data initialization. 0x0C for making LCD display on and cursor off. 0X01 for clearing the display of the LCD. 0x06 for increment cursor (shift cursor to right)
WriteCommandToLCD():
Whenever you send the command on 16×2 LCD, you have to set RS and RW pin low and E (enable) pin high. In code, I have written a function WriteCommandToLCD() which set RS pin low and E pin high. You can see the circuit I have already set RW pin low with the connection.
void WriteCommandToLCD(unsigned char Command) { LCD_RS = 0; // It is a command PORTB &= 0x0F; // Make Data pins zero PORTB |= (Command&0xF0); // Write Upper nibble of data ToggleEpinOfLCD(); // Give pulse on E pin PORTB &= 0x0F; // Make Data pins zero PORTB |= ((Command<<4)&0xF0); // Write Lower nibble of data ToggleEpinOfLCD(); // Give pulse on E pin }
WriteDataToLCD():
Whenever you send the character on 16×2 LCD for display, you have to set RS pin high, RW pin low and E (enable) pin high. In code, I have written a function WriteDataToLCD() which set RS pin high and E pin high. Due to the hardware connection, the RW PIN already low.
void WriteDataToLCD(char LCDChar) { LCD_RS = 1; // It is data PORTB &= 0x0F; // Make Data pins zero PORTB |= (LCDChar&0xF0); // Write Upper nibble of data ToggleEpinOfLCD(); // Give pulse on E pin PORTB &= 0x0F; // Make Data pins zero PORTB |= ((LCDChar<<4)&0xF0); // Write Lower nibble of data ToggleEpinOfLCD(); // Give pulse on E pin }
Recommended Post:
- 16*2 LCD Interfacing with PIC Microcontroller in 8-bit Mode.
- Push-button interfacing with PIC microcontroller.
- LED Interfacing with PIC Microcontroller.
- Read and Write to Internal EEPROM of PIC Microcontroller.
- Interfacing EEPROM with PIC Microcontroller – I2C Based.
- Interfacing RTC DS1307 with PIC Microcontroller.
- Display Custom Characters on LCD using PIC Microcontroller.
- Led blinking program in c for 8051.
- Interfacing of switch and led using the 8051
- Interfacing of Relay with 8051 microcontroller
- Moving message display on LCD using 8051
- LCD 4-bit mode c code for 8051.
- Create LCD custom characters for 16×2 alphanumeric LCD
- Interfacing of keypad with 8051
- Electronic digital lock using the 8051
- Interfacing of EEPROM with 8051 microcontrollers using I2C
- Embedded c interview questions.
- 8051 Microcontroller Pin Diagram and Pin Description.
- Can protocol interview questions.
- 8051 Architecture.