Vamos a ver, esto funciona bien al menos con el proteus
Te pego librerias y programita de prueba
EL principal
#include <16f877.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000,RESTART_WDT)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#include <kbd2.c>
#include <lcd1.c>
#include <eprom1.c>
#include <stdlib.h>
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, ADDRESS=0X08, FAST , FORCE_HW)
main()
{
char k;
int i=0,j=0;
char dato;
lcd_init(); // Inicializar LCD
init_ext_eeprom();
lcd_putc("Pulsa una tecla "
;
while(1)
{
i=0;
j=0;
k = kbd_getc(); // Leer tecla.
if(k)
{
j=k*16;
lcd_gotoxy(1,1);
lcd_putc("Tecla Pulsada "
;
printf(lcd_putc,"%c",k);
delay_ms(1000);
lcd_gotoxy(1,1);
lcd_putc("Mensaje eeprom "
;
lcd_gotoxy(1,2);
for(i=0;i<20;i++)
{
dato=read_ext_eeprom(i+j);
printf(lcd_putc,"%c",dato);
}
delay_ms(1000);
lcd_clr_line(1);
lcd_clr_line(2);
lcd_gotoxy(1,1);
lcd_putc("Pulsa una tecla "
;
}
}
}
Libreria LCD
///////////////////////////////////////////////////////////////////////////
//// LCD1.C ////
//// Driver para modulo LCD ////
//// ////
//// lcd_init() Debe ser llamada antes que cualquier funcion. ////
//// ////
//// lcd_putc(c) Mostrara c en la siguiente posicion del LCD. ////
//// Los siguientes envios tienen funciones especiales: ////
//// f Borra el LCD ////
////
Va al principio de la segunda linea ////
//// Mueve una posicion atras ////
//// ////
//// lcd_gotoxy(x,y) Fija la posicion de escritura (Arr. Izda es 1,1) ////
//// ////
//// lcd_getc(x,y) Devuelve el caracter de la posicion x,y del LCD ////
//// ////
///////////////////////////////////////////////////////////////////////////
// el conexionado de de los pines es el siguiente:
// D0 enable
// D1 rs
// D2 rw
// D4 D4
// D5 D5
// D6 D6
// D7 D7
//
// Los pines D0-D3 del LCd no se usan
// Elimina el // del comentario siguiente para usar el puerto B, en caso contrario se usa el D
//#define use_portb_lcd TRUE
struct lcd_pin_map { // Mediante el orden de esta estructura
BOOLEAN rs; // se organizan los pines asignados al LCD
BOOLEAN rw; // De menor a mayor, asi como estan el 0 sera RS
BOOLEAN enable; // el 1 RW y el 2 Enable
BOOLEAN unused; //
int data : 4;
} lcd;
#if defined(__PCH__)
#if defined use_portb_lcd
#byte lcd = 0xF81 // Esto fija la estructura entera
#else
#byte lcd = 0xF83 // Esto fija la estructura entera
#endif
#else
#if defined use_portb_lcd
#byte lcd = 6 // en el puerto B (la direccion 6)
#else
#byte lcd = 8 // en el puerto D (la direccion
#endif
#endif
#if defined use_portb_lcd
#define set_tris_lcd(x) set_tris_b(x)
#else
#define set_tris_lcd(x) set_tris_d(x)
#endif
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lineas
#define numero_caracteres 20 // cambiar aqui si es 2*16 2*20 o el numero de caracteres de la linea
#define lcd_line_two 0x40 // direccion de la LCD RAM para la segunda linea
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// Estos bytes necesitan enviarse al LCD
// para arrancarlo.
// Lo siguiente se usa para fijar
// la direccion del registro del puerto de I/O.
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // Para escribir todos los pines como salida
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // Para leer todos los pines como entrada
BYTE lcd_read_byte() {
BYTE low,high;
set_tris_lcd(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
high = lcd.data;
lcd.enable = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data;
lcd.enable = 0;
set_tris_lcd(LCD_WRITE);
return( (high<<4) | low);
}
void lcd_send_nibble( BYTE n ) {
lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
void lcd_init() {
BYTE i;
set_tris_lcd(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING
);
}
void lcd_gotoxy( BYTE x, BYTE y) {
BYTE address;
Libreria teclado
/*-------------------------------------------*
| KBD2.C |
| Autor: Pedro Mª Jiménez |
| (c) Microsystems Engineering (Bilbao) |
*-------------------------------------------*/
// Funciones para la gestión del teclado de la Trainer PLUS.
// char kbd_getc() Devuelve el código ASCII de la tecla pulsada.
// Si no se pulsó ninguna, devuelve 0.
// Conexiones del teclado.
/*
RB0 RB1 RB2 RB3
^ ^ ^ ^
| | | |
|---|---|---|---|
RB4 ---> | 1 | 2 | 3 | F |
|---|---|---|---|
RB5 ---> | 4 | 5 | 6 | E |
|---|---|---|---|
RB6 ---> | 7 | 8 | 9 | D |
|---|---|---|---|
RB7 ---> | A | 0 | B | C |
|---|---|---|---|
*/
// Caracteres ASCII asociados a cada tecla:
char const KEYS[4][4] = {{"1","2","3","F"},
{"4","5","6","E"},
{"7","8","9","D"},
{"A","0","B","C"}};
#byte kbd_port_b = 6
char kbd_getc()
{
char tecla=0;
int f,c,t,i,j;
port_b_pullups(true);
set_tris_b(0b00001111); // RB7-RB4 salidas, RB3-RB0 entradas
for(f=0x10, i=0; i<4; f<<=1, i++)
{
for(c=0x01, j=0; j<4; c<<=1, j++)
{
kbd_port_b = ~f;
delay_cycles(1);
t = kbd_port_b & 0x0F;
t = ~(t | 0xF0);
if(t == c)
{
delay_ms(20);
tecla=KEYS[j];
while(t==c)
{
restart_wdt();
t = kbd_port_b & 0x0F;
t = ~(t | 0xF0);
}
break;
}
}
if(tecla)
break;
}
port_b_pullups(false);
return tecla;
}
Libreria EEprom
///////////////////////////////////////////////////////////////////////////
//// Library for a 24LC64 serial EEPROM ////
//// ////
//// init_ext_eeprom(); Call before the other functions are used ////
//// ////
//// write_ext_eeprom(a, d); Write the byte d to the address a ////
//// ////
//// d = read_ext_eeprom(a); Read the byte d from the address a ////
//// ////
//// The main program may define eeprom_sda ////
//// and eeprom_scl to override the defaults below. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 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 EEPROM_SDA
#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3
#endif
#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 32768
#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL,FORCE_SW)
void init_ext_eeprom()
{
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);
}
void write_ext_eeprom(long int address, BYTE data)
{
short int status;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>;
i2c_write(address);
i2c_write(data);
i2c_stop();
i2c_start();
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
}
BYTE read_ext_eeprom(long int address) {
BYTE data;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>;
i2c_write(address);
i2c_start();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
return(data);
}
La eeprom la grabo con el grabador y la edito con ICPROG
OJO, el ficero de salida de la eeprom debe ser formato bin, el HEX es para los fuentes compilador para los pics.
Espero que te sirva