The use of a graphical LCD (GLCD) drastically changes the look of your project. It provides more freedom for presenting data than the HD44870 based character LCDs. Today we will see how to interface a KS0108 (name of the display controller chip) based GLCD to a PIC microcontroller. This experimental tutorial is divided into two parts. In the first part, we will see how to write a firmware for the PIC microcontroller to initialize the GLCD and send data to plot points and lines on the screen. The second part will focus more on exploring the built-in GLCD Library of mikroC Pro for PIC compiler to display more complex texts and objects. Since GLCDs are real resource hungry devices (in terms of required I/O pins and memory), a bigger size PIC microcontroller (PIC16F887, which has 36 I/O pins and 14KB flash memory) is selected for this experiment. I am using MikroElektronika’s UNI-DS6 development board to demonstrate this project, but the circuit setup can also be made on a breadboard.
Interfacing a 128×64 pixels GLCD
Theory
The graphical LCD used in this experiment is Winstar’s WDG0151-TMI module, which is a 128×64 pixel monochromatic display. It uses two Neotic display controller chips: NT7108C and NT7107C, which are compatible with Samsung KS0108B and KS0107B controllers. The KS0108B (or NT7108C)is a dot matrix LCD segment driver with 64 channel output, and therefore, the WDG0151 module contains two sets of it to drive 128 segments. On the other hand, the KS0107B (or NT7107C) is a 64-channel common driver which generates the timing signal to control the two KS0108B segment drivers. The KS0108B and KS0107B are a very popular controllers and have made their way into many graphical LCDs. The internal block diagram of the WDG0151 GLCD module is shown below.
Internal block diagram of a KS0108B (NT7108C) based 128×64 pixel GLCD module
The NT1707C drives the 64 display lines, COM1 – COM64. The first NT7108C drives the left half segments (SEG1 to SEG64) and the second one drives the right half segments (SEG65 to SEG128) of the display. The two halves of the display can be individually accessed through the chip select pins (CS1 and CS2) of the two NT7108C drivers. Each half consists of 8 horizontal pages (0-7) which are 8 bits (1 byte) high. This is illustrated in the drawing below.
GLCD pages
Starting from page 0 on the left half (/CS1 = 0) if you transmit one data byte, it will appear on the first column of page 0. If you repeat this 64 times, then switch to the second half, and repeat until 128th position is reached, the first 8 display lines will be plotted. The next 8 lines can be plotted similarly by switching to page address 1. The total amount of bytes needed for a complete display frame (128×64 pixels) is, therefore,2 * 64 pixels * 8 bits = 1024 bytes.
The Winstar WDG0151-TMI module does have an internal negative voltage generator circuit which provides a negative voltage at VEE external pin. An external potentiometer (usually 10 K) is connected between Vcc and VEE pins to set the LCD working voltage (contrast) at Vo pin. The pin diagrams of KS0108 based GLCDs is not standardized and it is therefore, important to read the manufacturer’s datasheet for correct wiring of a GLCD module. The following table shows the pin descriptions ofWinstar WDG0151-TMI module. It has altogether 20 pins. The first two pins (1 and 2) are the chip select pins for the left and right display controller. They are active low in a WDG0151-TMI module, but they could be active high in some other models. That’s why I said reading manufacturer’s datasheet is very important. The WDG0151-TMI module operates at 5.0 V power supply. Pin number 6 is Data/Instruction (also called Register Select, RS) select pin. The 8-bit data fed to D0-D7 pins of the GLCD is received by the LCD controller chip as an instruction if D/I = 0, and as data if D/I is 1. The R/W and E pins have similar functions as in a HD44780 based character LCD module.A fixed resistor value must be connected in series with the back-light LED (pins 19 and 20) to limit the current.
Pin description of Winstar WDG01510 GLCD module
The KS0107/KS0108 does not have a character generator so this must be implemented in the microcontroller firmware. The LCD controller supports a handful of instructions which are summarized in the table shown below. Note that the RS (D/I) pin is high only during data read and data write operations, and stays low when a transmitted byte is an instruction.
Display control instructions (click on image to enlarge)
Circuit diagram
The circuit diagram for this experiment is shown below. The PIC16F887 microcontroller is used to drive a Winstar WDG0151-TMI GLCD. The data pins are connected to PORTD and other control signals are driven through PORTB pins. I am trying this circuit on MikroElektronika’s UNI-DS6 development board.
Circuit diagram for GLCD interfacing
Software
We will be writing our test program in C using MikroElektronika’s mikroC Pro for PIC compiler. Although, the compiler does provide built-in library routines for GLCD operations, we will first try to write our own test code for transferring display data from the PIC16F887 to the GLCD. Later, we will explore the MikroElektronika’s GLCD library for more complex operations. The code provided below generates 11 dotted horizontal lines on the GLCD screen with a six-line spacing between two. I took most portion of it from Osama’s Lab GLCD library and modified it to suit with mikroC Pro for PIC and WDG0151-TMI GLCD. Here’s a brief description of various user-defined function subroutines used in the code.
GLCD_ON() : This function turns the display on. This can be done by sending the command 3Fh to both the controllers. So, while sending this command, both CS1 and CS2 must be pulled low. Similarly the RS pin should be low too as the byte sent is an instruction.
Set_Start_Line() :This function changes the line number to be displayed at the top of the screen. You can set it to be any number between 0 to 63. It does not affect the data in the display RAM, it just scrolls the display up and down.
GOTO_COL() : Moves the cursor to specified column (0-127).
GOTO_ROW() : Moves the cursor to specified row or page number (0-7).
GOTO_XY() : Moves the cursor to specified row and column.
GLCD_Write() : Writes a byte of data to the current location.
GLCD_Read() : Returns a byte read from the current display location. If you see the code for this subroutine, you will see there are two read operations involved. The first one is a dummy read during which the data is fetched from the display RAM is latched in to the output register of KS0108B. In the second read, the microcontroller can get the actual data.
GLCD_Clrln() : Clears a specified row (0-7).
GLCD_CLR() : Clears the whole screen (all 8 pages).
Draw_Point() : Plots a dark or light color point at a specified position.
At the end, the dotted lines are created by plotting too many points in horizontal directions.
/** Project name: Testing GLCD with PIC16F887Embedded-Lab.com, 2011.* Description:This routine demonstrates how to initialize a KS0108 based GLCD andactivate the pixels on the display. A sub-routine is written to draw a point onthe GLCD at a given coordinates, and is used to draw dotted lines.* Test configuration:MCU:PIC16F887Dev.Board:UNI-DS6Oscillator:HS, 10.0000 MHzExt. Modules:GLCD 128x64, KS108/107 controller*/// Glcd module connections#define GLCD_DataPORTD#define GLCD_DirTRISDsbit GLCD_CS1 at RB0_bit;sbit GLCD_CS2 at RB1_bit;sbit GLCD_RSat RB2_bit;sbit GLCD_RWat RB3_bit;sbit GLCD_RSTat RB4_bit;sbit GLCD_EN at RB5_bit;sbit GLCD_CS1_Direction at TRISB0_bit;sbit GLCD_CS2_Direction at TRISB1_bit;sbit GLCD_RS_Directionat TRISB2_bit;sbit GLCD_RW_Directionat TRISB3_bit;sbit GLCD_RST_Directionat TRISB4_bit;sbit GLCD_EN_Direction at TRISB5_bit;// End Glcd module connectionsvoid Enable_Pulse(){GLCD_EN = 1; //EN highdelay_us(5);GLCD_EN = 0; //EN lowdelay_us(5);}void GLCD_ON(){//Activate both chipsGLCD_CS1 = 0;GLCD_CS2 = 0;GLCD_RS = 0;//RS low for command byteGLCD_RW = 0;//RW low for writeGLCD_Data = 0x3F;//ON commandEnable_Pulse();}void Set_Start_Line(unsigned short line){GLCD_RS = 0;//RS low for commandGLCD_RW = 0;//RW low for write//Activate both chipsGLCD_CS1 = 0;GLCD_CS2 = 0;GLCD_Data = 0xC0 | line;//Set Start Line commandEnable_Pulse();}void GOTO_COL(unsigned int x){unsigned short Col_Data;GLCD_RS = 0;GLCD_RW = 0;if(x<64)//Left Half{GLCD_CS1 = 0;//select chip 1GLCD_CS2 = 1;//deselect chip 2Col_Data = x;//put column address on data port}else//Right Half{GLCD_CS2 = 0;GLCD_CS1 = 1;Col_Data = x-64;//put column address on data port}Col_Data = (Col_Data | 0x40 ) & 0x7F;//Command formatGLCD_Data = Col_Data;Enable_Pulse();}void GOTO_ROW(unsigned int y){unsigned short Row_Data;GLCD_RS = 0;GLCD_RW = 0;Row_Data = (y | 0xB8 ) & 0xBF; //put row address on data portGLCD_Data = Row_Data;Enable_Pulse();}void GOTO_XY(unsigned int x,unsigned int y){GOTO_COL(x);GOTO_ROW(y);}void GLCD_Write(unsigned short b){GLCD_RS = 1;GLCD_RW = 0;GLCD_Data = b;delay_us(1);Enable_Pulse();}unsigned short GLCD_Read(unsigned short column){unsigned short read_data = 0; //Read data hereGLCD_Dir = 0xFF;//PORTD as InputGLCD_RW = 1;//ReadGLCD_RS = 1;//DataGLCD_CS1 = (column>63);GLCD_CS2 = !GLCD_CS1;//Disable/Enable CS2delay_us(1);GLCD_EN = 1;//Latch RAM data into ouput registerdelay_us(1);//Dummy read to fetch data from the display RAMGLCD_EN = 0;//Low Enabledelay_us(5);GLCD_EN = 1;//latch data from output register to data busdelay_us(1);read_data = GLCD_Data;//Input dataGLCD_EN = 0;//Low Enable to remove data from the busdelay_us(1);GLCD_Dir = 0x00;//PORTD is Output againreturn read_data;}void GLCD_Clrln(unsigned short ln){int i;GOTO_XY(0,ln);//At start of line of left sideGOTO_XY(64,ln);//At start of line of right sideGLCD_CS1 = 0;for(i=0;i<65;i++)GLCD_Write(0);}void GLCD_CLR(){unsigned short m;for(m=0;m<8;m++){GLCD_Clrln(m);}}void Draw_Point(unsigned short x,unsigned short y, unsigned short color){unsigned short Col_Data;;GOTO_XY(x,(y/8));switch (color){case 0://Light spotCol_Data = ~(1<<(y%8)) & GLCD_Read(x);break;case 1://Dark spotCol_Data = (1<<(y%8)) | GLCD_Read(x);break;}GOTO_XY(x,(y/8));GLCD_Write(Col_Data);}void main() {unsigned short u, v;ANSEL= 0;// Configure AN pins as digitalANSELH = 0;C1ON_bit = 0;// Disable comparatorsC2ON_bit = 0;TRISD = 0x00;TRISB = 0x00;PORTB = 0x00;PORTD = 0x00;GLCD_CS1 = 1;// De-Activate both chipsGLCD_CS2 = 1;GLCD_RST = 1;GLCD_ON();GLCD_CLR();Set_Start_Line(0);do {for(u=0; u<64; u+=6)for (v=0; v<128; v+=2)Draw_Point(v, u, 1);delay_ms(1000);GLCD_CLR();delay_ms(1000);} while(1);}
Download the Source code and HEX file
When the microcontroller runs the program, you will see 11 dotted horizontal lines displayed on the screen as shown below.
Dotted horizontal lines
Summary
In this experimental tutorial, the internal block diagram of a KS0108 based 128×64 pixel GLCD, its pin configurations, and instruction set were discussed briefly. The GLCD operation was demonstrated with a Winstar WDG0151 GLCD module interfaced to the PIC16F887 microcontroller. A very basic firmware was written in mikroC Pro for PIC to demonstrate how to activate selected pixels on the screen to draw a line. In the second part of this tutorial (will be posted soon) we will learn to use the built-in GLCD library of mikroC Pro for PIC compiler to draw more complex objects and texts on the screen.
[via: http://embedded-lab.com/]







