3-LCD GRÁFICO PIC18F4550


                               


Esta práctica consiste en utilizar un LCD gráfico desde el PIC 18F4550.
Haremos un conversor AD y mostraremos textos y figuras con el fin de familiarizarnos con los comandos de las librerías del LCD.


La resolución de este LCD es de 128x64 y su controlador es el KS0108.




En Proteus realizaremos la simulación con el  LGM12641BS1R.



Para simplificar el uso de este dispositivo,  CCSC Compiler nos facilita la librería  “ Graphics.c “ en “C:\Program Files (x86)\PICC\Drivers”.


La librería es la siguiente:


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
////                          graphics.c                             ////
////                                                                 ////
////   This file contains functions to draw lines, rectangles, bars, ////
////   circles and text to a display. A function which draws a       ////
////   single pixel must be defined before calling the functions in  ////
////   this file. Call it glcd_pixel(x, y, color) where x is the     ////
////   horizontal coordinate, y is the vertical coordinate, and      ////
////   color is 1 bit to turn the pixel on or off.                   ////
////                                                                 ////
////   * Note: (0, 0) is treated as the upper left corner            ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
////  glcd_line(x1, y1, x2, y2, color)                               ////
////     * Draws a line from the first point to the second point     ////
////       with the given color                                      ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_rect(x1, y1, x2, y2, fill, color)                         ////
////     * Draws a rectangle with one corner at point (x1,y1) and    ////
////       the other corner at point (x2,y2)                         ////
////       - fill can be YES or NO                                   ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_bar(x1, y1, x2, y2, width, color)                         ////
////     * Draws a bar (wide line) from the first point to the       ////
////       second point                                              ////
////       - width is the number of pixels wide                      ////
////       - color is ON or OFF                                      ////
////                                                                 ////
////  glcd_circle(x, y, radius, fill, color)                         ////
////     * Draws a circle with center at (x,y)                       ////
////       - fill can be YES or NO                                   ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_text57(x, y, textptr, size, color)                        ////
////     * Write the null terminated text pointed to by textptr with ////
////       the upper left coordinate of the first character at (x,y) ////
////       Characters are 5 pixels wide and 7 pixels tall            ////
////       - size is an integer that scales the size of the text     ////
////       - color is ON or OFF                                      ////
////     * Note - This function wraps characters to the next line    ////
////              use #define GLCD_WIDTH to specify a display width  ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996, 2004 Custom Computer Services        ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////
#ifndef GRAPHICS_DRAWING_FUNCTIONS
#define GRAPHICS_DRAWING_FUNCTIONS
/////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////
#ifndef ON
#define ON  1
#endif

#ifndef OFF
#define OFF 0
#endif

#ifndef YES
#define YES 1
#endif

