No luck using Wixel with 24LC1025 EEPROM

I’m trying to use EEPROM memory 24LC1025 but no luck so far. Here’s my write and read functions:

unsigned char EEPROM1k_b0_WA=0xA0;     
unsigned char EEPROM1k_b0_RA=0xA1;

void writeByteEEPROM(uint16 eeaddress, unsigned char mData)
    {
        uint8 rdata=mData;
        i2cStart();
        i2cWriteByte(EEPROM256_WA);             // control byte address of EEPROM 24LC1025
        delayMs(5);
        MSB=eeaddress >> 8;
        i2cWriteByte(MSB);             
        delayMs(5);
        LSB=eeaddress & 0xFF;
        i2cWriteByte(LSB);           
        delayMs(5);
        i2cWriteByte(rdata);                         // data byte to be saved
        delayMs(5);
        i2cStop();
        printf("%u was written to address %x, MSB %x and LSB %x \r\n", rdata, eeaddress, MSB, LSB);
    }

uint8 readByteEEPROM(uint16 eeaddress)        
    {
        i2cStart();
        i2cWriteByte(EEPROM256_WA);
        MSB=eeaddress>>8;
        i2cWriteByte(MSB);
        delayMs(5);
        LSB=eeaddress&0xFF;
        i2cWriteByte(LSB);
        delayMs(5);
        i2cStart();
        i2cWriteByte(EEPROM256_RA);
        delayMs(5);
        i2cbyte=i2cReadByte(1);
        i2cStop();
        printf("%x read from address %u", i2cbyte, eeaddress);
        return(i2cbyte);
    }

I also have the following running in the main() function:

    i2cPinScl = param_I2C_SCL_pin;
    i2cPinSda = param_I2C_SDA_pin;
    i2cSetFrequency(param_I2C_freq_kHz);
    i2cSetTimeout(param_I2C_timeout_ms);

I’m not sure whether the failure is due to the write function or read function or something else needed in the main(). Response to the read function yield FF or 255 for any byte address.

Can you give me any guidance here? Is something needed like an equivalent to Arduino’s wire.begin() or wire.available() functions?

Hello.

I have moved your post to its own topic, because the topic you posted it in is not about the same EEPROM memory.

I noticed that in your code you use a lot of global variables that could probably be local variables instead, and you didn’t show us the definitions of those global variables. Also, you didn’t tell us what I2C frequency you are using or tell us anything about your wiring. I recommend simplifying your system as much as possible and giving us all the relevant information (including your complete source code and wiring) so we can help you find problems.

Do you have an Arduino and have you succeeded in talking to the EEPROM with your Arduino?

Do you have an oscilloscope available? Probing the two I2C data lines would be a great way to tell what part of your system isn’t behaving as expected. It could either be the Wixel or the EEPROM, and it could either be during the writing or the reading.

–David

Hi David,

True, I need to tidy up my use of global and local variables. The I2C frequency being used is 400 kHz. I don’t have an Arduino so I cannot test it the EEPROM on that. However, I have successfully used I2C on the Wixel for reading/writing to a real time clock (DS1307). I have not tried an oscilloscope yet, however I suspect that my problem is with the EEPROM rather than the Wixel’s I2C given that the RTC works. I also suspect that the write operation is failing as the read outputs FF which are the default values stored on the EEPROM. Full code and wiring diagram are as follows:

// EEPROM MEMORY USING I2C BASED ON PREVIOUS CODE WRITTEN FOR DS1307 REAL TIME CLOCK (RTC)

// NOTE: To access the I2C functions in this code, copy "options.mk" from <serial_i2c> directory into the directory of this C code

/* Dependencies ***************************************************************/

#include <cc2511_map.h>
#include <board.h>
#include <time.h>
#include <gpio.h>
#include <i2c.h>
#include <wixel.h>
#include <usb.h>
#include <usb_com.h>
#include <string.h>
#include <stdlib.h>


/* Global Constants & Variables ***********************************************/

int32 CODE param_I2C_SCL_pin = 10;
int32 CODE param_I2C_SDA_pin = 11;
int32 CODE param_I2C_freq_kHz = 400;
int32 CODE param_I2C_timeout_ms = 10;

