Estoy de acuerdo pero ya va en Proteus
VEreis he tenido que modificar algunas cosillas, quitar del programa de uso
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
no se porque
Ademas en la libreria no esta inicializado el puerto D asi que lo hice y quedo de la siguiente manera
// coach_lcd.c
//
// Funciones para la gestion del display 2x16 [ByCoach]:
//
// lcd_init() Debe ser llamada antes que las otras funciones.
//
// lcd_putc(c) Visualiza c en la siguiente posición del display.
// Caracteres especiales de control:
// f Borrar display
//
Saltar a la segunda linea
// Retroceder una posición.
//
// lcd_gotoxy(x,y) Selecciona la nueva posicion de escritura en el display.
// (la esquina superior izquierda es 1,1)
//
// lcd_getc(x,y) Devuelve el caracter de la posicion x,y del display.
//Definicion de pines:
#define lcd_rs PIN_D0 //
#define lcd_rw PIN_D1 //
#define lcd_en PIN_D2 //
#define lcd_DB4 PIN_D4 //
#define lcd_DB5 PIN_D5 //
#define lcd_DB6 PIN_D6 //
#define lcd_DB7 PIN_D7
#define set_tris_lcd(x) set_tris_d(x) // sirve para definir el puerto a usar
void lcd_enviar_nibble( int nibble )
{
output_bit( lcd_DB4, bit_test( nibble, 0 ) ); //Pone en el puerto B[4..7] el valor en nibble[0..3]
output_bit( lcd_DB5, bit_test( nibble, 1 ) );
output_bit( lcd_DB6, bit_test( nibble, 2 ) );
output_bit( lcd_DB7, bit_test( nibble, 3 ) );
delay_us( 1 );
output_high( lcd_en ); //Activa y desactiva enable para que el lcd capture el nibble
delay_us( 2 );
output_low( lcd_en );
}
int lcd_leer_byte( void )
{
int valor = 0;
output_high( lcd_rw ); //Se activa rw indicando que se va a realizar una lectura
delay_us( 1 );
output_high( lcd_en ); //Se activa enable para que el lcd saque la parte alta del byte deseado
delay_us( 1 ); //por los pines de datos
if( input( lcd_DB7 ) ) //Se captura la parte alta del byte deseado
bit_set( valor, 7 );
if( input( lcd_DB6 ) )
bit_set( valor, 6 );
if( input( lcd_DB5 ) )
bit_set( valor, 5 );
if( input( lcd_DB4 ) )
bit_set( valor, 4 );
output_low( lcd_en ); //Se desactiva y se vuelve a activar enable para que el lcd saque la parte
delay_us( 1 ); //baja del byte deseado por los pines de datos
output_high( lcd_en );
delay_us( 1 );
if( input( lcd_DB7 ) ) //Se captura la parte baja del byte deseado
bit_set( valor, 3 );
if( input( lcd_DB6 ) )
bit_set( valor, 2 );
if( input( lcd_DB5 ) )
bit_set( valor, 1 );
if( input( lcd_DB4 ) )
bit_set( valor, 0 );
output_low( lcd_en ); //Se desactiva enable, indicando al lcd el fin de la lectura del byte
return( valor ); //Devuelve el byte capturado
}
void lcd_enviar_byte( int dir, int valor ) //Si recibe en dir un 1 se trata de un dato y si es un 0 es un comando
{
output_low( lcd_rs );
while( bit_test( lcd_leer_byte(), 7 ) ); //Lectura del Flag de Busy (ocupado), si 1 se espera, si 0 se continúa
output_bit( lcd_rs, dir ); //Se asigna a rs el valor de dir para indicar si es dato o comando
delay_us( 1 );
output_low( lcd_rw ); //Se pone a cero rw para indicar que se va a realizar una escritura
delay_us( 1 );
output_low( lcd_en ); //Se pone a cero enable para preparar el valor a enviar
lcd_enviar_nibble( valor >> 4 ); //Se envía primero la parte alta del byte
lcd_enviar_nibble( valor & 0x0F ); //a continuación se envía la parte baja
}
void lcd_gotoxy( int x, int y ) //Se reciben las coordenadas x e y a las que se desea desplazarse
{
int dir;
if ( y != 1 ) //La posición "y" determinará la línea elegida, si es 1 -> Línea 1, si no -> Línea 2
dir = 0x40; //Dirección de la RAM del LCD para la 2ª línea
else
dir = 0x00; //Dirección de la RAM del LCD para la 1ª línea
dir += x - 1; //Resta uno, ya que la posición 1 sería la 0 para el lcd
lcd_enviar_byte( 0, dir | 0x80 ); //Se envía el byte, indicando que es un comando y poniendo el bit
} //más significativo a 1, para diferenciar este comando de los demás
void lcd_init( void )
{
int i;
int bytes_inicio[4] = { 0x28, 0x0C, 0x01, 0x06 };
set_tris_lcd(0x00);
output_low( lcd_rs ); //Pone a cero todos los pines de control
output_low( lcd_rw );
output_low( lcd_en );
delay_ms( 30 );
for ( i = 1 ; i <= 3 ; i++ )
{
lcd_enviar_nibble( 3 );
delay_ms( 5 );
}
lcd_enviar_nibble( 2 );
for( i = 0 ; i <= 3 ; i++ ) //Se configura el lcd con las características indicadas anteriormente
lcd_enviar_byte( 0 , bytes_inicio
);
}
void lcd_putc( char c ) //Se recibe el caracter a enviar
{
switch( c )
{
case "f" : lcd_enviar_byte( 0, 1 ); //Si c = "f", se envía un 1, e indica que es un comando
delay_ms( 2 ); //Enviando un 1, se borra la pantalla del lcd
break;
case "
" : lcd_gotoxy( 1, 2 ); //Si c = "
", se posiciona en la segunda línea
break;
case "" : lcd_enviar_byte( 0, 0x10 ); //Si c = "", se sitúa una posición a la izquierda
break;
default : lcd_enviar_byte( 1, c ); //Si no es ninguna de las anteriores, envía un caracter
break;
}
}
char lcd_getc( int x,int y ) //Se reciben las coordenadas x e y de las que se desea el dato
{
char valor;
lcd_gotoxy( x, y ); //Se posiciona en el punto deseado
output_high( lcd_rs ); //Pone a 1 el pin rs, indicando que se trata de un dato
valor = lcd_leer_byte(); //Lee el byte de la posición deseada
output_low( lcd_rs );
return( valor ); //Devuelve el caracter leído
}
El programa de uso que funciona en PRoteus es la siguiente chorrada
#include <16f877.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=20000000,RESTART_WDT)
#include <lcd20Mhz.c>
main()
{
lcd_init(); // Inicializar LCD
while(1)
lcd_putc("Pulsa una tecla "
}
Probadlo y vereis, lo que necesitamos ahora es que alguien que tenga un prototipo a 20 Mhz lo cargue y lo pruebe, si funciona repararemos la libreria ya que tiene algun defectillo mas.
Dejad noticias por favor