#ifndef NO
#define NO  0
#endif
/////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////
//// Defines a 5x7 font
/////////////////////////////////////////////////////////////////////////
const int8 FONT[51][5] ={0x00, 0x00, 0x00, 0x00, 0x00, // SPACE
                         0x00, 0x00, 0x5F, 0x00, 0x00, // !
                         0x00, 0x03, 0x00, 0x03, 0x00, // "
                         0x14, 0x3E, 0x14, 0x3E, 0x14, // #
                         0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
                         0x43, 0x33, 0x08, 0x66, 0x61, // %
                         0x36, 0x49, 0x55, 0x22, 0x50, // &
                         0x00, 0x05, 0x03, 0x00, 0x00, // '
                         0x00, 0x1C, 0x22, 0x41, 0x00, // (
                         0x00, 0x41, 0x22, 0x1C, 0x00, // )
                         0x14, 0x08, 0x3E, 0x08, 0x14, // *
                         0x08, 0x08, 0x3E, 0x08, 0x08, // +
                         0x00, 0x50, 0x30, 0x00, 0x00, // ,
                         0x08, 0x08, 0x08, 0x08, 0x08, // -
                         0x00, 0x60, 0x60, 0x00, 0x00, // .
                         0x20, 0x10, 0x08, 0x04, 0x02, // /
                         0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
                         0x00, 0x04, 0x02, 0x7F, 0x00, // 1
                         0x42, 0x61, 0x51, 0x49, 0x46, // 2
                         0x22, 0x41, 0x49, 0x49, 0x36, // 3
                         0x18, 0x14, 0x12, 0x7F, 0x10, // 4
                         0x27, 0x45, 0x45, 0x45, 0x39, // 5
                         0x3E, 0x49, 0x49, 0x49, 0x32, // 6
                         0x01, 0x01, 0x71, 0x09, 0x07, // 7
                         0x36, 0x49, 0x49, 0x49, 0x36, // 8
                         0x26, 0x49, 0x49, 0x49, 0x3E, // 9
                         0x00, 0x36, 0x36, 0x00, 0x00, // :
                         0x00, 0x56, 0x36, 0x00, 0x00, // ;
                         0x08, 0x14, 0x22, 0x41, 0x00, // <
                         0x14, 0x14, 0x14, 0x14, 0x14, // =
                         0x00, 0x41, 0x22, 0x14, 0x08, // >
                         0x02, 0x01, 0x51, 0x09, 0x06, // ?
                         0x3E, 0x41, 0x59, 0x55, 0x5E, // @
                         0x7E, 0x09, 0x09, 0x09, 0x7E, // A
                         0x7F, 0x49, 0x49, 0x49, 0x36, // B
                         0x3E, 0x41, 0x41, 0x41, 0x22, // C
                         0x7F, 0x41, 0x41, 0x41, 0x3E, // D
                         0x7F, 0x49, 0x49, 0x49, 0x41, // E
                         0x7F, 0x09, 0x09, 0x09, 0x01, // F
                         0x3E, 0x41, 0x41, 0x49, 0x3A, // G
                         0x7F, 0x08, 0x08, 0x08, 0x7F, // H
                         0x00, 0x41, 0x7F, 0x41, 0x00, // I
                         0x30, 0x40, 0x40, 0x40, 0x3F, // J
                         0x7F, 0x08, 0x14, 0x22, 0x41, // K
                         0x7F, 0x40, 0x40, 0x40, 0x40, // L
                         0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
                         0x7F, 0x02, 0x04, 0x08, 0x7F, // N
                         0x3E, 0x41, 0x41, 0x41, 0x3E, // O
                         0x7F, 0x09, 0x09, 0x09, 0x06, // P
                         0x1E, 0x21, 0x21, 0x21, 0x5E, // Q
                         0x7F, 0x09, 0x09, 0x09, 0x76};// R

const int8 FONT2[44][5]={0x26, 0x49, 0x49, 0x49, 0x32, // S
                         0x01, 0x01, 0x7F, 0x01, 0x01, // T
                         0x3F, 0x40, 0x40, 0x40, 0x3F, // U
                         0x1F, 0x20, 0x40, 0x20, 0x1F, // V
                         0x7F, 0x20, 0x10, 0x20, 0x7F, // W
                         0x41, 0x22, 0x1C, 0x22, 0x41, // X
                         0x07, 0x08, 0x70, 0x08, 0x07, // Y
                         0x61, 0x51, 0x49, 0x45, 0x43, // Z
                         0x00, 0x7F, 0x41, 0x00, 0x00, // [
                         0x02, 0x04, 0x08, 0x10, 0x20, // \
                         0x00, 0x00, 0x41, 0x7F, 0x00, // ]
                         0x04, 0x02, 0x01, 0x02, 0x04, // ^
                         0x40, 0x40, 0x40, 0x40, 0x40, // _
                         0x00, 0x01, 0x02, 0x04, 0x00, // `
                         0x20, 0x54, 0x54, 0x54, 0x78, // a
                         0x7F, 0x44, 0x44, 0x44, 0x38, // b
                         0x38, 0x44, 0x44, 0x44, 0x44, // c
                         0x38, 0x44, 0x44, 0x44, 0x7F, // d
                         0x38, 0x54, 0x54, 0x54, 0x18, // e
                         0x04, 0x04, 0x7E, 0x05, 0x05, // f
                         0x08, 0x54, 0x54, 0x54, 0x3C, // g
                         0x7F, 0x08, 0x04, 0x04, 0x78, // h
                         0x00, 0x44, 0x7D, 0x40, 0x00, // i
                         0x20, 0x40, 0x44, 0x3D, 0x00, // j
                         0x7F, 0x10, 0x28, 0x44, 0x00, // k
                         0x00, 0x41, 0x7F, 0x40, 0x00, // l
                         0x7C, 0x04, 0x78, 0x04, 0x78, // m
                         0x7C, 0x08, 0x04, 0x04, 0x78, // n
                         0x38, 0x44, 0x44, 0x44, 0x38, // o
                         0x7C, 0x14, 0x14, 0x14, 0x08, // p
                         0x08, 0x14, 0x14, 0x14, 0x7C, // q
                         0x00, 0x7C, 0x08, 0x04, 0x04, // r
                         0x48, 0x54, 0x54, 0x54, 0x20, // s
                         0x04, 0x04, 0x3F, 0x44, 0x44, // t
                         0x3C, 0x40, 0x40, 0x20, 0x7C, // u
                         0x1C, 0x20, 0x40, 0x20, 0x1C, // v
                         0x3C, 0x40, 0x30, 0x40, 0x3C, // w
                         0x44, 0x28, 0x10, 0x28, 0x44, // x
                         0x0C, 0x50, 0x50, 0x50, 0x3C, // y
                         0x44, 0x64, 0x54, 0x4C, 0x44, // z
                         0x00, 0x08, 0x36, 0x41, 0x41, // {
                         0x00, 0x00, 0x7F, 0x00, 0x00, // |
                         0x41, 0x41, 0x36, 0x08, 0x00, // }
                         0x02, 0x01, 0x02, 0x04, 0x02};// ~
