9 years ago.

ATMEL AT24C512 EEPROM LIBRARY

I had some experience to find a suitable EEPROM 24C512 library for Arduino Due platform, and it really helped me to solve my problems efficiently and quickly.

But in STM24F407 platform i tried different libraries both from "mbed import library" and from cookbook menu. But unfortunately couldn't solve my problem.

I tried to organize some code over official I2C library but result was disappointing...

So at the moment, I would like to know and need support about suitable and effective library for AT24C512 EEPROM. If anyone experinced and tried any library i wish to knoıw....

Regards...

2 Answers

9 years ago.

Try here, I have used a similar library, however there are problems searching on Mbed at the moment so I can't find the exact library I used.

One more issue, actually a continuing issue, ST appears not to be very Mbed friendly, so don't hold your breath, it may not work.

http://developer.mbed.org/users/bborredon/code/eeprom/

edit..

This is the library I used and here is my program that worked, you will need to change the oled.printf functions to suit your display.

The first part checks for connected i2c devices, then writes RTC time stamp to the eeprom and reads back the result.

eeprom

#include "mbed.h"
#include "eeprom.h"
#include "OLED32028P1T.h"


//OLED32028P1T oled(p13, p14, p29);   // Oled Display tx, rx, rs
OLED32028P1T oled(p28, p27, p29);   // Oled Display tx, rx, rs

EEPROM rom(p9, p10, 0, EEPROM::T24C32);
I2C i2c(p9, p10); // I2C device sda, scl

Timer timer;

int n,x;
int RomAddress;
int rdata,wdata;
int hour,minute,second,dayofweek,dayofmonth,month,year;
int RTCsecond,RTCminute,RTChour,RTCdayofweek,RTCdayofmonth,RTCmonth,RTCyear; 

char buffer[32];

void RTCread();

struct tm t;

int main() {
    
    
    oled.init();
    oled.eraseScreen();
    oled.setTextBackgroundType(TEXT_OPAQUE);
    oled.setFontColor(WHITE);
        
        oled.printf("I2C Searching!");
        oled.locate(0,2);
        
        int count = 0;
        for (int address=0; address<256; address+=2) {
            if (!i2c.write(address, NULL, 0)) { // 0 returned is ok
                oled.setFontColor(GREEN);
                oled.printf("I2C address 0x%02X\n", address);
                count++;
            }
        }
        oled.setFontColor(CYAN);
        oled.locate(0,7);
        oled.printf("%d devices found\n", count);
        oled.locate(0,12);
        oled.setFontColor(YELLOW);
        
        
        
        while (RomAddress < 4096){
            
         
                while (n<10){
                
                    time_t seconds = time(NULL);
                    
                    wdata = seconds;
                    rom.write(RomAddress,wdata); wait_ms(1);
                                
                    rom.read(RomAddress,rdata);
                    float memused = RomAddress;
                    oled.locate(0,n+10);               
                    oled.printf("Address %04d   data  %d  %d \n", RomAddress, rdata, rom.getError());
                    if(rom.getError()==2) {rdata=0;}                   
                    
                    RTCread();
                    
                    oled.locate(10,22);
                    oled.printf("%2d:%02d:%02d  ",RTChour,RTCminute,RTCsecond);
                    oled.printf("%d-%02d-20%02d",RTCdayofmonth,RTCmonth,RTCyear); 
                    
                    oled.locate(10,24);oled.printf("%3.2f %% Memory used", memused/4096*100);
                    n++;RomAddress=RomAddress+4; 
                
                    wait(1);
                }
                
             n=0;      
            }
    
        oled.printf("Finished");
     
}

void RTCread()
{
                time_t seconds = rdata;               

                strftime(buffer, 2,"%S", localtime(&seconds));
                RTCsecond = atoi(buffer);
                strftime(buffer, 2,"%M", localtime(&seconds));
                RTCminute = atoi(buffer);                       
                strftime(buffer, 2,"%H", localtime(&seconds));
                RTChour = atoi(buffer);
                strftime(buffer, 2,"%d", localtime(&seconds));                                
                RTCdayofmonth = atoi(buffer);
                strftime(buffer, 2,"%w", localtime(&seconds));                
                RTCdayofweek = atoi(buffer);
                strftime(buffer, 2,"%m", localtime(&seconds));
                RTCmonth = atoi(buffer);
                strftime(buffer, 2,"%y", localtime(&seconds));
                RTCyear = atoi(buffer);
} 

