Hello every body, since a few months i try to play with an eeprom 24lc512, at first i have been using the component 24AA_EEPROM but when i try to read more than two strings seems that my code only was storing the last data and i can't read correctly an specific address, then i try to follow the data sheet and do the task using bit io .I get a perfect work writing and reading bytes the following is the code:
/*
* I2C_24LC512.c
*
* Created on: 15/09/2015
* Author: ingeniero03
*/
#include "Cpu.h"
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "I2C_24LC512.h"
#include "string.h"
volatile unsigned char aaa;
void Ret5us (void);
void NOP4 (void); // OK
void NotBusy (void); // OK
void StopBit (void); // OK
void StartBit (void); // OK
unsigned char LeerAck (void); // OK
void LeerNOAck (void);
void E_ByteI2C (unsigned char datoI2C); // OK
unsigned char L_ByteI2C (void); // OK
unsigned char LeerByteI2C (unsigned int addT); // OK
void EscribirByteI2C (unsigned int addT, unsigned char datoI2C); // OK
void E_BloqueI2C (char datoI2CB); // OK
char L_BloqueI2C (void); // OK
char LeerBloqueI2C (unsigned int addT); // OK
void EscribirBloqueI2C (unsigned int addT, char datoI2CB[]); // OK
unsigned char addrL, addrH, valorACK;
char addrLB, addrHB, valorACKB;
volatile unsigned char aaa;
unsigned char temp, tickEE;
int i;
char bloqueleido[64];
/*
* NOMBRE: EscribirByteI2C
* ENTRADAS: Direccion de memoria a escribir
* Dato a escribir
* SALIDAS: Ninguna
* DESCRIPCION: Escribe un dato en la memoria I2C
*/
void EscribirByteI2C (unsigned int addT, unsigned char datoI2C)
{
addrH = (unsigned char)(addT>>8);
addrL = (unsigned char)(addT);
NotBusy ();
StartBit ();
E_ByteI2C (CONTROL_E);
if ( !LeerAck() ) { E_ByteI2C(addrH); }
else { goto parar; }
if ( !LeerAck() ) { E_ByteI2C(addrL); }
else { goto parar; }
if ( !LeerAck() ) { E_ByteI2C(datoI2C); }
valorACK = LeerAck();
parar:
StopBit ();
}
/*
* NOMBRE: LeerByteI2C
* ENTRADAS: Direccion a leer
* SALIDAS: Error
* DESCRIPCION: Lee una posicion en la memoria EEPROM
* retorna 0 si hubo lectura correcta
* retorna 1 si no hubo lectura correcta
*/
unsigned char LeerByteI2C (unsigned int addT)
{
addrH = (unsigned char)(addT>>8);
addrL = (unsigned char)(addT);
valorACK = 0xFF;
NotBusy ();
StartBit ();
E_ByteI2C (CONTROL_E);
if ( !LeerAck() ) { E_ByteI2C(addrH); }
else { goto detener; }
if ( !LeerAck() ) { E_ByteI2C(addrL); }
else { goto detener; }
if ( !LeerAck() )
{
NotBusy ();
StartBit();
}
else { goto detener; }
E_ByteI2C (CONTROL_L);
if ( !LeerAck() ) { valorACK = L_ByteI2C (); }
LeerNOAck();
detener:
StopBit ();
return valorACK;
}
/*
* NOMBRE: NOP4
* ENTRADAS: Ninguna
* SALIDAS: Ninguna
* DESCRIPCION: Funcion para deliveradamente perder
* algunos ciclos de maquina en tiempo
*/
void NOP4 (void)
{
aaa = 2;
aaa++;
}
/*
* NOMBRE: NotBusy
* ENTRADAS: Ninguna
* SALIDAS: Ninguna
* DESCRIPCION: Coloca desocupado el bus I2C
* Coloca SDA y SCL en alto
*/
void NotBusy (void)
{
SCL_OFF;
Ret5us ();
SDA_OUT;
SDA_ON;
SCL_ON;
Ret5us ();
}
/*
* NOMBRE: StartBit
* ENTRADAS: Ninguna
* SALIDAS: Ninguna
* DESCRIPCION: Coloca un bajo en SDA, cuando SCL esta en alto
* Debe ejecutarse antes la funcion NotBusy
*/
void StartBit (void)
{
SDA_OUT;
SDA_OFF;
Ret5us ();
}
/*
* NOMBRE: E_ByteI2C
* ENTRADAS: datoI2C, unsigned char
* SALIDAS: Ninguna
* DESCRIPCION: Manda el valor en datoI2C, por los pines I2C
* Envia primero el bit mas significativo
* Cada bit cambia cuando SCL esta en bajo
*/
void E_ByteI2C (unsigned char datoI2C)
{
unsigned char datoRRF, RRF;
SCL_OFF;
SDA_OUT;
datoRRF = 128;
for (RRF=0; RRF<8; RRF++)
{
SCL_OFF;
NOP4();
NOP4();
if ( ( datoI2C & datoRRF ) == datoRRF ) { SDA_ON; }
else { SDA_OFF; }
Ret5us ();
SCL_ON;
NOP4();
NOP4();
Ret5us ();
datoRRF = datoRRF>>1;
}
}
/*
* NOMBRE: L_ByteI2C
* ENTRADAS: Ninguna
* SALIDAS: El Dato I2C leido
* DESCRIPCION: Recibe un dato I2c
* Recibe primero el bit mas significativo
* Lee cada bit cuando SCL esta en alto
*/
unsigned char L_ByteI2C (void)
{
unsigned char datoRRF, RRF, datoLeido;
SCL_OFF;
SDA_INP; // SDA como entrada
datoRRF = 128;
datoLeido = 0;
for (RRF=0; RRF<8; RRF++)
{
SCL_OFF;
NOP4();
NOP4();
Ret5us ();
SCL_ON;
Ret5us ();
if ( SDA_IO ) {datoLeido = (datoLeido | datoRRF); }
NOP4();
NOP4;
datoRRF = datoRRF>>1;
}
SDA_OUT;
return datoLeido;
}
/*
* NOMBRE: LeerAck
* ENTRADAS: Ninguno
* SALIDAS: Valor de ACK, Unsigned char
* DESCRIPCION: Con cada Byte enviado o recibido, el esclavo debe enviar un caracer de
* reconocimiento, que consiste en colocar la linea SDA en bajo
* El Maestro por su parte debe enviar un pulso de reloj adicional para tal fin
* LeerAck = 0, si el esclavo envio el ACK
* LeerAck = 1, si el esclavo NO envio el ACK
*/
unsigned char LeerAck (void)
{
unsigned char lecturaACK;
SCL_OFF;
SDA_INP;
Ret5us ();
NOP4;
NOP4;
SCL_ON;
NOP4;
NOP4;
if (SDA_IO == 0) { lecturaACK = 0; }
else { lecturaACK = 1; }
Ret5us ();
return lecturaACK;
}
/*
* NOMBRE: LeerNOAck
* ENTRADAS: Ninguno
* SALIDAS: nINGUNO
* DESCRIPCION: Pulso adicional necesario para
* el bit de reconocimiento
*
*/
void LeerNOAck (void)
{
SDA_INP;
SCL_OFF;
Ret5us ();
SDA_OUT;
SDA_OFF;
SCL_ON;
Ret5us ();
}
/*
* NOMBRE: StopBit
* ENTRADAS: Ninguna
* SALIDAS: Ninguna
* DESCRIPCION: Bit de stop para comunicacion I2C
* Flanco de subida de SDA
* mientras SCL esta en alto
*/
void StopBit (void)
{
SCL_OFF;
NOP4;
NOP4;
SDA_OUT;
SDA_OFF;
Ret5us ();
SCL_ON;
NOP4;
NOP4;
SDA_ON;
Ret5us ();
}
/*
* NOMBRE: Ret5us
* ENTRADAS: Ninguna
* SALIDAS: Ninguna
* DESCRIPCION: Retardo de 15 micro segundos
* Utiliza la variable tickEE que se incrementa cada 5 microsegundos
* en una interrupcion de tiempo.
* Es Obligatorio tener una interrupcion de tiempo de 5 microsegundos
* que incremente la variable tickEE
*/
void Ret5us (void)
{
tickEE = 0;
while (tickEE<2) {}
}
With that i try to modify the writing cicles before the star and sending the control bytes for write blocks or pages or strings but i have no lucky this time, it seems i can't write and read more than one char , the next was the code that i try:
void EscribirBloqueI2C (unsigned int addT, char datoI2CB[])
{
addrHB = (char)(addT>>8);
addrLB = (char)(addT);
NotBusy ();
StartBit ();
E_BloqueI2C (CONTROL_E);
if ( !LeerAck() ) { E_BloqueI2C(addrHB); }
else { goto parar; }
if ( !LeerAck() ) { E_BloqueI2C(addrLB); }
else { goto parar; }
for(i=0 ; i <strlen(datoI2CB);i++){
if ( !LeerAck() ) { E_BloqueI2C(datoI2CB[i]);
}
valorACK = LeerAck();
parar:
StopBit ();
}
char LeerBloqueI2C (unsigned int addT)
{
addrHB = (char )(addT>>8);
addrLB = (char )(addT);
valorACK = 0xFF;
NotBusy ();
StartBit ();
E_BloqueI2C (CONTROL_E);
if ( !LeerAck() ) { E_BloqueI2C(addrHB); }
else { goto detener; }
if ( !LeerAck() ) { E_BloqueI2C(addrLB); }
else { goto detener; }
if ( !LeerAck() )
{
NotBusy ();
StartBit();
}
else { goto detener; }
E_BloqueI2C (CONTROL_L);
for(i=0 ; i < sizeof(bloqueleido)-1;i++){
if ( !LeerAck() ) {bloqueleido[i] = L_BloqueI2C (); }
}
LeerNOAck();
detener:
StopBit ();
return valorACK;
}
void E_BloqueI2C (char datoI2CB)
{
char datoRRFB, RRFB;
SCL_OFF;
SDA_OUT;
datoRRFB = 128;
for (RRFB=0; RRFB<8; RRFB++)
{
SCL_OFF;
NOP4();
NOP4();
if ( ( datoI2CB & datoRRFB ) == datoRRFB ) { SDA_ON; }
else { SDA_OFF; }
Ret5us ();
SCL_ON;
NOP4();
NOP4();
Ret5us ();
datoRRFB = datoRRFB>>1;
}
}
char L_BloqueI2C (void)
{
char datoRRFB, RRFB, datoLeidoB;
SCL_OFF;
SDA_INP; // SDA como entrada
datoRRFB = 128;
datoLeidoB = 0;
for (RRFB=0; RRFB<8; RRFB++)
{
SCL_OFF;
NOP4();
NOP4();
Ret5us ();
SCL_ON;
Ret5us ();
if ( SDA_IO ) {datoLeidoB = (datoLeidoB | datoRRFB); }
NOP4();
NOP4;
datoRRFB = datoRRFB>>1;
}
SDA_OUT;
return datoLeidoB;
}
Some body can help me? i dont know what i am doing wrong :smileyconfused:
Hello,
I am sorry but I am not able to verify your driver code.
Please, look at the Driver for Microchip 24xx Serial EEPROM | MCU on Eclipse technical user guide document where the driver for 24LC512 is described by using the 24AA_EEPROM component. I hope it will help you.
Best Regards,
Marek Neuzi
Thank you for answer myf question , but this tutorial i was follow at first , but i can't read an specific memory address. if i choose readbyte or read block and write byte/ block and an specific adrees like 0X0A and store a data like 3 and after repeat the same process but this time the adress 0X13 and store the data 2 . when i try to read the 0X13 i got return the data 3.
Hello,
I am sorry but I am not able to use your driver and debug the application (it is fragment of your application and I have not also the eeprom device).
Please, look at the datasheet of your eeprom device and verify the configuration (control byte, chip selection address, address range and so on).
Do you execute acknowledge polling after writing data into eeprom device? There is possible that you don't allow the device to write data, i.e. when you execute writing of a block of data the application must wait until all data are internally flashed into eeprom device.
For example there is stated in a 24LC512 datasheet:
ACKNOWLEDGE POLLING
Since the device will not acknowledge during a write
cycle, this can be used to determine when the cycle is
complete (this feature can be used to maximize bus
throughput). Once the Stop condition for a Write
command has been issued from the master, the device
initiates the internally timed write cycle. ACK polling
can be initiated immediately. This involves the master
sending a Start condition, followed by the control byte
for a Write command (R/W = 0). If the device is still
busy with the write cycle, then no ACK will be returned.
If no ACK is returned, then the Start bit and control byte
must be re-sent. If the cycle is complete, then the
device will return the ACK and the master can then
proceed with the next Read or Write command. See
Figure 7-1 for flow diagram
Best regards,
Marek Neuzil