Hola a todos, en esta práctica os voy a enseñar cómo
escribir en un LCD gráfico, que nada tiene que ver con un alfanumérico, ya que
el gráfico funciona a modo de mapa de bits, por lo que podemos dibujar a
nuestro antojo, mientras que en el alfanumérico esta cuestión es imposible.
En primer lugar deciros que vamos a utilizar el famoso
18f4550 para controlarlo, y nos valdremos de diferentes librerías, que me
vienen dentro del compilador CCSC, o “C compiler”
La parte importante de la práctica es desarrollar un
conversor AD pero, como estamos usando un LCD gráfico vamos a aprovechar para
dibujar cualquier cosa, bien sea líneas, círculos, etc.
Esto se verá más adelante. Por otro lado, es importante
saber que nuestro LCD gráfico tiene una resolución de 128x64 y que, como ya
dije sobre el LCD anterior, tiene un microcontrolador incorporado, el ks0108.
Gracias al uso de ciertas librerías, concretamente 2, la “HDM64GS12.c”
y “graphics.c” podemos tener un mayor control del dispositivo, y mediante unas
cuantas sentencias, podemos dibujar de una manera bastante sencilla.
Os diré que ambas librerías me venían en la ruta ““C:\Program
Files\PICC\Drivers”, por si no la encontráis. Obviamente tenéis que tener C
compiler instalado.
Aquí os adjunto las librerías:
En primer lugar la HDM64GS12.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////
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 en segundo lugar la librería “graphics.c”
/////////////////////////////////////////////////////////////////////////
////
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
{
#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
{
#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
Aquí os dejo el programa principal.
////////////////////////////////////////////////////////////////////////////////////
// AUTOR: Gabri Allende ENERO/2011
////////////////////////////////////////////////////////////////////////////////////
// PROGRAMA: Lcd grafico VERSIÓN: 1.0
// DISPOSITIVO: PIC 18F4550 COMPILADOR: CCSc
// Entorno IDE: MPLAB SIMULADOR: proteus
// TARJETA DE APLICACIÓN: DEBUGGER: ICD3
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// VOLTIMETRO
// DIBUJOS (TRIANGULO)
// TEXTO (GABI)
//
//
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// CABECERA ////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
#include
//#fuses INTHS //OSCILADOR INTERNO NO LO PONGO
#FUSES HS //RELOJ EXTERNO
#FUSES MCLR //MASTER CLEAR ATIVADO
#use delay(clock=20000000)
#include
#include
#use fast_io(b)
#use fast_io(c)
////////////////////////////////////////////////////////////////////////////////////
// VARIABLES GLOBALES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
char texto[]="Voltaje";
char nombre[]="GABI";
char voltios[32];
int voltref,voltaje2,voltaje3;
const float v_max=20.06;
float voltaje;
long int valor;
const long int escala=1023;//Depende de los bits del conver
////////////////////////////////////////////////////////////////////////////////////
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);
//triangulo//
glcd_line(45, 55, 110, 55, on); //LADO INFERIOR
glcd_line(77, 5, 110, 55, on); //LADO Derecho
glcd_line(77, 5, 45, 55, on); //LADO IZQUIERDO
glcd_circle(77, 35, 15, on, on); //CIRCULO
//Variable mensaje
glcd_text57(85,3,texto,1,on); //VOLtaje
sprintf(voltios,"%1.3f", voltaje);
glcd_text57(40,3,voltios,1,on);
glcd_text57(65,30,nombre,1,off); //"GABI"
while(true)
{
delay_ms(50);
voltaje2=voltaje3;
valor=read_adc();//conversion AD
voltaje=(valor*v_max)/escala;
voltaje3=read_adc();
voltref=59-(voltaje*10);
if((voltaje2>voltaje3+(voltaje3/70))||(voltaje2{
glcd_text57(85,3,texto,1,on);
glcd_text57(40,3,voltios,1,off);
sprintf(voltios,"%1.3f", voltaje);
glcd_text57(40,3,voltios,1,on);
}
}
}
Aquí os dejo la simulación en proteus para que veais como queda:
////////////////////////////////////////////////////////////////////////////////////
// AUTOR: Gabri Allende ENERO/2011
////////////////////////////////////////////////////////////////////////////////////
// PROGRAMA: Lcd grafico VERSIÓN: 1.0
// DISPOSITIVO: PIC 18F4550 COMPILADOR: CCSc
// Entorno IDE: MPLAB SIMULADOR: proteus
// TARJETA DE APLICACIÓN: DEBUGGER: ICD3
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// VOLTIMETRO
// DIBUJOS (TRIANGULO)
// TEXTO (GABI)
//
//
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// CABECERA ////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
#include
//#fuses INTHS //OSCILADOR INTERNO NO LO PONGO
#FUSES HS //RELOJ EXTERNO
#FUSES MCLR //MASTER CLEAR ATIVADO
#use delay(clock=20000000)
#include
#include
#use fast_io(b)
#use fast_io(c)
////////////////////////////////////////////////////////////////////////////////////
// VARIABLES GLOBALES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
char texto[]="Voltaje";
char nombre[]="GABI";
char voltios[32];
int voltref,voltaje2,voltaje3;
const float v_max=20.06;
float voltaje;
long int valor;
const long int escala=1023;//Depende de los bits del conver
////////////////////////////////////////////////////////////////////////////////////
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);
//triangulo//
glcd_line(45, 55, 110, 55, on); //LADO INFERIOR
glcd_line(77, 5, 110, 55, on); //LADO Derecho
glcd_line(77, 5, 45, 55, on); //LADO IZQUIERDO
glcd_circle(77, 35, 15, on, on); //CIRCULO
//Variable mensaje
glcd_text57(85,3,texto,1,on); //VOLtaje
sprintf(voltios,"%1.3f", voltaje);
glcd_text57(40,3,voltios,1,on);
glcd_text57(65,30,nombre,1,off); //"GABI"
while(true)
{
delay_ms(50);
voltaje2=voltaje3;
valor=read_adc();//conversion AD
voltaje=(valor*v_max)/escala;
voltaje3=read_adc();
voltref=59-(voltaje*10);
if((voltaje2>voltaje3+(voltaje3/70))||(voltaje2
glcd_text57(85,3,texto,1,on);
glcd_text57(40,3,voltios,1,off);
sprintf(voltios,"%1.3f", voltaje);
glcd_text57(40,3,voltios,1,on);
}
}
}
Como veis el dibujo es bastante sencillo, un triángulo creado con 3 líneas, además de eso, he creado un círculo en su interior y ,dentro del círculo un texto que contiene mi nombre, por último el conversor en la parte superior y listo.
Es importante tener en cuenta que yo he trabajado en una placa entrenadora, como este blog en sí es una memoria de cada una de mis prácticas creo que es importante decir que, hay que conectar un cable enrte ra0 y la salida analógica de voltaje para que funcione. (Lo veréis en la imagen que os adjunto ahora, junto con el vídeo demostrativo) .Con esto ya tendríamos nuestro conversor hecho en un LCD gráfico.
Cable de RA0 al Voltaje analógico:
Foto en mejor definición:
Espero que os haya servido de ayuda ,un saludo!
DESCARGAR AQUÍ EL PROGRAMA
Es importante tener en cuenta que yo he trabajado en una placa entrenadora, como este blog en sí es una memoria de cada una de mis prácticas creo que es importante decir que, hay que conectar un cable enrte ra0 y la salida analógica de voltaje para que funcione. (Lo veréis en la imagen que os adjunto ahora, junto con el vídeo demostrativo) .Con esto ya tendríamos nuestro conversor hecho en un LCD gráfico.
Cable de RA0 al Voltaje analógico:
Vídeo demostrativo del Conversor AD.
Foto en mejor definición:
Espero que os haya servido de ayuda ,un saludo!
DESCARGAR AQUÍ EL PROGRAMA
gracias.. me es de gran ayuda tu aporte
ResponderEliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarEste comentario ha sido eliminado por el autor.
ResponderEliminar