uint8 XDATA report[128]; //Big buffer for holding report (string input). DM changed back to 128
uint16 DATA reportLength = 0; //Length (in bytes) of report currently in buffer, if zero then buffer is empty
uint16 DATA reportBytesSent = 0; //Number of bytes in current report that have already been sent to computer via USB
uint8 byteCommand[32]={0}; // variables to store bytes received from USB
uint8 byteCommandCounter = 0; // variables to store bytes received from USB
void frequentTasks(void);
void delaySeconds(uint8);
void putchar(char);
void processBytesFromUsb(void);
void sendReportToUsb(void);
void processUserCommand(void);


unsigned char tsec,cmin,tmin,thour,tday,tdate,tmonth,tyear;
uint8 second, minute, hour, date, month, year; // change to day and date instead of ...OfWeek, OfMonth
uint16 byte,hex;
uint8 i2cbyte,dec,time,logValue,mem1,mem2;
unsigned char dsec,dmin,dhour,dday,ddate,dmonth,dyear;
uint8 nsec,nmin,nhour,nday,ndate,nmonth,nyear;
uint8 hexToDec(uint16);
uint16 decToHex(uint8);
unsigned char MSB, LSB;

unsigned char DS1307_WA=0xD0;       	// 0xD0 = 11010000 in binary. I2C address of DS1307 is 1101000, subsequent 0 denotes write direction
unsigned char DS1307_RA=0xD1;       	// 0xD1 = 11010001 in binary. I2C address of DS1307 is 1101000, subsequent 1 denotes read direction
unsigned char EEPROM1k_b0_WA=0xA0;     	// 0xA0 = 10100000 is write address for EEPROM 24LC1025. 1010 is the chips control byte, 0 is the first 512kb sector, next tow 0s denote A1 and A0 at GND, final 0 denotes write direction
unsigned char EEPROM1k_b0_RA=0xA1;     	// 0xA1 = 10100001 is read address for EEPROM 24LC1025 first 512kb sector
unsigned char EEPROM1k_b1_WA=0xA8;     	// 0xA0 = 10101000 is write address for EEPROM 24LC1025. 1010 is the chips control byte, 1 is the second 512kb sector, next tow 0s denote A1 and A0 at GND, final 0 denotes write direction
unsigned char EEPROM1k_b1_RA=0xA9;     	// 0xA1 = 10101001 is read address for EEPROM 24LC1025 second 512kb sector
unsigned char EEPROM256_WA=0xA4;     	// 10100100 is write address for EEPROM 24LC256 (if pins set to same as 1kB)
unsigned char EEPROM256_RA=0xA4;     	// 10100101 is read address for EEPROM 24LC256 (if pins set to same as 1kB)

uint16 intlMemAddr=0x0001;              // overall counter for internal address location. 16 bit value, will be split into MSB and LSB.


/*  ************************************** RTC FUNCTIONS ******************************************************************************/

void Write_DS1307(unsigned char Addr, unsigned char Data)
{
    i2cStart();
    i2cWriteByte(DS1307_WA);
    i2cWriteByte(Addr);         	// Addr is the registor address (i.e. 0x00 to 0x07) specified at input
    i2cWriteByte(Data);
    i2cStop();
}

Read_DS1307(unsigned char Addr)
{
    i2cStart();
    i2cWriteByte(DS1307_WA);
    i2cWriteByte(Addr);
    i2cStart();
    i2cWriteByte(DS1307_RA);
    i2cbyte=i2cReadByte(1);     	// If 1, a NACK will be sent to the slave device instead of an ACK after this byte is received. (This is used to signal conclusion of a transfer from the slave to the master.)
    i2cStop();
    return(i2cbyte);  			//byte from ReadByte
}


void displayTime(void)
{
    nsec=hexToDec(Read_DS1307(0x00));
    nmin=hexToDec(Read_DS1307(0x01));
    nhour=hexToDec(Read_DS1307(0x02) & 0b111111);   // "& 0b111111" allows 24-hour clock to be read properly
    //dday=hexToDec(Read_DS1307(0x03));             // day, a number in range 1-7 representing day of week, is neglected here as unnecessary
    ndate=hexToDec(Read_DS1307(0x04));
    nmonth=hexToDec(Read_DS1307(0x05));
    nyear=hexToDec(Read_DS1307(0x06));
    printf("%02u/%02u/%02u %02u:%02u:%02u \r\n",ndate,nmonth,nyear,nhour,nmin,nsec);
}