Accepted Answer

After searching some codes on the net and reading the 24C512 manual, i prepared the below code... The result is always 255 on Tera Term serial terminal... Any suggestions or solutions?

Thanks

#include "mbed.h"




unsigned int value = 1;       // Write data to address 1
char lsb = (value & 0xFF);    // LSB of address
char msb = (value >> 8);      // MSB of address


char result;


char address = 0xA0;    // 10100000  --- A1 and A2 is ground.. Write sequence (Last bit is 0)
char address2 = 0xA1;   // 10100001  --- A1 and A2 is ground.. Read sequence (Last bit is 1)
char data = 2;           // Data to write address 1


I2C i2c(I2C_SDA, I2C_SCL);
Serial pc(SERIAL_TX, SERIAL_RX);



int main()
{
    i2c.frequency(400000);              // EEPROM connection in Hertz
    pc.printf("%s\n", "Hi EEPROM");
    
    // EEPROM WRITE BYTE
    i2c.start();
    int ok1 = i2c.write(address);
    if (ok1 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }

    int ok2 = i2c.write(msb);
    if (ok2 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    int ok3 = i2c.write(lsb);
    if (ok3 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    int ok4 = i2c.write(data);
    if (ok4 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    i2c.stop();
    wait_ms(500);

    // EEPROM READ BYTE (RANDOM)
    i2c.start();
    int ok5 = i2c.write(address);
    if (ok5 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    int ok7 = i2c.write(address2);
    if (ok7 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    int ok8 = i2c.write(msb);
    if (ok8 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    int ok9 = i2c.write(lsb);
    if (ok9 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    i2c.start();                        // Restart for random reading 
    int ok6 = i2c.write(address2);
    if (ok6 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    wait_ms(20);
    
    
    // Lets collect result if we can :)
    result = i2c.read(0);
    i2c.stop();
    


    pc.printf("%u\n", result);

}

posted by Kamil M 24 Apr 2015

The read sequence has a wrong structure. You need to remove the part related to ''Ok7'' .

    // EEPROM READ BYTE (RANDOM)
    i2c.start();
    int ok5 = i2c.write(address);
    if (ok5 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    int ok8 = i2c.write(msb);   //Set the address for random read
    if (ok8 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    int ok9 = i2c.write(lsb);
    if (ok9 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    i2c.start();                        // Restart for random reading 
    int ok6 = i2c.write(address2);
    if (ok6 == 0) {
        pc.printf("%s\n", "Ok");
    } else {
        pc.printf("%s\n", "NOT OK");
    }
    wait_ms(20);

You may also want to use the blockread and write operations rather than the individual byte ops since these are not always correctly supported for all mbed platforms. I assume you have pull-up Rs installed and you do get I2C acknowledges on the slave address.

posted by Wim Huiskamp 24 Apr 2015

Hi Paul,

I can say that THIS EEPROM.H is nice... Solved my problem at last with very basic and effective usage :)

Thanks...

Thanks to everyone who supports...

Regards..

my basic code is:

#include "mbed.h"
#include "eeprom.h"

int rdata;

EEPROM rom(I2C_SDA, I2C_SCL, 0, EEPROM::T24C512);       // AT24C512 EEPROM usage
I2C i2c(I2C_SDA, I2C_SCL); // I2C device sda, scl

Serial pc(SERIAL_TX, SERIAL_RX);


int main(){
    rom.read(1, rdata);         // Read EEPROM address 1 first
    pc.printf("%u\n", rdata);   // Print it
    rom.write(1 ,80);           // Write 80 to EEPROM address 1
    wait_ms(50);
    rom.read(1, rdata);         // Re-read EEPROM address 1, NOW IT CHANGES !!!
    pc.printf("%u\n", rdata);   // Print it !!!!!!!
    }
posted by Kamil M 24 Apr 2015
9 years ago.

Hi Kamil,

Please check my code as for use of the i2c structure usage with an EEPROM

http://developer.mbed.org/users/martinsimpson/code/EEPROM_Nucleo_i2c_master/

eg i2c.read(i2caddressofdevice,*array,NumberOfBytes)

(not sure what i2c.read(0) would actually produce)

Kind Regards

Martin

Thank for support Martin. I'll try and post the result. İ2c.read(0) means dont expect ack from eeprom i think.

posted by Kamil M 24 Apr 2015

This code is for a 2kbit EEPROM (256 bytes). Kamil uses a larger device (512) and needs extended addressrange of 2 bytes. You could modify this code to use the I2C blockwrites rather than the single byte instructions that Kamils example above shows. Note Martins code set the addressbit 0 to indicate read/write. That is automatically taken care of in the mbed I2C block read/write operations. You only need to do that yourself when using the I2C byte read/write operations.

posted by Wim Huiskamp 24 Apr 2015

Hi Martin;

With your permission, I have made some modification in your code to make it simpler, may be... The eeprom_read function is almost same with yours... But i wish to return this function a char (byte) for me to pass it my variable.. The function is below:

void read_eeprom(int address)
{
    char ucdata_write[1];
    char ucdata_read[1];
    ucdata_write[0] = address; //Address here to read
    while (i2c.write((AT24C512_ADDR|WRITE), ucdata_write, 1, 0)) {} //Wait for ACK if EEPROM is in 'write' cycle
    i2c.read((AT24C512_ADDR|READ), ucdata_read, 1, 0); //Note 'OR' Address with Read bit
    //pc.printf("%#X %c",ucdata_read[0],ucdata_read[0]);
    return ucdata_read[0];        // This line does not work...
}

I wish the last line of the code returns me the value of the eeprom address.. Any solution?

Regards

posted by Kamil M 24 Apr 2015

Hello Wim,

The only I2C read/write byte operations at the moment is suitable for me... My device configuration to save and read is not too long... And i can merge or seperate the values of two address of EEPROM with bit shifting operations, if it is higher than 0xFF...

addition... The mbed I2C routine did not solve my problem, even it says auto adding (changing) 0 or 1 for write or read... My device address is 10100000 = 0xA0 (also for write) and 10100001 = 0xA1 for read... (A pins are grounded)...2k2 pull ups added...

Martins' code seems solve my problem, since i can read his name's characters on Tera Term, may be because of DEVICE_ADDRESS | READ or WRITE ... I dont know...

posted by Kamil M 24 Apr 2015

Ok, sorry for repeated problems but the output from Terra Term for Martin's code is

Hello World at 115200 BAUD and 400KHz i2c Frequency
Using mbed.org Martin
0xfa 0xFF ÿ
0xfb 0xFF ÿ
0000 M  0001 a  0002 r  0003 t  0004 i  0005 n
0XFF ÿ  0XFF ÿ  0XFF ÿ  0XFF ÿ  0XFF ÿ  0XFF

0XFF ÿ  0XFF ÿ  0XFF ÿ  0XFF ÿ  0XFF ÿ  0XFF

Still 0xFF..

posted by Kamil M 24 Apr 2015

OK a few comments "array[number]=variable" will assign the numbered element in an array with the contents of variable "return array[number]" Returns the contents of the numbered element so in my example the contents of the EEPROM address.

Why do I use the following line? "while (i2c.write((AT24C512_ADDR|WRITE), ucdata_write, 1, 0)) {} Wait for ACK if EEPROM is in 'write' cycle"

This is because on page 5 and 9 of the data sheet for the EEPROM there is a finite time between write cycles it would be inefficient to just wait for a time period so the program 'polls' the I2C for the EEPROM address untill the ACK reappears to indicate th EEPROM is ready.

Since the data sheet states this can be from 5 to 10ms just waiting 50ms would be time consuming. Polling as above would increase write speed by 5 to 10 times.

The ORing of the READ/WRITE bit in the addressing is not necessary except to help others appreciate what is happening in reality.

Hope this clarifies the code it was an exercise for others to see how to get simple I2C operations and simple EEPROM addressing read/write cycles.

Best Regards

Martin

posted by Martin Simpson 28 Apr 2015