Codigo:
////////////////////////////////////////////////////////////////////////////////
//// lcd_modificado.c ////
//// Driver para módulos LCD microcontrolados ////
//// ////
//// Inspirado en librería CCS ////
//// Adaptado por Fernando Nuño García y Miguel Ángel José Prieto para ////
//// funcionamiento con el LCD integrado en la placa PICDEM-2-PLUS. ////
//// ////
//// Funciones definidas ////
//// ////
//// lcd_init() Inicialización,llamar antes de cualquier otra función ////
//// ////
//// lcd_putc(c) Muestra c en la posicion siguiente del LCD. ////
//// Caracteres de control: ////
//// f Borra display ////
////
Sitúa cursor al comienzo de la línea 2 ////
//// Retrocede el cursor una posición ////
//// Avanza el cursor una posición ////
//// Retrocede una posición la pantalla visible ////
//// v Avanza una posición la pantalla visible ////
//// ////
//// ////
//// lcd_gotoxy(x,y) Sitúa escritura en posición del LCD ////
//// (posición 1,1: arriba a la izquierda) ////
//// ////
//// lcd_getc(x,y) Devuelve carácter en posición x,y del LCD ////
//// ////
////////////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,1997 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. ////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Conexión a 7 pines del MCU: 3 de control / interface de datos de 4 bits: //
// //
// Líneas de control asignadas //
// RA1 enable //
// RA2 rw //
// RA3 rs //
// //
// Líneas de Datos //
// RD0 D4 //
// RD1 D5 //
// RD2 D6 //
// RD3 D7 //
// //
////////////////////////////////////////////////////////////////////////////////
struct lcd_pines_control
{ // Estructura que se define para facilitar acceso
boolean nada;
boolean enable; // y asociarlos a los 3 bits más bajos del PORTC
boolean rw; // asignamos luego a esta estructura el PORTC
boolean rs; // rs (1º
corresponde al menos significativo
// a los pines de control del LCD
int otros : 4;
} lcd_control;
struct lcd_pines_datos
{ // Hacemos lo mismo con esta estructura para el PORTD
int datos:4; // los 4 bits más bajos son los de datos
int no_usados:4;
} lcd_datos;
#byte lcd_control = 5 // Ponemos la estructura entera en el PORTC (registro 7)
#byte trisa = 0x85 // Registro de dirección de datos
#byte lcd_datos =8 // Lo mismo para los datos, en el PORTD (registro 6)
#byte trisd = 0x88 // Registro de dirección de datos
#define lcd_linea_dos 0x40 // Dirección de inicio para la 2ª línea en la DDRAM
////////////////////////////////////////////////////////////////////////////////
/// -Prototipos de las funciones //
////////////////////////////////////////////////////////////////////////////////
void lcd_init();
byte lcd_read_byte();
void lcd_send_nibble(byte n);
void lcd_send_byte(byte address, byte n);
void lcd_gotoxy(byte x, byte y);
void lcd_putc(char c);
char lcd_getc(byte x, byte y);
void lcd_clr_line(char fila);
////////////////////////////////////////////////////////////////////////////////
/// Función que inicializa el LCD, se deberían cambiar bits //
// para cambiar configuracion //
////////////////////////////////////////////////////////////////////////////////
void lcd_init()
{
byte i;
trisa&=0b11110001; // Asignamos salidas en RC0, RC1 y RC2, resto puerto
//como estaba
trisd&=0b11110000; // Lo mismo para RD0 a RD3
lcd_control.rs = 0;
lcd_control.rw = 0;
lcd_control.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
lcd_send_byte(0,0b00101000); ///Se envía Function set 0 0 1 DL N F - -
lcd_send_byte(0,0b00001100); ///Se envía Display on/off 0 0 0 0 1 D C B
lcd_send_byte(0,0b00000001); //Se envía Clear Display
lcd_send_byte(0,0b00000110); //Se envía Entry Mode set 0 0 0 0 0 1 I/D S//
////////////////////////////////////////////////////////////////////////////////
// DL: datos 4 bits(0); 8 bits (1) / N: 2 líneas (1); 1 línea (0) / F: 5x10 (1); 5x8 (0)
// D: display on (1); off (0) / C: cursor on (1); off (0) / B: parpadeo pos.cursor (1); no (0)
// I/D: incremento en R/W (1) o decremento (0) / S: acompaña desplaz.display (1); no (0)
////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
// Lee el byte señalado por el puntero, 1º parte alta, 2º parte baja //
// Si al llamar a esta función rs=0, devuelve busy flag (+signif.) //
//y dirección actual //
////////////////////////////////////////////////////////////////////////////////
byte lcd_read_byte()
{
byte low,high;
trisa&=0b11110001; //Señales de control (salidas), el resto lo que sean
trisd|=0b00001111; //Las de datos pasan a ser entradas, las demas igual
lcd_control.rw = 1;
delay_cycles(1);
lcd_control.enable = 1;
delay_cycles(1);
high = lcd_datos.datos;
lcd_control.enable = 0;
delay_cycles(1);
lcd_control.enable = 1;
delay_us(1);
low = lcd_datos.datos;
lcd_control.enable = 0;
trisd&=0b11110000; // Dejamos RD0 a RD3 como salidas
return( (high<<4) | low);
}
////////////////////////////////////////////////////////////////////////////////
// Envía medio byte, los 4 bits más bajos de n //
// Necesario poner rs y rw de modo adecuado y entrar con enable=0 //
////////////////////////////////////////////////////////////////////////////////
void lcd_send_nibble( byte n )
{
lcd_datos.datos = n;
delay_cycles(1);
lcd_control.enable = 1;
delay_us(2);
lcd_control.enable = 0;
}
////////////////////////////////////////////////////////////////////////////////
// -Envía un byte (n) al registro de instrucciones (si address=0) ó //
// reg. de datos (address=1) //
// //
// //
// -Utiliza lcd_send_nibble(n) enviando primero nibble alto del byte //
////////////////////////////////////////////////////////////////////////////////
void lcd_send_byte( byte address, byte n )
{
lcd_control.rs = 0;
while ( bit_test(lcd_read_byte(),7) ); //Mientras esté ocupado el LCD, espera
lcd_control.rs = address;
delay_cycles(1);
lcd_control.rw = 0;
delay_cycles(1);
lcd_control.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0x0F);
}
/////////////////////////////////////////////////////////////////////////////////////////
// Sitúa el contador de direcciones en la DDRAM (para lectura o escritura posterior) //
// x puede ir de 1 a 40, posición dentro de una línea (16 visibles) //
// y puede ser 1 (línea 1) o 2 (línea 2) //
/////////////////////////////////////////////////////////////////////////////////////////
void lcd_gotoxy( byte x, byte y)
{
byte posicion;
if(y!=1)
posicion=lcd_linea_dos;
else
posicion=0;
posicion+=x-1;
lcd_send_byte(0,0x80|posicion); //Las direcciones de la DDRAM empiezan por 1xxxxxxx
}
//////////////////////////////////////////////////////////////////////////////////
// Envía un carácter c a la DDRAM del LCD, también algunos caracteres de control//
//////////////////////////////////////////////////////////////////////////////////
void lcd_putc( char c)
{
switch (c)
{
case "f" : lcd_send_byte(0,1); //Limpia la pantalla
delay_ms(2);
break;
case "
" : lcd_gotoxy(1,2); //Coloca puntero en 1ª posicion de la 2ª línea
break;
case "" : lcd_send_byte(0,0x10); //Retrocede una posición el cursor
break;
case " " : lcd_send_byte(0,0x14); //Avanza una posición el cursor
break;
case "" : lcd_send_byte(0,0x18); //Retrocede una posición la pantalla visible
break;
case "v" : lcd_send_byte(0,0x1C); //Avanza una posición la pantalla visible
break;
default : lcd_send_byte(1,c); //Envía caracter a DDRAM,
break; //Si es una tira, los envía todos uno a uno
}
}
////////////////////////////////////////////////////////////////////////////////
// Devuelve el carácter situado en la posición x,y de la DDRAM //
////////////////////////////////////////////////////////////////////////////////
char lcd_getc( byte x, byte y) {
char value;
lcd_gotoxy(x,y);
lcd_control.rs=1;
value = lcd_read_byte();
lcd_control.rs=0;
return(value);
}
////////////////////////////////////////////////////////////////////////////////////
// Limpia la linea correspondiente y se situa al principio de la misma //
////////////////////////////////////////////////////////////////////////////////////
void lcd_clr_line(char fila)
{
int j;
lcd_gotoxy(1,fila);
for (j=0;j<40;j++) lcd_putc(" ");
lcd_gotoxy(1,fila);
}