/////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////
// Purpose:       Draw a line on a graphic LCD using Bresenham's
//                line drawing algorithm
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                color - ON or OFF
// Dependencies:  glcd_pixel()
/////////////////////////////////////////////////////////////////////////
#ifdef LARGE_LCD
void glcd_line(int16 x1, int16 y1, int16 x2, int16 y2, int1 color)
#else
void glcd_line(int8 x1, int8 y1, int8 x2, int8 y2, int1 color)
#endif
{
   int16        dy, dx;
   signed int8  addx=1, addy=1;
   signed int16 P, diff;

   #ifdef LARGE_LCD
   int16 i=0;
   dx = abs((signed int16)(x2 - x1));
   dy = abs((signed int16)(y2 - y1));
   #else
   int8 i=0;
   dx = abs((signed int8)(x2 - x1));
   dy = abs((signed int8)(y2 - y1));
   #endif

   if(x1 > x2)
      addx = -1;
   if(y1 > y2)
      addy = -1;

   if(dx >= dy)
   {
      dy *= 2;
      P = dy - dx;
      diff = P - dx;

      for(; i<=dx; ++i)
      {
         glcd_pixel(x1, y1, color);

         if(P < 0)
         {
            P  += dy;
            x1 += addx;
         }
         else
         {
            P  += diff;
            x1 += addx;
            y1 += addy;
         }
      }
   }
   else
   {
      dx *= 2;
      P = dx - dy;
      diff = P - dy;

      for(; i<=dy; ++i)
      {
         glcd_pixel(x1, y1, color);

         if(P < 0)
         {
            P  += dx;
            y1 += addy;
         }
         else
         {
            P  += diff;
            x1 += addx;
            y1 += addy;
         }
      }
   }
}


/////////////////////////////////////////////////////////////////////////
// Purpose:       Draw a rectangle on a graphic LCD
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                fill  - YES or NO
//                color - ON or OFF
// Dependencies:  glcd_pixel(), glcd_line()
/////////////////////////////////////////////////////////////////////////
#ifdef LARGE_LCD
void glcd_rect(int16 x1, int16 y1, int16 x2, int16 y2, int1 fill, int1 color)
#else
void glcd_rect(int8 x1, int8 y1, int8 x2, int8 y2, int1 fill, int1 color)
#endif
{
   if(fill)
   {
      #ifdef LARGE_LCD
      int16 i, xmin, xmax, ymin, ymax;
      #else
      int8  i, xmin, xmax, ymin, ymax;
      #endif

      if(x1 < x2)                            //  Find x min and max
      {
         xmin = x1;
         xmax = x2;
      }
      else
      {
         xmin = x2;
         xmax = x1;
      }

      if(y1 < y2)                            // Find the y min and max
      {
         ymin = y1;
         ymax = y2;
      }
      else
      {
         ymin = y2;
         ymax = y1;
      }

      for(; xmin <= xmax; ++xmin)
      {
         for(i=ymin; i<=ymax; ++i)
         {
            glcd_pixel(xmin, i, color);
         }
      }
   }
   else
   {
      glcd_line(x1, y1, x2, y1, color);      // Draw the 4 sides
      glcd_line(x1, y2, x2, y2, color);
      glcd_line(x1, y1, x1, y2, color);
      glcd_line(x2, y1, x2, y2, color);
   }
}