uint8 hexToDec(uint16 hexValue)
{
    uint8 truncValueHex = hexValue / 16;
    uint8 decCalc = hexValue - (truncValueHex * 6);
    return decCalc;
}

uint16 decToHex(uint8 decValue)
{
    uint8 truncValueDec = decValue / 10;
    uint16 hexCalc = (16*truncValueDec)+decValue%10;
    return hexCalc;
}


// ---   ---   ---   ---   ---   ---  EEPROM FUNCTIONS  ---   ---   ---   ---   ---   ---   ---   ---   ---   ---   ---   ---   ---   ---   /

void writeByteEEPROM(uint16 eeaddress, unsigned char mData)
    {
        uint8 rdata=mData;
        i2cStart();
        i2cWriteByte(EEPROM256_WA);             // control byte address of EEPROM 24LC1025 - need something to check use of b0 or b1
        delayMs(5);
        MSB=eeaddress >> 8;
        i2cWriteByte(MSB);             // takes the first 8 bits (MSB) of the 16-bit intlAddr
        delayMs(5);
        LSB=eeaddress & 0xFF;
        i2cWriteByte(LSB);           // compares the 16-bit intlAddr (xxxxxxxxXXXXXXXX) with 11111111 (0xFF), thus extracting the second 8-bits (LSB)
        delayMs(5);
        i2cWriteByte(rdata);                         // data byte to be saved
        delayMs(5);
        i2cStop();
        printf("%u was written to address %x, MSB %x and LSB %x \r\n", rdata, eeaddress, MSB, LSB);
    }

// page write: writes up to 128 bytes. After receipt of each byte, seven lower address pointer bits are incremented by 1

uint8 readByteEEPROM(uint16 eeaddress)        // void was uint16 intlMemAddr
    {
        i2cStart();
        i2cWriteByte(EEPROM256_WA);
        MSB=eeaddress>>8;
        i2cWriteByte(MSB);
        delayMs(5);
        LSB=eeaddress&0xFF;
        i2cWriteByte(LSB);
        delayMs(5);
        i2cStart();
        i2cWriteByte(EEPROM256_RA);
        delayMs(5);
        i2cbyte=i2cReadByte(1);
        i2cStop();
        printf("%x read from address %u", i2cbyte, eeaddress);
        return(i2cbyte);
    }

void writeReadEEPROMtest(void)			// an example function to write 0x77 to address 0001000100010001; does not work as 0xFF or 255 is read back
    {
        i2cStart();
        i2cWriteByte(0xA0);     delayMs(5);     // writes 1010-0000 for control byte write
        i2cWriteByte(0x11);     delayMs(5);     // writes 0001-0001 for address high byte
        i2cWriteByte(0x11);     delayMs(5);     // writes 0001-0001 for address low byte
        i2cWriteByte(0x77);     delayMs(5);     // writes 0111-0111 (dec 119) for data to be stored
        i2cStop();
        printf("Value 0x77 or decimal 119 written to memory location 0001000100010001 \r\n");		
        delaySeconds(2);

        i2cStart();
        i2cWriteByte(0xA1);     delayMs(5);     // // writes 1010-0001 for control byte read
        mem1=i2cReadByte(1);
        i2cStop();
        printf("Current address should have been read to yield %x \r\n", mem1);

        i2cStart();
        i2cWriteByte(0xA0);     delayMs(5);     // writes 1010-0001 for control byte write
        i2cWriteByte(0x11);     delayMs(5);     // writes 0001-0001 for address high byte
        i2cWriteByte(0x11);     delayMs(5);     // writes 0001-0001 for address low byte
        i2cStart();
        i2cWriteByte(0xA1);     delayMs(5);     // // writes 1010-0001 for control byte read
        mem2=i2cReadByte(1);
        i2cStop();
        printf("Specific address (0001000100010001) should have been read to yield %x \r\n",mem2);
    }

//******************************  MAIN() FUNCTION  ************************************************************************************************/

