In this tutorial we will see how to interface and graphical LCD(GLCD) with PIC16F877A. In this tutorial we will look at interfacing KS0108 controller based JHD12864E display. There are many displays out there based on KS0108 or compatible display controller. They all work the same way, but make sure to check the datasheet for the pin diagram before doing the connection.

We will look at the working of the display, the hardware setup and programming with PIC16F877A. You may use any other AVR,8051,PIC,ARM controller as well. We have it tested and working on 8051, AVR, PIC and ARM. We have similar tutorials on these MCUs as well.

Unlike a 16 x 2 display, this does not have a character map for ascii values stored on its ROM. However it allows us the flexibility of creating fonts like Arial, times new roman etc. We could also display bit-map images on it and stretching it little further we can make GUI's and little animation, but that's for another day. So lets get started.

GLCD Internals And Pinout

Below image shows the internal block diagram of 128x64 GLCD along with its pin out. GLCD 128x64 BlockDiagram.png As per the name it has 128pixels on X-axis and 64-pixels on Y-axis. Further the X-axis is divided into two parts of 64 pixels each and controlled by unique contoller/driver IC as shown in the above image. Below table provides the detailed info of all the GLCD pins.

Pin Number Symbol Pin Function
1 VSS Ground
2 VCC +5v
3 VO Contrast adjustment (VO)
4 RS/DI Register Select/Data Instruction. 0:Instruction, 1: Data
5 R/W Read/Write, R/W=0: Write & R/W=1: Read
6 EN Enable. Falling edge triggered
7 D0 Data Bit 0
8 D1 Data Bit 1
9 D2 Data Bit 2
10 D3 Data Bit 3
11 D4 Data Bit 4
12 D5 Data Bit 5
13 D6 Data Bit 6
14 D7 Data Bit 7/Busy Flag
15 CS1 Chip Select for IC1/PAGE0
16 CS2 Chip Select for IC2/PAGE1
17 RST Reset the LCD module
18 VEE Negative voltage used along with Vcc for brightness control
15 A/LED+ Back-light Anode(+)
16 K/LED- Back-Light Cathode(-)


Page, Line and Cursor Selection

GLCD Pages.png Lets view the GLCD as a open book with 2pages constisting of 8lines on each page.
Each line has 64 cursors positions to display data/images.
The required page can be selected using CS1,CS2 pins as shown below.
CS2-CS1:Chip Select Lines
00 = None
01 = Page 0
10 = Page 1
11 = Both Pages

Line Selection

To select the lines we need to send the command/line address to GLCD.
The line address starts from 0xb8 and goes till 0xbf as shown below.

7 6 5 4 3 2 1 0
1 0 1 1 1 Y2 Y1 Y0

Y2-Y0:Line Selection
000 = Line0 (Address = 0xB8)
001 = Line1 (Address = 0xB9)
010 = Line2 (Address = 0xBA)
011 = Line3 (Address = 0xBB)
100 = Line4 (Address = 0xBC)
101 = Line5 (Address = 0xBD)
110 = Line6 (Address = 0xBE)
111 = Line7 (Address = 0xBF)

Cursor/Char Position

To set the cursor position(0-63) we need to send its address to GLCD.
The cursor positions address starts from 0x40 and goes till 0x7f as shown below.

7 6 5 4 3 2 1 0
0 1 x5 x4 x3 x2 x1 x0

x5-x0:Line Selection
000000 = Cursor Position 0 (Address = 0x40)
000001 = Cursor Position 1 (Address = 0x41)
000010 = Cursor Position 2 (Address = 0x42)
'
111111 = Cursor Position 63 (Address = 0x7F)

Instruction Set

Below is the complete instruction table. GLCD InstructionSet.png

Steps

Steps for Sending Command:

  • step1: Send the I/P command to LCD.
  • step2: Select the Control Register by making RS low.
  • step3: Select Write operation making RW low.
  • step4: Send a High-to-Low pulse on Enable PIN with some delay_us.

/* Function to send the command to LCD */
void Glcd_CmdWrite(char cmd)
{
GlcdDataBus = cmd; //Send the Command nibble
GlcdControlBus &= ~(1<<RS); // Send LOW pulse on RS pin for selecting Command register
GlcdControlBus &= ~(1<<RW); // Send LOW pulse on RW pin for Write operation
GlcdControlBus |= (1<<EN); // Generate a High-to-low pulse on EN pin
delay(100);
GlcdControlBus &= ~(1<<EN);
delay(1000);
}
view raw glcd_CmdWrite.c hosted with ❤ by GitHub

Steps for Sending Data:

  • step1: Send the character to LCD.
  • step2: Select the Data Register by making RS high.
  • step3: Select Write operation making RW low.
  • step4: Send a High-to-Low pulse on Enable PIN with some delay.

/* Function to send the Data to LCD */
void Glcd_DataWrite(char dat)
{
GlcdDataBus = dat; //Send the data on DataBus nibble
GlcdControlBus |= (1<<RS); // Send HIGH pulse on RS pin for selecting data register
GlcdControlBus &= ~(1<<RW); // Send LOW pulse on RW pin for Write operation
GlcdControlBus |= (1<<EN); // Generate a High-to-low pulse on EN pin
delay(100);
GlcdControlBus &= ~(1<<EN);
delay(1000);
}


Code

Below is the sample code for displaying HELLO WORLD on two different pages of GLCD.