/////////////////////////////////////////////////////////////////////////
// Purpose:       Draw a bar (wide line) on a graphic LCD
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                width  - The number of pixels wide
//                color - ON or OFF
/////////////////////////////////////////////////////////////////////////
#ifdef LARGE_LCD
void glcd_bar(int16 x1, int16 y1, int16 x2, int16 y2, int8 width, int1 color)
#else
void glcd_bar(int8 x1, int8 y1, int8 x2, int8 y2, int8 width, int1 color)
#endif
{
   int8         half_width;
   signed int16 dy, dx;
   signed int8  addx=1, addy=1, j;
   signed int16 P, diff, c1, c2;

   #ifdef LARGE_LCD
   int16 i=0;
   dx = abs((signed int16)(x2 - x1));
   dy = abs((signed int16)(y2 - y1));
   #else
   int8 i=0;
   dx = abs((signed int8)(x2 - x1));
   dy = abs((signed int8)(y2 - y1));
   #endif

   half_width = width/2;
   c1 = -(dx*x1 + dy*y1);
   c2 = -(dx*x2 + dy*y2);

   if(x1 > x2)
   {
      signed int16 temp;
      temp = c1;
      c1 = c2;
      c2 = temp;
      addx = -1;
   }
   if(y1 > y2)
   {
      signed int16 temp;
      temp = c1;
      c1 = c2;
      c2 = temp;
      addy = -1;
   }

   if(dx >= dy)
   {
      P = 2*dy - dx;
      diff = P - dx;

      for(i=0; i<=dx; ++i)
      {
         for(j=-half_width; j<half_width+width%2; ++j)
         {
            #ifdef LARGE_LCD
            int16 temp;
            #else
            int8 temp;
            #endif

            temp = dx*x1+dy*(y1+j);    // Use more RAM to increase speed
            if(temp+c1 >= 0 && temp+c2 <=0)
               glcd_pixel(x1, y1+j, color);
         }
         if(P < 0)
         {
            P  += 2*dy;
            x1 += addx;
         }
         else
         {
            P  += diff;
            x1 += addx;
            y1 += addy;
         }
      }
   }
   else
   {
      P = 2*dx - dy;
      diff = P - dy;

      for(i=0; i<=dy; ++i)
      {
         if(P < 0)
         {
            P  += 2*dx;
            y1 += addy;
         }
         else
         {
            P  += diff;
            x1 += addx;
            y1 += addy;
         }
         for(j=-half_width; j<half_width+width%2; ++j)
         {
            #ifdef LARGE_LCD
            int16 temp;
            #else
            int8 temp;
            #endif

            temp = dx*x1+dy*(y1+j);    // Use more RAM to increase speed
            if(temp+c1 >= 0 && temp+c2 <=0)
               glcd_pixel(x1+j, y1, color);
         }
      }
   }
}


/////////////////////////////////////////////////////////////////////////
// Purpose:       Draw a circle on a graphic LCD
// Inputs:        (x,y) - the center of the circle
//                radius - the radius of the circle
//                fill - YES or NO
//                color - ON or OFF
/////////////////////////////////////////////////////////////////////////
#ifdef LARGE_LCD
void glcd_circle(int16 x, int16 y, int16 radius, int1 fill, int1 color)
#else
void glcd_circle(int8 x, int8 y, int8 radius, int1 fill, int1 color)
#endif
{
   #ifdef LARGE_LCD
   signed int16 a, b, P;
   #else
   signed int8  a, b, P;
   #endif

   a = 0;
   b = radius;
   P = 1 - radius;

   do
   {
      if(fill)
      {
         glcd_line(x-a, y+b, x+a, y+b, color);
         glcd_line(x-a, y-b, x+a, y-b, color);
         glcd_line(x-b, y+a, x+b, y+a, color);
         glcd_line(x-b, y-a, x+b, y-a, color);
      }
      else
      {
         glcd_pixel(a+x, b+y, color);
         glcd_pixel(b+x, a+y, color);
         glcd_pixel(x-a, b+y, color);
         glcd_pixel(x-b, a+y, color);
         glcd_pixel(b+x, y-a, color);
         glcd_pixel(a+x, y-b, color);
         glcd_pixel(x-a, y-b, color);
         glcd_pixel(x-b, y-a, color);
      }

      if(P < 0)
         P += 3 + 2 * a++;
      else
         P += 5 + 2 * (a++ - b--);
    } while(a <= b);
}


