Autor Tema: Libreria EEPROM en HiTech  (Leído 4506 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Libreria EEPROM en HiTech
« en: 13 de Abril de 2011, 19:22:19 »
Estoy intentando hacer una libreria para una 24LC16 en HiTech, pero no consigo hacerla funcionar bien. Estoy usando las funciones del ejemplo que viene en el compilador, y lo que hago basicamente es lo mismo que en la libreria de la 2416 del CCS.

Os dejo el codigo, espero ayuda.

Código: [Seleccionar]
#include <htc.h>
#include "i2c.c"
//---------------------------------------------
void init_ext_eeprom() {
SCL_DIR = 1;//Pone pin como entrada.
SDA_DIR = 1;
}
//--------------------------------------------
unsigned char ext_eeprom_ready() {
   unsigned char ack;
   i2c_Restart();            // If the write command is acknowledged,
   ack = i2c_SendAddress(0x50,0);// then the device is ready.
   i2c_Stop();
   return !ack;
}
//--------------------------------------------
void write_ext_eeprom(unsigned char address, unsigned char data) {
   while(!ext_eeprom_ready());
   i2c_Restart();
   i2c_SendAddress(0x50,0);
   i2c_SendByte(address);
   i2c_SendByte(data);
   i2c_Stop();
}
//---------------------------------------------
int  read_ext_eeprom(unsigned char address) {
   int data;

   while(!ext_eeprom_ready());
   i2c_Restart();
   i2c_SendAddress(0x50,0);//Escribir
   i2c_SendByte(address);
   i2c_Restart();
   i2c_SendAddress(0x50,1);//Leer.
   data=i2c_ReadByte();
   i2c_Stop();
   return(data);
}

Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Libreria EEPROM en HiTech
« Respuesta #1 en: 13 de Abril de 2011, 22:11:18 »
  ¿Y cuál es el problema que estás teniendo? ¿Estás intentando utilizar el I2C por HardWare o por SoftWare?
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Libreria EEPROM en HiTech
« Respuesta #2 en: 14 de Abril de 2011, 06:38:39 »
Pues el problema es que no leo el dato que escribo previamente. La secuencia que obtengo en Proteus es esta:

Código: [Seleccionar]
S 50 P
S 50 A 02 A P
S 50 P
S 50 A 03 Sr 51 N Sr P

Y el codigo de prueba:

Código: [Seleccionar]
init_ext_eeprom();
write_ext_eeprom(1, 0x22);
datoAux = read_ext_eeprom(1);
GotoxyLcd(1,1);
WriteStrLcd("dato: ");
itoa(texto,datoAux,10);
WriteStrLcd(texto);

Como se puede ver, intento leer y escribir en la posicion 1, y en la segunda secuencia se puede ver que escribe un 2. En la ultima secuencia escribe un 3, cuando deberia ser un 1.

Estoy usando los pines que el pic tiene para el I2C, pero no sé si la comunicación es por hardware o por software, como dije uso las librerias para el I2C que trae el compilador (están en los adjuntos).
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Libreria EEPROM en HiTech
« Respuesta #3 en: 14 de Abril de 2011, 09:11:28 »
Bueno, de esta otra forma, al menos la escritura parece correcta. Ahora si no me equivoco solo falla la lectura del dato, lee 0xFF en lugar de 0x22.

Código: [Seleccionar]
#include <htc.h>
#include "i2c.c"
//---------------------------------------------
void init_ext_eeprom() {
SCL_DIR = 1;//Pone pin como entrada.
SDA_DIR = 1;
}
//--------------------------------------------
unsigned char ext_eeprom_ready() {
   unsigned char ack;
   i2c_Restart();            // If the write command is acknowledged,
   ack = i2c_SendAddress(0x50,0);// then the device is ready.
   i2c_Stop();
   return !ack;
}
//--------------------------------------------
void write_ext_eeprom(unsigned char address, unsigned char data) {
    while(!ext_eeprom_ready());
    i2c_WriteTo(0x50);
i2c_PutByte(address);
i2c_PutByte(data);
i2c_Stop();
}
//---------------------------------------------
int  read_ext_eeprom(unsigned char address) {
    int data;

    while(!ext_eeprom_ready());
    i2c_WriteTo(0x50);
i2c_PutByte(address);
i2c_ReadFrom(0x50);
data = i2c_GetByte(I2C_LAST);
i2c_Stop();
return(data);
}

Y las secuencias en proteus:

Código: [Seleccionar]
S 50 P
S 50 N 01 N 22 N Sr P
S 50 P
S 50 N 01 N Sr 51 N FF N Sr P
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Libreria EEPROM en HiTech
« Respuesta #4 en: 14 de Abril de 2011, 09:28:58 »
Podrías verificar si no existe alguna función que indique que el proceso de envío/recepción de datos ha finalizado y luego leer? Puede que las funciones solo escriban sobre SSPBUF.

Ahora, esto porqué?

return !ack;  y while(!ext_eeprom_ready()); . Negado y negado..
No contesto mensajes privados, las consultas en el foro

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Libreria EEPROM en HiTech
« Respuesta #5 en: 14 de Abril de 2011, 09:47:45 »
  Prestale atención a lo que indica Suky, y que incluso queda de manifiesto con lo mostrado por el I2C monitor, ya que se aprecia claramente que no hay respuesta del dispositivo.

Código: C
  1. S 50 P
  2. S 50 N 01 N 22 N Sr P
  3. S 50 P
  4. S 50 N 01 N Sr 51 N FF N Sr P
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Libreria EEPROM en HiTech
« Respuesta #6 en: 14 de Abril de 2011, 11:20:19 »
  micro_pepe, ¿Por qué hacés esto i2c_SendAddress(0x50,0);? Según el datasheet que estoy consultando, al address de una 24LC16 es 1010 + 3 bits de bloque interno + el bit r/w. Entonces para llamar al dispositivo y queriendo manejar el primer bloque para escritura tendríamos que enviar 0xA0 y no 0x50
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Libreria EEPROM en HiTech
« Respuesta #7 en: 14 de Abril de 2011, 12:21:28 »
  micro_pepe, ¿Por qué hacés esto i2c_SendAddress(0x50,0);? Según el datasheet que estoy consultando, al address de una 24LC16 es 1010 + 3 bits de bloque interno + el bit r/w. Entonces para llamar al dispositivo y queriendo manejar el primer bloque para escritura tendríamos que enviar 0xA0 y no 0x50

Pues hago eso porque las direcciones de los dispositivos I2C son de 7 bit, y luego a parte el bit que indica si se escribe o se lee, 1010000 = 0x50. Esto lo aprendí con el Arduino: http://www.todopic.com.ar/foros/index.php?topic=32811.0

De todas formas probé con 0xA0. Tendré en cuenta lo que me decís en post anteriores.

Saludos.
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Libreria EEPROM en HiTech
« Respuesta #8 en: 14 de Abril de 2011, 12:26:39 »
Lo que pasa que la direccion I2C es 1010A2A1A0, y si los Ax está a GND la dirección de 7-bits es 0x50, que ubicada correctamente en el byte junto al bit R/W es 0xA0 o 0xA1 como dice AngelGris  ;-)



Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Libreria EEPROM en HiTech
« Respuesta #9 en: 14 de Abril de 2011, 13:41:20 »
Bueno, creo que algo he avanzado, la secuencia es esta, ahora si responde la memoria (supongo que la 'A' es el ack de respuesta):

