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.