/////////////////////////////////////////////////////////////////////////
// Purpose:       Write text on a graphic LCD
// Inputs:        (x,y) - The upper left coordinate of the first letter
//                textptr - A pointer to an array of text to display
//                size - The size of the text: 1 = 5x7, 2 = 10x14, ...
//                color - ON or OFF
/////////////////////////////////////////////////////////////////////////
#ifdef LARGE_LCD
void glcd_text57(int16 x, int16 y, char* textptr, int8 size, int1 color)
#else
void glcd_text57(int8 x, int8 y, char* textptr, int8 size, int1 color)
#endif
{
   int8 j, k, l, m;                       // Loop counters
   int8 pixelData[5];                     // Stores character data

   for(; *textptr != '\0'; ++textptr, ++x)// Loop through the passed string
   {
      if(*textptr < 'S') // Checks if the letter is in the first font array
         memcpy(pixelData, FONT[*textptr - ' '], 5);
      else if(*textptr <= '~') // Check if the letter is in the second font array
         memcpy(pixelData, FONT2[*textptr - 'S'], 5);
      else
         memcpy(pixelData, FONT[0], 5);   // Default to space

      // Handles newline and carriage returns
      switch(*textptr)
      {
         case '\n':
            y += 7*size + 1;
            continue;
         case '\r':
            x = 0;
            continue;
      }

      if(x+5*size >= GLCD_WIDTH)          // Performs character wrapping
      {
         x = 0;                           // Set x at far left position
         y += 7*size + 1;                 // Set y at next position down
      }
      for(j=0; j<5; ++j, x+=size)         // Loop through character byte data
      {
         for(k=0; k < 7; ++k)             // Loop through the vertical pixels
         {
            if(bit_test(pixelData[j], k)) // Check if the pixel should be set
            {
               for(l=0; l < size; ++l)    // These two loops change the
               {                          // character's size
                  for(m=0; m < size; ++m)
                  {
                     glcd_pixel(x+m, y+k*size+l, color); // Draws the pixel
                  }
               }
            }
         }
      }
   }
}

#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


También utilizaremos la librería “HDM64GS12.c” obtenida del mismo directorio que la anterior.

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////                           HDM64GS12.c                           ////
////                                                                 ////
//// This file contains drivers for using a Hantronix HDM64GS12 with ////
//// a KS0108 display controller. The HDM64GS12 is 128 by 64 pixels. ////
//// The driver treats the upper left pixel as (0,0).                ////
////                                                                 ////
//// Use #define FAST_GLCD if the target chip has at least 1k of RAM ////
//// to decrease the time it takes to update the display.            ////
//// glcd_update() must then be called to update the display after   ////
//// changing the pixel information.                                 ////
//// See ex_glcd.c for suggested usage.                              ////
//// See KS0108.c for controlling a single 64 by 64 display          ////
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// LCD Pin connections:                                            ////
//// (These can be changed as needed in the following defines).      ////
////  * 1: VSS is connected to GND                                   ////
////  * 2: VDD is connected to +5V                                   ////
////  * 3: V0  - LCD operating voltage (Constrast adjustment)        ////
////  * 4: D/I - Data or Instruction is connected to B2              ////
////  * 5: R/W - Read or Write is connected to B4                    ////
////  * 6: Enable is connected to B5                                 ////
////  *7-14: Data Bus 0 to 7 is connected to port d                  ////
////  *15: Chip Select 1 is connected to B0                          ////
////  *16: Chip Select 2 is connected to B1                          ////
////  *17: Reset is connected to C0                                  ////
////  *18: Negative voltage is also connected to the 20k Ohm POT     ////
////  *19: Positive voltage for LED backlight is connected to +5V    ////
////  *20: Negavtive voltage for LED backlight is connected to GND   ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
////  glcd_init(mode)                                                ////
////     * Must be called before any other function.                 ////
////       - mode can be ON or OFF to turn the LCD on or off         ////
////                                                                 ////
////  glcd_pixel(x,y,color)                                          ////
////     * Sets the pixel to the given color.                        ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_fillScreen(color)                                         ////
////     * Fills the entire LCD with the given color.                ////
////       - color can be ON or OFF                                  ////
////                                                                 ////
////  glcd_update()                                                  ////
////     * Write the display data stored in RAM to the LCD           ////
////     * Only available if FAST_GLCD is defined                    ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996, 2004 Custom Computer Services        ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////