Código: [Seleccionar]
S A0 A 01 A 22 A Sr P
S A0 A 01 A Sr A1 A FF N Sr P

Código: [Seleccionar]
//--------------------------------------------
void write_ext_eeprom(unsigned char address, unsigned char data) {
    while(i2c_WriteTo(0xA0));
while(i2c_PutByte(address));
while(i2c_PutByte(data));
i2c_SendAcknowledge(1);
while(!i2c_ReadAcknowledge());
i2c_Stop();
}
//---------------------------------------------
unsigned char  read_ext_eeprom(unsigned char address) {
    unsigned char data;

while(i2c_WriteTo(0xA0));
while(i2c_PutByte(address));
while(i2c_ReadFrom(0xA1));
data = i2c_GetByte(I2C_LAST);
i2c_Stop();
return(data);
}
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Libreria EEPROM en HiTech
« Respuesta #10 en: 14 de Abril de 2011, 13:58:19 »
  Bien, y si, ese A es de ack.

  Ahora solo falta que se grabe el dato. Podrías probar de dejar un delay de unos 5mS a 10mS entre que intentas escribir en la memoria y luego intentar la lectura.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Libreria EEPROM en HiTech
« Respuesta #11 en: 14 de Abril de 2011, 20:10:18 »
  Bien, y si, ese A es de ack.

  Ahora solo falta que se grabe el dato. Podrías probar de dejar un delay de unos 5mS a 10mS entre que intentas escribir en la memoria y luego intentar la lectura.

