Codigo:
// _EEPROM_RS232_I2C.c
#include <16f876a.h> // Definiciones del PIC 16F876A
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT // Los Fuses de siempre
#use delay(clock=4000000) // Oscilador a 4 Mhz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)// Definicion RS232 estandar
#use i2c(master,sda=PIN_C4, scl=PIN_C3) // Definicion I2C estandar
#include <ctype.h>
#include <string.h>
// CONSTANTES /////////////////////////////////////////////////////////////////
int const lenbuff=32; // Longitud de buffer, Ajustar
// a lo que desees (o te sea posible)
int const address_EEPROMR=0b10100001; // Direccion I2C de EEPROM (para lectura)
int const address_EEPROMW=0b10100000; // Direccion I2C de EEPROM (para escritura)
// 1010 000 0
// ---- --- -
// | | R/W
// | Hard
// Fijo
int const ddeeeprom=32; // Delay Default EEPROM
// VARIABLES EN RAM ///////////////////////////////////////////////////////////
int xbuff=0x00; // Índice: siguiente char en cbuff
char cbuff[lenbuff]; // Buffer
char rcvchar=0x00; // último caracter recibido
int1 flagcommand=0; // Flag para indicar comando disponible
// Declaración de Funciones ///////////////////////////////////////////////////
void presmenu(void); // Presenta el menú
void inicbuff(void); // Borra buffer
int addcbuff(char c); // añade caracter recibido al buffer
void echos(char c); // Eco selectivo sobre RS232
void comando(void); // Procesa comando
int ascii2hex(char d); // Convierte un caracter ascii a hex
void i2cw1(int i2cdev, int i2cdir, int i2cdat); // Rutina de escritura I2C completa
void i2cw2(int i2cdev, int i2cdat); // Rutina de escritura I2C parcial
int i2cr(int i2cdev); // Rutina de lectura I2C
// INTERRUPCIONES /////////////////////////////////////////////////////////////
#int_rda
void serial_isr() { // Interrupción recepción serie USART
rcvchar=0x00; // Inicializo caracter recibido
if(kbhit()){ // Si hay algo pendiente de recibir ...
rcvchar=getc(); // lo descargo y ...
addcbuff(rcvchar); // lo añado al buffer y ...
echos(rcvchar); // hago eco (si procede).
}
}
// Desarrollo de Funciones ////////////////////////////////////////////////////
void presmenu(void){ // Presenta el menú --------------------
delay_ms(25);
printf("
" );
printf("** EEPROM I2C OS **
" ); // Presenta menú
printf("** Control del buffer:
" );
printf("[Enter] Procesa comando
" );
printf("[Escape] Borra todo el buffer
" );
printf("[Delete] Borra último carácter del buffer
" );
printf("
" );
printf("** Comandos EEPROM:
" );
printf("/? Presenta Menú
" );
printf("/B Formatea (borra) eeprom iniciando <indice> a 0.
" );
printf("/r Lee contenido completo de eeprom y vuelca a RS232.
" );
printf("/w <dat> Escribe <dat> en eeprom a partir de <indice>.
" );
printf("/i <dir> Coloca índice de eeprom a <0xdir> sin borrar contenido.
" );
printf("
" );
delay_ms(25);
}
int addcbuff(char c){ // Añade a cbuff -----------------------
switch(c){
case 0x0D: // Enter -> Habilita Flag para procesar
flagcommand=1; // Comando en Main
break;
case 0x08: // Del -> Borra último caracter del Buffer
if(xbuff>0) cbuff[--xbuff]=0x00;
break;
case 0x01B: // Esc -> Borra el Buffer completamente
inicbuff();
break;
default:
cbuff[xbuff++]=c; // Añade caracter recibido al Buffer
if(xbuff>lenbuff) xbuff=lenbuff;
}
}
void echos(char c){ // Echo selectivo ----------------------
int i;
switch(c){
case 0x0D: printf("
" ); // Si he pulsado la tecla [Intro]
break;
case 0x08: printf("%s ",cbuff); // Si he pulsado la tecla [Retroceso]
break;
case 0x1B: printf("" ); // Si he pulsado la tecla [Escape]
for(i=0;i<lenbuff;i++){
printf(" " ); // Borra display (en la longitud del buffer)
}
printf("" );
break;
default: putc(rcvchar); // Echo de cualquier otro caracter
}
}
void inicbuff(void){ // Inicia a cbuff -------------------
int i;
for(i=0;i<lenbuff;i++){ // Bucle que pone a 0 todos los
cbuff[ i ]=0x00; // caracteres en el buffer
}
xbuff=0x00; // Inicializo el indice de siguiente
// caracter
}
int ascii2hex(char d){ // Convierte un caracter ascii a hex ---
int r=0x00;
if(isxdigit(d)){
if(isdigit(d)){
r=d-"0";
}
if(isalpha(d)){
d=toupper(d);
r=10+(d-"A");
}
}
return(r);
}
void i2cw1(int i2cdev, int i2cdir, int i2cdat){ // Rutina de escritura I2C completa
i2c_start(); // Inicializo comunicación I2C
i2c_write(i2cdev); // Envio Dirección de dispositivo I2C + R/W
i2c_write(i2cdir); // Envio address eeprom donde escribir
i2c_write(i2cdat); // Envio byte a escribir
i2c_stop(); // Cierro comunicacion
delay_ms(ddeeeprom); // Espero a que escriba correctamente
}
void i2cw2(int i2cdev, int i2cdat){ // Rutina de escritura I2C parcial
i2c_start(); // Inicializo comunicación I2C
i2c_write(i2cdev); // Envio Dirección de dispositivo I2C + R/W
i2c_write(i2cdat); // Envio byte a escribir
i2c_stop(); // Cierro comunicacion
delay_ms(ddeeeprom); // Espero a que escriba correctamente
}
int i2cr(int i2cdev){ // Rutina de lectura I2C
int r=0x00;
i2c_start();
i2c_write(i2cdev);
r=i2c_read();
i2c_stop();
delay_ms(ddeeeprom);
return(r);
}
// Programa Principal /////////////////////////////////////////////////////////
void main() {
inicbuff(); // Borra buffer al inicio
presmenu(); // Presenta el menú
enable_interrupts(int_rda); // Habilita Interrupción RDA
enable_interrupts(global); // Habilita interrupciones
delay_ms(25);
do {
if(flagcommand) comando(); // Si hay comando pendiente
// de procesar ... lo procesa.
} while (TRUE);
}
// Procesador de Comandos /////////////////////////////////////////////////////
void comando(void){
int i,j,u,h;
int1 flagvalido=0; // Flag para detectar comandos invalidos
char arg[lenbuff]; // Argumento de comando (si lo tiene)
disable_interrupts(int_rda); // Dehabilito Interrupción RDA durante procesado
flagcommand=0; // Desactivo flag de comando pendiente.
for(i=0;i<lenbuff;i++){ // Limpia el argumento (por si lo hay)
arg[ i ]=0x00;
}
// Comando /?
if(cbuff[0]=="/"&&cbuff[1]=="?"){ // Comparo inicio del buffer con comando "/?"
flagvalido=1; // Marco comando válido
presmenu(); // Presenta el menú
}
// Comando /B
if(cbuff[0]=="/"&&cbuff[1]=="B"){ // Comparo inicio del buffer con comando "/B"
flagvalido=1; // Marco comando válido
printf("
Formateando " );
j=0;
for(i=0;i<255;i++){
i2cw1(address_EEPROMW,i,0x00);// Envio Dirección de dispositivo I2C + Escribir
// Envio address eeprom donde escribir
// Envio byte a escribir (0x00)
if(++j>14){ // Monitorizo en bloques de 15 bytes
j=0;
putc(".");
}
}
printf("
Formateado Ok.
" );
}
// Comando /r
if(cbuff[0]=="/"&&cbuff[1]=="r"){ // Comparo inicio del buffer con comando "/R"
flagvalido=1; // Marco comando válido
i2cw2(address_EEPROMW,0x00); // Inicializo dirección a partir de la que leer
// que fijo desde el primer byte
for(i=0;i<16;i++) printf("%X ",i); // Pongo cabecera de direcciones
printf("
" );
for(i=0;i<16;i++) printf("== " );
printf("
" );
j=0;
i2c_start(); // Realizo la lectura completa de la EEPROM
i2c_write(address_EEPROMR);
for(i=0;i<255;i++){
u=i2c_read();
printf("%X ",u); // y vuelco en bloques de 15 bytes
if(++j>15){
j=0;
printf("
" );
}
}
i2c_stop();
printf("
" );
}
// Comando /w dat
if(cbuff[0]=="/"&&cbuff[1]=="w"){ // Comparo inicio del buffer con comando "/w"
flagvalido=1; // Marco comando válido
i=3;
do{ // Extraemos argumento del buffer
arg[i-3]=cbuff[ i ]; // a partir del 4º byte y hasta .
}while(cbuff[++i]!=0x00);
// recupero posición inicial <indice> para escribir
i2cw2(address_EEPROMW,0x00); // Inicializo dirección a partir de la que leer
// que fijo desde el primer byte
h=i2cr(address_EEPROMR); // leo el valor de índice
++h;
printf("
Escribir %s a partir de %X
",arg,h);
i2cw2(address_EEPROMW,h); // Inicializo dirección a partir de la que leer
// que fijo desde el <indice>
// escribo argumento a partir de índice
i=0;
do{
i2cw1(address_EEPROMW,h,arg[ i ]);// Envio Dirección de dispositivo I2C + Escribir
// Envio address eeprom donde escribir -> h
// Envio byte a escribir -> arg[ i ]
++h;
++i;
}while(arg[ i ]!=0x00);
// Actualizo indice
--h;
i2cw1(address_EEPROMW,0x00,h);// Envio Dirección de dispositivo I2C + Escribir
// Envio address eeprom donde escribir -> 0x00
// Envio byte a escribir -> h
printf("Buffer Escrito.
" );
}
// Comando /i dir
if(cbuff[0]=="/"&&cbuff[1]=="i"){ // Comparo inicio del buffer con comando "/i"
flagvalido=1; // Marco comando válido
i=3;
do{ // Extraemos argumento del buffer
arg[i-3]=cbuff[ i ]; // a partir del 4º byte y hasta .
}while(cbuff[++i]!=0x00);
h=(16*ascii2hex(arg[0]))+(ascii2hex(arg[1])); // Convierto de Hex-Ascci-2-digitos
// al entero correspondiente
i2cw1(address_EEPROMW,0x00,h); // Escribo nuevo indice en 0x00
printf("> i=%X hex (%u dec)
",h,h); // Monitorizo lo realizado.
}
// Retorno error o comando invalido
if(!flagvalido) printf("¿%s?
",cbuff);
inicbuff(); // Borro buffer.
enable_interrupts(int_rda); // Habilita de nuevo Interrupción RDA
}