#ifndef HDM64GS12
#define HDM64GS12

#ifndef GLCD_WIDTH
#define GLCD_WIDTH   128
#endif

#ifndef GLCD_CS1
#define GLCD_CS1     PIN_B0   // Chip Selection 1
#endif

#ifndef GLCD_CS2
#define GLCD_CS2     PIN_B1   // Chip Selection 2
#endif

#ifndef GLCD_DI
#define GLCD_DI      PIN_B2   // Data or Instruction input
#endif

#ifndef GLCD_RW
#define GLCD_RW      PIN_B4   // Read/Write
#endif

#ifndef GLCD_E
#define GLCD_E       PIN_B5   // Enable
#endif

#ifndef GLCD_RST
#define GLCD_RST     PIN_C0   // Reset
#endif

#define GLCD_LEFT    0
#define GLCD_RIGHT   1

#ifndef ON
#define ON           1
#endif

#ifndef OFF
#define OFF          0
#endif

/////////////////////////////////////////////////////////////////////////
// Function Prototypes
/////////////////////////////////////////////////////////////////////////
void glcd_init(int1 mode);
void glcd_pixel(int8 x, int8 y, int1 color);
void glcd_fillScreen(int1 color);
void glcd_writeByte(int1 side, BYTE data);
BYTE glcd_readByte(int1 side);
void glcd_update();
/////////////////////////////////////////////////////////////////////////

#ifdef FAST_GLCD
struct
{
   int8 left[512];
   int8 right[512];
} displayData;
#endif


// Purpose:       Initialize the LCD.
//                Call before using any other LCD function.
// Inputs:        OFF - Turns the LCD off
//                ON  - Turns the LCD on
void glcd_init(int1 mode)
{
   // Initialze some pins
   output_high(GLCD_RST);
   output_low(GLCD_E);
   output_low(GLCD_CS1);
   output_low(GLCD_CS2);

   output_low(GLCD_DI);                 // Set for instruction
   glcd_writeByte(GLCD_LEFT,  0xC0);    // Specify first RAM line at the top
   glcd_writeByte(GLCD_RIGHT, 0xC0);    //   of the screen
   glcd_writeByte(GLCD_LEFT,  0x40);    // Set the column address to 0
   glcd_writeByte(GLCD_RIGHT, 0x40);
   glcd_writeByte(GLCD_LEFT,  0xB8);    // Set the page address to 0
   glcd_writeByte(GLCD_RIGHT, 0xB8);

   if(mode == ON)
   {
      glcd_writeByte(GLCD_LEFT,  0x3F); // Turn the display on
      glcd_writeByte(GLCD_RIGHT, 0x3F);
   }
   else
   {
      glcd_writeByte(GLCD_LEFT,  0x3E); // Turn the display off
      glcd_writeByte(GLCD_RIGHT, 0x3E);
   }

   glcd_fillScreen(OFF);                // Clear the display

   #ifdef FAST_GLCD
   glcd_update();
   #endif
}


// Purpose:    Update the LCD with data from the display arrays
#ifdef FAST_GLCD
void glcd_update()
{
   int8 i, j;
   int8 *p1, *p2;

   p1 = displayData.left;
   p2 = displayData.right;

   // Loop through the vertical pages
   for(i = 0; i < 8; ++i)
   {
      output_low(GLCD_DI);                      // Set for instruction
      glcd_writeByte(GLCD_LEFT, 0x40);          // Set horizontal address to 0
      glcd_writeByte(GLCD_RIGHT, 0x40);
      glcd_writeByte(GLCD_LEFT, i | 0xB8);      // Set page address
      glcd_writeByte(GLCD_RIGHT, i | 0xB8);
      output_high(GLCD_DI);                     // Set for data

      // Loop through the horizontal sections
      for(j = 0; j < 64; ++j)
      {
         glcd_writeByte(GLCD_LEFT, *p1++);      // Turn pixels on or off
         glcd_writeByte(GLCD_RIGHT, *p2++);     // Turn pixels on or off
      }
   }
}
#endif