#include<pic16f877a.h>
/* Configure the data bus and Control bus as per the hardware connection
Dtatus bus is connected to PB0:PB7 and control bus PD0:PD4*/
#define GlcdDataBus PORTB
#define GlcdControlBus PORTD
#define GlcdDataBusDirnReg TRISB
#define GlcdCtrlBusDirnReg TRISD
#define RS 0
#define RW 1
#define EN 2
#define CS1 3
#define CS2 4
/* 5x7 Font including 1 space to display HELLO WORLD */
char H[]={0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00};
char E[]={0x7F, 0x49, 0x49, 0x49, 0x41, 0x00};
char L[]={0x7F, 0x40, 0x40, 0x40, 0x40, 0x00};
char O[]={0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00};
char W[]={0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00};
char R[]={0x7F, 0x09, 0x19, 0x29, 0x46, 0x00};
char D[]={0x7F, 0x41, 0x41, 0x22, 0x1C, 0x00};
/* local function to generate delay */
void delay(int cnt)
{
int i;
for(i=0;i<cnt;i++);
}
void Glcd_SelectPage0() // CS1=1, CS2=0
{
GlcdControlBus |= (1<<CS1);
GlcdControlBus &= ~(1<<CS2);
}
void Glcd_SelectPage1() // CS1=0, CS1=1
{
GlcdControlBus &= ~(1<<CS1);
GlcdControlBus |= (1<<CS2);
}
/* Function to send the command to LCD */
void Glcd_CmdWrite(char cmd)
{
GlcdDataBus = cmd; //Send the Command nibble
GlcdControlBus &= ~(1<<RS); // Send LOW pulse on RS pin for selecting Command register
GlcdControlBus &= ~(1<<RW); // Send LOW pulse on RW pin for Write operation
GlcdControlBus |= (1<<EN); // Generate a High-to-low pulse on EN pin
delay(100);
GlcdControlBus &= ~(1<<EN);
delay(1000);
}
/* Function to send the Data to LCD */
void Glcd_DataWrite(char dat)
{
GlcdDataBus = dat; //Send the data on DataBus nibble
GlcdControlBus |= (1<<RS); // Send HIGH pulse on RS pin for selecting data register
GlcdControlBus &= ~(1<<RW); // Send LOW pulse on RW pin for Write operation
GlcdControlBus |= (1<<EN); // Generate a High-to-low pulse on EN pin
delay(100);
GlcdControlBus &= ~(1<<EN);
delay(1000);
}
void Glcd_DisplayChar(char *ptr_array)
{
int i;
for(i=0;i<6;i++) // 5x7 font, 5 chars + 1 blankspace
Glcd_DataWrite(ptr_array[i]);
}
int main()
{
GlcdDataBusDirnReg = 0x00; // Configure all the LCD pins as output
GlcdCtrlBusDirnReg = 0x00; // Configure the Ctrl pins as output
/* Select the Page0/Page1 and Turn on the GLCD */
Glcd_SelectPage0();
Glcd_CmdWrite(0x3f);
Glcd_SelectPage1();
Glcd_CmdWrite(0x3f);
delay(100);
/* Select the Page0/Page1 and Enable the GLCD */
Glcd_SelectPage0();
Glcd_CmdWrite(0xc0);
Glcd_SelectPage1();
Glcd_CmdWrite(0xc0);
delay(100);
Glcd_SelectPage0(); // Display HELLO on Page0, Line1
Glcd_CmdWrite(0xb8);
Glcd_DisplayChar(H);
Glcd_DisplayChar(E);
Glcd_DisplayChar(L);
Glcd_DisplayChar(L);
Glcd_DisplayChar(O);
Glcd_SelectPage1(); // Display WORLD on Page1, Last line
Glcd_CmdWrite(0xbF);
Glcd_DisplayChar(W);
Glcd_DisplayChar(O);
Glcd_DisplayChar(R);
Glcd_DisplayChar(L);
Glcd_DisplayChar(D);
while(1);
}

Using ExploreEmbedded GLCD Lib

#include "glcd.h" //User defined LCD library which contains the lcd routines
#include "delay.h"
/* start the main program */
void main()
{
/* Initialize the glcd before displaying any thing on the lcd */
GLCD_Init();
GLCD_Printf("Interfacing\n\n");
GLCD_Printf(" KS108 128x64\n\n");
GLCD_Printf(" With Pic16f877a");
GLCD_GoToLine(6);
GLCD_Printf(" ExploreEmbedded");
while(1);
}
0Glcd iterfacing with PIC16f877a.png

Displaying Numbers

#include "glcd.h"
#include "delay.h"
void main()
{
int count=0;
GLCD_Init();
GLCD_DisplayString(" Displaying Numbers");
while(1)
{
GLCD_GoToLine(2);
GLCD_Printf("hex:%4x \n\ndec:%5d \n\nbin:%16b",count,count,count);
DELAY_ms(100);
count++;
}
}
Glcd DisplayNumber.png

Displaying Bar Graphs

#include "glcd.h"
void main()
{
GLCD_Init();
GLCD_HorizontalGraph(0,45);
GLCD_HorizontalGraph(1,50);
GLCD_HorizontalGraph(2,82);
GLCD_HorizontalGraph(3,74);
while(1);
}
Glcd HorizontalGraph.png


#include "glcd.h"
void main()
{
GLCD_Init();
GLCD_VerticalGraph(0,45);
GLCD_VerticalGraph(1,50);
GLCD_VerticalGraph(2,82);
GLCD_VerticalGraph(3,74);
while(1);
}
Glcd VerticalGraph.png

Downloads

Download the complete project folder from the below link:
Hardware design Files and Code Library


Have a opinion, suggestion , question or feedback about the article let it out here!