Interfacing an alphanumeric display to PIC16F876A using MPLABX XC8

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.

 1
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.

 2
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

Leave a comment