We usually found an LCD module in electronic projects, commonly 16×2 alphanumeric displays. It has a built-in controller calls HD44780 chip. It’s an industrial standard alphanumeric LCD controller from Hitachi released around 1987. Today there are many compatible LCD controllers to this chip. However, they perform the same function.
16×2 LCD Module
A popular LCD module is 16 characters by 2 lines. It’s widely available. I bought it from EBay around 2 dollars. It usually comes with backlight with many color options.
A yellow backlight 16×2 LCD module with 16 pins |
The module is connected with 16 pins. The first three pins are supply voltage and contrast adjustment. The next 11 pins are control signals and data port. The remaining two pin are for backlight. The table below is a description of those pins.
Pin Description | ||
Pin number | Name | Function |
1 | VSS | Supply ground |
2 | VDD | +5V supply |
3 | VO | Contrast Adjustment |
4 | RS | Register select |
5 | RW | Read/Write |
6 | E | Enable |
7 | D0 | 8-bit data port |
8 | D1 | |
9 | D2 | |
10 | D3 | |
11 | D4 | |
12 | D5 | |
13 | D6 | |
14 | D7 | |
15 | A | Backlight anode |
16 | K | Backlight cathode |
The character display on LCD could ASCII and some Japanese characters. Some special characters could also be display using bitmap and special command.
LCD Controlling
To control this module we use to main operations, writing the instruction and writing the data. The instruction is command for LCD, for example turning on or clearing the display. Commanding the display is first step we must do, while writing the data is additional.
Writing command or data depends on RS pin. Give RS=0 to write command, while RS=1 is for data. The R/W is set to 0 mean writing modes, forces data port to become input. The E pin must toggle from high to low forcing the module to accept input data at data port.
Here is some command of LCD.
Commands for LCD | |
Hex codes | Instruction |
1 | Clear display screen |
2 | Return home |
4 | Decrement cursor |
6 | Increment cursor |
5 | Shift display right |
7 | Shift display left |
8 | Display off, cursor off |
C | Display off, cursor off |
E | Display off, cursor on |
F | Display on, cursor blinking |
10 | Shift cursor position to the left |
14 | Shift cursor position to the right |
18 | Shift entire display to the left |
1C | Shift entire display to the right |
80 | Force cursor to the beginning of 1st line |
C0 | Force cursor to the beginning of 2nd line |
28 | 2 lines and 5×7 matrix (4-bit) |
38 | 2 lines and 5×7 matrix (8-bit) |
Writing the command
In this section we use 8-bit LCD mode. To write the command we must do the following step.
- Assign E=0 (if it’s not 0)
- Assign the command to the LCD port.
- Assign RS=0 and RW=0
- Assign E=1 for very short time
- And assign E=0
Writing the Data
To write the data we must do the following step.
- Assign the data (character) to the LCD port
- Assign RS=1 and RW=0
- Assign E=1 for very short time
- And assign E=0
Writing C code in MPLABX
In MPLABX I use XC8 C compiler due to its free of use. The circuit below is drawn using Proteus 8. The microcontroller I use is PIC16F876A that I posses, despite its factory discontinuity. The data port is connected to PORTB and control signal is connected to PORTC. Pin RW is not important because I only write to LCD. I can short it to ground.
Circuit connection |
The C codes below are written using XC8:
#include <xc.h> #include "config.h" #define _XTAL_FREQ 20e6 #define LCD_PORT PORTB #define LCD_DIR TRISB #define LCD_CON TRISC #define RS PORTCbits.RC0 #define RW PORTCbits.RC1 #define EN PORTCbits.RC2 void sDelay(unsigned int delay); void latch(void); void lcdCmd(unsigned char cmd); void lcdDat(unsigned char dat); void lcdStr(unsigned char *str); void lcdInit(); void main(){ lcdInit(); lcdStr("HELLO WORLD !"); lcdCmd(0xC0); // goto 2nd line lcdStr("FROM PHNOM PENH"); while(1); } void sDelay(unsigned int delay){ for(int i=0;i<delay;i++); } void lcdInit(){ LCD_PORT=0x00; LCD_DIR=0x00; LCD_CON=0x00; EN=0; lcdCmd(0x38); // 16x2 5x7 lcdCmd(0x0E); // display ON Cursor ON lcdCmd(0x01); // clear display sDelay(2000); lcdCmd(0x06); // shift cursor to the right } void latch(){ EN=1; sDelay(100); EN=0; } void lcdCmd(unsigned char cmd){ LCD_PORT=cmd; // send command to PORTB RS=0; // RS=0 for command RW=0; // RW=0 for writing latch(); // EN H_TO_L transition to latch data sDelay(20); } void lcdDat(unsigned char dat){ LCD_PORT=dat; // SEND DATA TO PORTA RS=1; // RS=1 FOR DATA RW=0; // RW=0 FOR WRITTING latch(); sDelay(20); } void lcdStr(unsigned char *str){ while(*str) lcdDat(*str++); }
Source Link: https://github.com/BongPeav/xc8/raw/master/PIC16F876A_LCD.X.rar