// Purpose:    Turn a pixel on a graphic LCD on or off
// Inputs:     1) x - the x coordinate of the pixel
//             2) y - the y coordinate of the pixel
//             3) color - ON or OFF
void glcd_pixel(int8 x, int8 y, int1 color)
#ifdef FAST_GLCD
{
   int8* p;
   int16 temp;
   temp =  y/8;
   temp *= 64;
   temp += x;

   if(x > 63)
   {
      p = displayData.right + temp - 64;
   }
   else
   {
      p = displayData.left + temp;
   }

   if(color)
   {
      bit_set(*p, y%8);
   }
   else
   {
      bit_clear(*p, y%8);
   }
}
#else
{
   BYTE data;
   int1 side = GLCD_LEFT;  // Stores which chip to use on the LCD

   if(x > 63)              // Check for first or second display area
   {
      x -= 64;
      side = GLCD_RIGHT;
   }

   output_low(GLCD_DI);                         // Set for instruction
   bit_clear(x,7);                              // Clear the MSB. Part of an instruction code
   bit_set(x,6);                                // Set bit 6. Also part of an instruction code
   glcd_writeByte(side, x);                     // Set the horizontal address
   glcd_writeByte(side, (y/8 & 0xBF) | 0xB8);   // Set the vertical page address
   output_high(GLCD_DI);                        // Set for data
   glcd_readByte(side);                         // Need two reads to get data
   data = glcd_readByte(side);                  //  at new address

   if(color == ON)
      bit_set(data, y%8);        // Turn the pixel on
   else                          // or
      bit_clear(data, y%8);      // turn the pixel off

   output_low(GLCD_DI);          // Set for instruction
   glcd_writeByte(side, x);      // Set the horizontal address
   output_high(GLCD_DI);         // Set for data
   glcd_writeByte(side, data);   // Write the pixel data
}
#endif


// Purpose:    Fill the LCD screen with the passed in color
// Inputs:     ON  - turn all the pixels on
//             OFF - turn all the pixels off
void glcd_fillScreen(int1 color)
#ifdef FAST_GLCD
{
   int8  data;
   int8  *p1, *p2;
   int16 i;

   p1 = displayData.left;
   p2 = displayData.right;
   data = 0xFF * color;

   for(i=0; i<512; ++i)
   {
      *p1++ = data;
      *p2++ = data;
   }
}
#else
{
   int8 i, j;

   // Loop through the vertical pages
   for(i = 0; i < 8; ++i)
   {
      output_low(GLCD_DI);                      // Set for instruction
      glcd_writeByte(GLCD_LEFT, 0b01000000);    // Set horizontal address to 0
      glcd_writeByte(GLCD_RIGHT, 0b01000000);
      glcd_writeByte(GLCD_LEFT, i | 0b10111000);// Set page address
      glcd_writeByte(GLCD_RIGHT, i | 0b10111000);
      output_high(GLCD_DI);                     // Set for data

      // Loop through the horizontal sections
      for(j = 0; j < 64; ++j)
      {
         glcd_writeByte(GLCD_LEFT, 0xFF*color);  // Turn pixels on or off
         glcd_writeByte(GLCD_RIGHT, 0xFF*color); // Turn pixels on or off
      }
   }
}
#endif


// Purpose:    Write a byte of data to the specified chip
// Inputs:     1) chipSelect - which chip to write the data to
//             2) data - the byte of data to write
void glcd_writeByte(int1 side, BYTE data)
{
   if(side)                   // Choose which side to write to
      output_high(GLCD_CS2);
   else
      output_high(GLCD_CS1);

   output_low(GLCD_RW);       // Set for writing
   output_d(data);            // Put the data on the port
   delay_cycles(1);
   output_high(GLCD_E);       // Pulse the enable pin
   delay_cycles(5);
   output_low(GLCD_E);

   output_low(GLCD_CS1);      // Reset the chip select lines
   output_low(GLCD_CS2);
}


// Purpose:    Reads a byte of data from the specified chip
// Ouputs:     A byte of data read from the chip
BYTE glcd_readByte(int1 side)
{
   BYTE data;                 // Stores the data read from the LCD

   set_tris_d(0xFF);          // Set port d to input
   output_high(GLCD_RW);      // Set for reading

   if(side)                   // Choose which side to write to
      output_high(GLCD_CS2);
   else
      output_high(GLCD_CS1);

   delay_cycles(1);
   output_high(GLCD_E);       // Pulse the enable pin
   delay_cycles(4);
   data = input_d();          // Get the data from the display's output register
   output_low(GLCD_E);

   output_low(GLCD_CS1);      // Reset the chip select lines
   output_low(GLCD_CS2);
   return data;               // Return the read data
}