void main()
{
    systemInit();
    usbInit();

    i2cPinScl = param_I2C_SCL_pin;
    i2cPinSda = param_I2C_SDA_pin;
    i2cSetFrequency(param_I2C_freq_kHz);	// sets frequency to 400 kHz as per 24LC1025 specs
    i2cSetTimeout(param_I2C_timeout_ms);
           
    

    while(1)
    {
        frequentTasks();
        
    }

}

//*******************************  OTHER NON-I2C FUNCTIONS  ***************************************************************************************/

void frequentTasks() 			//function for calling the services below, needs to be iterated every 50 ms to keep everything running smoothly
{
    boardService();
    usbComService();
    processBytesFromUsb();
    sendReportToUsb();	
}

void putchar(char c)  			//populates report buffer to be later sent from HyterTerminal via USB
{
    report[reportLength] = c;
    reportLength++;
}

void delaySeconds(uint8 seconds)  	//enables seconds delay, allowing USB comms every 50 milliseconds
{

     while(seconds--)
     {
         uint8 i;
         for(i=1;i<=20;i++)
         {
             delayMs(50);
             frequentTasks();
         }
     }
 }


void sendReportToUsb()
{
    uint8 bytesToSend;
    // Send the report to USB in chunks.
    if (reportLength > 0)
    {
        bytesToSend = usbComTxAvailable();
        if (bytesToSend > reportLength - reportBytesSent)
        {
            // Send the last part of the report.
            usbComTxSend(report+reportBytesSent, reportLength - reportBytesSent);
            reportLength = 0;
        }
        else
        {
            usbComTxSend(report+reportBytesSent, bytesToSend);
            reportBytesSent += bytesToSend;
        }
    }
}

void processBytesFromUsb()
{
    uint8 bytesInRxBuffer = usbComRxAvailable();
    uint8 byteReceived;
    while(bytesInRxBuffer)
        {
            byteReceived = usbComRxReceiveByte();
            if (byteReceived==0x0D) // run when carriage return (ENTER key) entered by user
                {
                    byteCommand[byteCommandCounter] = byteReceived;
                    processUserCommand();
                    memset(&byteCommand[0], 0, sizeof(byteCommand)); 	// set all elements in byteCommand to null
                    byteCommandCounter = 0; 				//reset byteCommandCounter
                }
            else if (byteReceived==0x03) 				//this is the CTRL+C character which will serve as an interupt to other while loop
                {
                    // if necessary, reset all pins etc
                    printf("\r\n>> Reset \r\n>>");
                    while(1)
                        {
                            frequentTasks();
                        }

                }
            else // populate byteCommand byte by byte from USB RX buffer
                {
                    byteCommand[byteCommandCounter] = byteReceived;
                    printf("%c", byteCommand[byteCommandCounter]);
                    byteCommandCounter++;
                }

            bytesInRxBuffer--;
        }

}

void processUserCommand()				// recognises the commands typed into HyperTerminal
{
    char * cmd;
    char delims[] = ", \r";

    cmd = strtok(byteCommand,delims); // parse command

    printf("\r\n");

    if(!strcmp(byteCommand, "\r"))
        {

        }
    else if (!strcmp(cmd, "showtime"))      		// prints date and time to Hyperterminal, updated every second
        {
            while(1)
            {
                displayTime();
                delaySeconds(1);
                frequentTasks();
            }

        }

    else if ((!strcmp(cmd, "settime")))         	// for example: settime 12 02 16 14 32 - set system time to 16/02/2012 14:32
        {
            cmd = strtok(NULL,delims);                  // "strtok" returns a pointer to token in a string
                year=decToHex((atoi(cmd)));             // "atoi" converts string to integer
                Write_DS1307(0x06,year);
            cmd = strtok(NULL,delims);
                month=decToHex((atoi(cmd)));
                Write_DS1307(0x05,month);
            cmd = strtok(NULL,delims);
                date=decToHex((atoi(cmd)));
                Write_DS1307(0x04,date);
            cmd = strtok(NULL,delims);                  //day (i.e. 1-7 representing Mon-Sun, register 0x03, is ignored as being unnecessary)
                hour=decToHex((atoi(cmd)));
                Write_DS1307(0x02,hour);
            cmd = strtok(NULL,delims);                  
                minute=decToHex((atoi(cmd)));
                Write_DS1307(0x01,minute);
            cmd = strtok(NULL,delims);                  
                second=decToHex((atoi(cmd)));
                Write_DS1307(0x00,second);
            displayTime();
        }
    else if (!strcmp(cmd, "test"))      		// function to write 0x77 to address 0001000100010001 and read back from this address
        {
            writeReadEEPROMtest();
        }
    else
        {
            printf(">> Invalid Command\r\n");
        }
    printf(">> ");
}