Pues lo del retardo no funciona  :? :? he probado otras cosas y no he conseguido nada.
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Libreria EEPROM en HiTech
« Respuesta #12 en: 14 de Abril de 2011, 22:08:27 »
  Yo hice un programa con unas rutinas propias de I2C e implementando el delay (según la simulación) sí me graba el dato...

Acá está el programa que estoy simulando

Código: C
  1. #include <htc.h>
  2.  
  3.   __CONFIG (HS & WDTDIS & LVPDIS);
  4.  
  5. #define PIC_CLK    10000000
  6. #define _XTAL_FREQ 10000000
  7. #define I2C_BAUD   100000
  8.  
  9. #include "HardI2c.c"
  10. #include "Def16f87xa.h"
  11.  
  12. void main(void)
  13. {
  14.   char DatoLeido;
  15.  
  16.   setup_adc (ADC_OFF);
  17.   setup_adc_ports (NO_ANALOG);
  18.   CMCON = 7;
  19.   TRISB = 0;
  20.   TRISC = 0;
  21.   setup_i2c (I2C_MASTER);
  22.   start_i2c();
  23.   if (write_i2c(0xA0) == ACK)  // envio la direccion de la memoria
  24.   {
  25.     write_i2c(0x00);           // envio en que direccion quiero escribir
  26.     write_i2c(0x10);           // envio el dato a escribir
  27.   }
  28.   stop_i2c();
  29.   __delay_ms(10);              // espero a que termine de grabar
  30.   start_i2c();
  31.   write_i2c(0xA0);             // envio la direccion de la memoria
  32.   write_i2c(0x00);             // envio la direccion a leer
  33.   rstart_i2c();                // envio el Repeated Start
  34.   if (write_i2c(0xA1) == ACK) DatoLeido = read_i2c(NOACK);
  35.  // envio la direccion de la memoria para leer y si hay respuesta leo el dato y envio NOACK.
  36.   stop_i2c();
  37.  
  38.   while (1);
  39. }
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3206
Re: Libreria EEPROM en HiTech
« Respuesta #13 en: 16 de Abril de 2011, 16:59:53 »
Pues no consigo hacerlo funcionar, lo que si está claro es que no graba el dato, si prviamente en real grabo la memoria, los datos grabados los lee correctamente.

Saludos.
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Libreria EEPROM en HiTech
« Respuesta #14 en: 16 de Abril de 2011, 19:48:03 »
  Te cuento mi experiencia con mis propias rutinas.
  Antes intentaba hacer polling sobre el ACK -como indica el datasheet de la memoria- para saber cuando terminaba el proceso de escritura y luego intentar la lectura, pues bien, siempre fallaba la lectura. Luego puse el delay posterior a la grabación y allí si pude leer. Pero no entendía el porque del fallo en el polling, debuggeando el programa comprendí que en mi función "write_ic2" luego de llenar el registro SSPBUF con el dato que quería enviar salía de la misma retornando el bit ACKSTAT.

Código: C
  1. char write_i2c (unsigned char data)
  2.   {
  3.     while (( SSPCON2 & 0x1F ) || RW );
  4.     SSPBUF = data;
  5.     return ACKSTAT;
  6.   }

  Pero el error está en que se está saliendo antes de que haya terminado la transferencia y por lo tanto el valor de retorno no es el correcto. La solución fue no salir de la rutina hasta asegurarse que el bit RW se haga 0 (porque dicho bit se pone en 1 cuando hay transferencia sobre el bus).
  El cambio fue muy sencillo, quedando la rutina de esta manera

Código: C
  1. char write_i2c (unsigned char data)
  2.   {
  3.     while (( SSPCON2 & 0x1F ) || RW );
  4.     SSPBUF = data;
  5.     while (RW == 1);
  6.     return ACKSTAT;
  7.   }


  Y así ya me deja hacer polling sobre el bit ACK para saber cuando termina el proceso de escritura de la memoria.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas