/**************************************************************************
* Libreria para manejo de LCD en 4 u 8 bits para compilador HiTech *
***************************************************************************
***************************************************************************
* Basado en el mapa de memoria de los display WinStar y los comandos del *
* HD44780. *
* Sirve para display 16x1, 16x2 y 16x4 *
***************************************************************************
***************************************************************************
* *
* Antes de incluir este archivo en nuestro programa hay que definir *
* algunos parametros. Estos son *
* *
* _XTAL_FREQ (es necesario para los delay utilizados internamente) *
* LcdDataPort (el puerto que se utilizara para los datos) *
* LcdControlPort (el puerto que se utilizara para los bits de control) *
* LcdRWBit (el numero de bit que se utilizara para RW) *
* LcdRSBit (el numero de bit que se utilizara para RS) *
* LcdENBit (el numero de bit que se utilizara para EN) *
* *
* En el caso de querer usar protocolo de 4 Bits tambien hay que definir *
* *
* LcdD4 (el numero de bit que sera D4 hacia el display) *
* *
* *
* LcdD4 solo puede ser 0 o 4. Si es 0 se utiliza el nibble bajo de *
* LcdDataPort para enviar los datos al display. Si es 1 se utiliza *
* el nibble alto. *
* Si no esta definido LcdD4, se usa protocolo de 8 bits. En este caso *
* se usan los 8 bits de LcdDataPort para enviar los datos al display. *
* *
***************************************************************************
***************************************************************************
* *
* En esta libreria se encuentran las siguientes funciones *
* *
* InitLcd() (inicializa del display) *
* ClearLcd() (borra el display y se posiciona en el inicio)*
* GotoxyLcd(char,char) (posiciona el cursor en el lugar indicado) *
* LcdOn() (enciende el display) *
* LcdOff() (apaga el display) *
* SetCursorLcd(char,char) (configura el cursor) *
* WriteCharLcd(char) (envia un caracter al display) *
* WriteStrLcd(char*) (envia un String al display) *
* *
* El parametro de la funcion anterior puede ser un puntero a un String *
* o el propio String. *
* *
* ReadBytLcd() (devuelve el byte leido en la posicion actual)*
* WriteByteLcd(char,char) (envia un byte al display) *
* *
* El segundo parametro de la funcion anterior puede ser 0 o 1 y es el *
* valor que va a tomar el pin RS. *
* Por eso, esta funcion puede ser utilizada para enviar una instruccion *
* o un caracter al display. *
* *
* Tambien se encuentran definidos los parametros CursorOn, CursorOff, *
* CursorBlinkOn y CursorBlinkOff que son utilizados por la funcion *
* SetCursorLcd(char). *
* Tambien estan definidos los parametros ShiftDisplay, ShiftCursor, *
* ShiftRight y ShiftLeft que son utilizados por la funcion LcdShift(char) *
***************************************************************************
***************************************************************************
* *
* Luego de utilizar las funciones, el puerto utilizado para LcdDataPort *
* retorna a su estado original. *
* Es decir que el registro TRIS vuelve a configurarse como estaba antes *
* de utilizar las funciones. Y sobre el puerto vuelve a aparecer el mismo *
* dato que habia antes de utilizar las funciones para el display *
* *
***************************************************************************
* Ejemplo de configuracion y utilizacion
#define _XTAL_FREQ 10000000 // Cristal 10MHz
#define LcdControlPort PORTC // Uso el puerto A para los bits de control
#define LcdRWBit 0 // El bit 0 del puerto A para RW
#define LcdRSBit 1 // El bit 0 del puerto A para RS
#define LcdENBit 1 // El bit 0 del puerto A para EN
#define LcdDataPort PORTB // Uso el puerto B para los datos
//#define LcdD4 4 // Solo utilizar para protocolo de 4 Bits
#include "SuperLcd.C" // Incluimos nuestra libreria
void main(void)
{
const char * pantalla = "Mundo";
.....
.....
.....
InitLcd();
WriteStrLcd ("Hola"); // escribe en la primer linea la palabra Hola
GotoxyLcd (1,2);
WriteStrLcd (pantalla); // escribe en la segunda linea la palabra apuntada por la variable pantalla
SetCursorLcd (CursorOff | CursorBlinkOn); // apaga el cursor, y lo hace parpadear
LcdShift (ShiftDisplay | ShiftRight); // dezplaza el display hacia la derecha (texto a la izquierda)
}
*/
#if defined (LcdControlPort) && defined (LcdRWBit) && defined (LcdRSBit) && defined (LcdENBit) &&\
defined (LcdDataPort)
#if defined (LcdD4) //Define el bit de menos peso del nibble (puede ser 0 o 4)
#define Protocolo4Bits
#if (LcdD4 != 0) && (LcdD4 != 4)
#error Mal definido D4 del LCD
#endif
#endif
#define CursorOff 0b1100
#define CursorOn 0b1110
#define CursorBlinkOff 0b1100
#define CursorBlinkOn 0b1101
#define ShiftDisplay 0b11000
#define ShiftCursor 0b10000
#define ShiftRight 0b10100
#define ShiftLeft 0b10000
unsigned char Mascara;
volatile bit TRISLcdRW @ (unsigned)&LcdControlPort*8 +0x80*8 +LcdRWBit;
volatile bit TRISLcdRS @ (unsigned)&LcdControlPort*8 +0x80*8 +LcdRSBit;
volatile bit TRISLcdEN @ (unsigned)&LcdControlPort*8 +0x80*8 +LcdENBit;
volatile bit LcdRW @ (unsigned)&LcdControlPort*8 +LcdRWBit;
volatile bit LcdRS @ (unsigned)&LcdControlPort*8 +LcdRSBit;
volatile bit LcdEN @ (unsigned)&LcdControlPort*8 +LcdENBit;
volatile char TRISLcdData @ (unsigned)&LcdDataPort + 0x80;
unsigned char ReadByteLcd(void)
{
unsigned char high, low;
unsigned char TRISAnterior;
unsigned char DatoAnterior;
unsigned char DatoLeido;
DatoAnterior = LcdDataPort;
TRISAnterior = TRISLcdData;
#ifdef Protocolo4Bits
#if (LcdD4 == 0)
TRISLcdData |= 0x0F;
#elif (LcdD4 == 4)
TRISLcdData |= 0xF0;
#endif
#else
TRISLcdData = 0xFF;
#endif
LcdRS = 0;
LcdRW = 1;
LcdEN = 1;
__delay_us (1);
#ifdef Protocolo4Bits
high = LcdDataPort;
LcdEN = 0;
__delay_us (1);
LcdEN = 1;
__delay_us (1);
low = LcdDataPort;
LcdEN = 0;
#if (LcdD4 == 0)
high = high<<4;
low = low & 0x0F;
#elif (LcdD4 == 4)
high = high & 0xF0;
low = low>>4;
#endif
DatoLeido = high + low;
#else
DatoLeido = LcdDataPort;
LcdEN = 0;
#endif
TRISLcdData = TRISAnterior;
LcdDataPort = DatoAnterior;
return DatoLeido;
}
void WriteNibbleLcd (unsigned char Data)
{
#ifdef Protocolo4Bits
#if (LcdD4 == 0)
LcdDataPort = (LcdDataPort & 0xF0) + (Data>>4);
#elif (LcdD4 == 4)
LcdDataPort = (LcdDataPort & 0x0F) + (Data & 0xF0);
#endif
#else
LcdDataPort = Data;
#endif
LcdEN = 1;
__delay_us(2);
LcdEN = 0;
}
void WriteByteLcd(unsigned char Data, unsigned char dir)
{
unsigned char TRISAnterior;
unsigned char DatoAnterior;
DatoAnterior = LcdDataPort;
TRISAnterior = TRISLcdData;
TRISLcdData &= Mascara;
while ((ReadByteLcd() & 128) == 128);
__delay_us(10);
LcdRS = (bit)dir;
LcdRW = 0;
#ifdef Protocolo4Bits //Si uso 4 bits separa el byte en 2
WriteNibbleLcd(Data);
WriteNibbleLcd(Data<<4);
#else
WriteNibbleLcd(Data); //Si uso 8 bits envio el byte entero
#endif
TRISLcdData = TRISAnterior;
LcdDataPort = DatoAnterior;
}
void WriteStrLcd (const char *palabra)
{
while (*palabra)
WriteByteLcd ((*palabra++),1);
}
void GotoxyLcd (unsigned char x, unsigned char y)
{
if (y == 1) y = 0;
else
if (y == 2) y = 0x40;
else
if (y == 3) y = 0x10;
else
if (y == 4) y = 0x50;
x--;
WriteByteLcd (((y+x)|0x80),0);
}
#define LcdShift(Estado) WriteByteLcd (Estado,0)
#define SetCursorLcd(Estado) WriteByteLcd (Estado,0)
#define WriteCharLcd(letra) WriteByteLcd (letra,1)
#define LcdOn() WriteByteLcd(0x0C,0)
#define LcdOff() WriteByteLcd(0x08,0)
#define ClearLcd() WriteByteLcd(0x01,0)
void InitLcd(void)
{
unsigned char TRISAnterior;
unsigned char DatoAnterior;
unsigned char Contador;
#ifdef Protocolo4Bits
#if (LcdD4 == 0)
Mascara = 0xF0;
#elif (LcdD4 == 4)
Mascara = 0x0F;
#endif
#else
Mascara = 0;
#endif
TRISLcdRW = 0;
TRISLcdRS = 0;
TRISLcdEN = 0;
LcdEN = 0;
TRISAnterior = TRISLcdData;
DatoAnterior = LcdDataPort;
LcdRW = 0;
LcdRS = 0;
TRISLcdData &= Mascara;
__delay_ms (15);
for (Contador= 3; Contador > 0; Contador--)
{
WriteNibbleLcd (0x30);
__delay_ms (5);
}
#ifdef Protocolo4Bits
WriteNibbleLcd (0x20); //indica que se escribe en 2 nibbles de 4 bits
WriteByteLcd (0x28,0);
// 30 para el st7066
// 32 para el st7066
#else
WriteByteLcd (0x38,0);
#endif
LcdOff(); //08
// 38 para el st7066?
ClearLcd(); //01
WriteByteLcd (0x06,0); //06
//WriteByteLcd (0x0E,0);
LcdOn(); //0C
TRISLcdData = TRISAnterior;
LcdDataPort = DatoAnterior;
}
#else
#error Faltan definir parametros
#endif