Following your advice of simplicity, I have written a specific function to write a value to a specified address and read back from that address (writeReadEEPROMtest). However the value is not being written. Compared to Arduino code that I see online, there’s a Wire.begin() function in the main() or an if(wire.available) function in the write function - these seem to be part of Arduino’s wire library. Is something like this necessary for me and if so is there an equivalent in Wixel’s I2C library?

On a side note, I am going to order the EEPROM chip used by the other author (M24C02) to see if that works any easier for me.

Thanks for your help.

Since you are getting 0xFF back from the i2c functions, it is possible that the SDA line is just high the entire time and you are not actually communicating with the EEPROM at all.

I don’t think that Wire.begin() and Wire.available() matter; the former just initializes the I2C module on the Arduino but probably doesn’t do much to the bus. The latter is used for doing backgroud reception of data is definitely doesn’t have an effect on the bus.

Unfortunately, I don’t know what is causing your problem, but maybe someone else who is more familiar with this EEPROM chip will see it.

–David

Any luck on this one?
I am trying the same thing using a 24LC256 and no joy using the i2c lib.
My code is almost an exact dup of yours.

Setup the usual things pins, timeouts etc…

i2cPinScl = 4;
i2cPinSda = 5;
i2cSetFrequency(100);
i2cSetTimeout(500);

void write_eep(int addr, int value)
{	
	temp_hi = hibyte(addr);			// split address into two bytes  
	temp_lo = lobyte(addr); 

	i2cStart();		
	 i2cWriteByte(command_write);
	 i2cWriteByte(temp_hi);
	 i2cWriteByte(temp_lo);
	 i2cWriteByte(value);
    i2cStop();
		
}
int read_eep(int addr)
{	
	temp_hi = hibyte(addr);			// split address into two bytes  
	temp_lo = lobyte(addr); 
	
	i2cStart();			 
	 i2cWriteByte(command_write);
	 i2cWriteByte(temp_hi);
	 i2cWriteByte(temp_lo);
	  i2cWriteByte(command_read);
	  temp_data = i2cReadByte(0);
	i2cStop();

	return temp_data;
}

Hello, jamz_az.

I’m not familiar with these EEPROMs, but one thing I noticed about both your code and collinsf’s is that neither of you are generating a repeated START after sending the read address. A quick glance at the 24LC256 datasheet seems to show that this is necessary, in figure 8-2. Also, you should transmit a NACK after reading the last byte (which is determined by the argument to i2cReadByte). So your read function should probably look like this:

...
i2cStart();
i2cWriteByte(command_write);
i2cWriteByte(temp_hi);
i2cWriteByte(temp_lo);
i2cStart();
i2cWriteByte(command_read);
temp_data = i2cReadByte(1);
i2cStop();
...

Does that give you any better results?

- Kevin

Yup already tried that, doesnt work.
I don’t get it the 24lc’s are standard i2c protocal.
I got it wired right.

These wxl calls do not produce any results on them.
What were these i2c calls tested on device wise during development of this lib?
Maybe I can gleen some insight from that devices datasheet.

I’m fairly sure I tested the I2C library with an LSM303 while we were developing it.

If you have an oscilloscope or logic analyzer and something else that can communicate with the EEPROM succesfully, the best way to debug the problem would probably be to capture both devices communicating with the EEPROM and see what’s different.

- Kevin

Indeed, if i had a logic analyzer I would not be on the forums asking for insight.
I have tried everything from others lib’s ported to bit banging my own.

I have given up on the i2c and now am trying SPI on the MC 25lcxxx series eep.
Will see if that yields any joy.

The best diagnostic tool I ever bought was the $150 Saleae 8-channel logic analyzer. The hardware is okay, but the software is superb (and works well under Linux, too!)

Ok, SPi lib much joy.
Works grand with 25AA320A/25LC320A eep.
No problems at all and works great, plug and play using standard calls.

Not sure what the deal was with i2c (some timing bullcrap prob) but spi is a go so moving on, storing data…