#endif


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Y Finalmente el programa principal.


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////
//   AUTOR: José Antonio Pelayo                                        NOVIEMBRE/2011
////////////////////////////////////////////////////////////////////////////////////
//   PROGRAMA:    ESTUDIO LCD gráfico                   VERSIÓN:    1.0
//   DISPOSITIVO: PIC 18F4550                           COMPILADOR:    CCS vs4.109
//   Entorno IDE: MPLAB                                 SIMULADOR:    Proteus 7.7 sp2
//   TARJETA DE APLICACIÓN: ___                         DEBUGGER:    ICD3

/////////////////////////////////////////////////////////////////////////////////                            
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
//       
//       
//        
//        .Utilizar LCD gráfico, Hacer un Voltímetro
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
     
////////////////////////////////////////////////////////////////////////////////////
// CABECERA ////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
#include <c:\h\18F4550.h>
//#fuses INTHS                 //Selecciona el oscilador interno
#FUSES HS                   //External clock
#FUSES MCLR                   //Master Clear pin enabled
#use delay(clock=20000000)
#include <HDM64GS12.c>
#include <GRAPHICS.c>
#include <math.h>
#include <stdio.h>
#use fast_io(b)

#use fast_io(c)


////////////////////////////////////////////////////////////////////////////////////
// VARIABLES GLOBALES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
                char texto[]="Vol.";
    char cinco[]="_5";
    char cuatro[]="_4";
    char tres[]="_3";
    char dos[]="_2";
    char uno[]="_1";
    char cero[]="0";
    char nombre[]="Jose A. Pelayo";
    char voltios[32];
    int voltref,voltaje2,voltaje3;
    const float v_max=20.06;
    float voltaje;
    long int valor;
    const long int escala=1023;//el fondo de escala depende de los bits del conversor
////////////////////////////////////////////////////////////////////////////////////


void main()

{
  setup_adc(ADC_CLOCK_DIV_8);//selecciona el reloj de conversion
  setup_adc_ports(AN0);//configura el conversor
  set_adc_channel(0);//selecciona canal.
  glcd_init(on);

 // cubo//
  glcd_line(80, 40, 90, 30, on);
  glcd_line(100, 60, 110, 50, on);
  glcd_line(100, 40, 110, 30, on);
  glcd_line(90, 30, 110, 30, on);
  glcd_line(110, 30, 110, 50, on);
  glcd_rect(80, 40, 100, 60, yes, on);
  glcd_rect(81, 41, 99, 59, yes, off);
 //Escribo el texto que contiene la variable mensaje
glcd_text57(85,3,texto,1,on); 

glcd_rect(35, 0, 120, 15, no, on);
//valores.
glcd_text57(15,3,cinco,1,on);
glcd_text57(15,13,cuatro,1,on);
glcd_text57(15,23,tres,1,on);
glcd_text57(15,33,dos,1,on);
glcd_text57(15,43,uno,1,on);
glcd_text57(20,53,cero,1,on);
glcd_text57(40,3,voltios,1,off);
glcd_rect(0,0,12, 64, yes,off);
sprintf(voltios,"%1.3f", voltaje);  
glcd_text57(40,3,voltios,1,on);
glcd_rect(2,8,11,60,no,on);//contorno
glcd_rect(3,voltref, 10,59, yes,on);
glcd_text57(35,19,nombre,1,on);

 while(true)

{

delay_ms(50);
voltaje2=voltaje3;
valor=read_adc();//conversion AD
voltaje=(valor*v_max)/escala;
voltaje3=read_adc();
voltref=59-(voltaje*10);
//leo en entero para el indicador


//rectángulo de referencia.
if((voltaje2>voltaje3+(voltaje3/70))||(voltaje2<voltaje3-(voltaje3/70)) )//que solo refresque la pantalla al cambio de la entrada analógica con rango de error
{
//Escribo el texto que contiene la variable mensaje
glcd_text57(85,3,texto,1,on); 
glcd_rect(35, 0, 120, 15, no, on);
glcd_text57(40,3,voltios,1,off);
glcd_rect(0,0,12, 64, yes,off);
sprintf(voltios,"%1.3f", voltaje);  
glcd_text57(40,3,voltios,1,on);
glcd_rect(2,8,11,60,no,on);//contorno
glcd_rect(3,voltref, 10,59, yes,on);
}
 }
}


Ahora ya solo queda simularlo en Proteus antes de pasar a la tarjeta .
















Y finalmente la prueba en la tarjeta.





                                    DESCARGA PROGRAMA