Problem with I2C EEPROM

Status
Not open for further replies.

kyru27

New Member
I think I should be able to read and write the 24LC256 I'm using with the following code:

Code:
#include <p18f4620.h>
#include <i2c.h>

#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config LVP = OFF
#pragma config XINST=OFF
#pragma config OSC=INTIO67

#define CLOCK_FREQ		(80000000ul)      // Hz 

void main(void)
{

char data;

OpenI2C(MASTER, SLEW_OFF);

StartI2C();
WriteI2C(0b10100000); //control byte
WriteI2C(0b00000000); //adr hi
WriteI2C(0b00000000); //adr lo
WriteI2C(0x25); //data 0
StopI2C();

StartI2C();
WriteI2C(0b10100001); //control byte (read data)
WriteI2C(0b00000000); //adr hi
WriteI2C(0b00000000); //adr lo
data=ReadI2C();

StopI2C(); 
}

But, by watching data in debug mode, I get an FF instead of the 25 I think should be reading.

I think I've done everything according to the datasheet (http://www.datasheetcatalog.org/datasheet2/7/0yuw0yc3x0278cpz78zge08qi13y.pdf), even exchanging the chip selection bits to 000 or 111 if it might be the problem, and I guess the schematic is right (I'm showing it anyway).

Any idea of what can be wrong?

Thanks.
 
Last edited:
There has to be a delay between a write and then next command... the datasheet recommend 20mS

ALSO!! the WP pin HAS to be grounded... keeping it high stops inadvertent writes...
 
Can't use the delays , they enter an infinite loop as in my other question (https://www.electro-tech-online.com/threads/problem-with-sample-spi-transmission.127832/) and nothing can be done... Aren't there more libraries for delay functions except for the predetermined ones of MPLAB C18?

I've tried to work around this problem with the following:
Code:
WriteI2C(0b10100000);
retraso(i);
...

retraso (int i)
{
while (i>0)
{
int j=255;
while (j>0)
{
Nop();
j=j-1;
}
i=i-1;
}
}

And this way to produce a delay, but this has 2 problems:

1) I don't how much time the delay really happens.

2) It also loops indefinitely with some values of i.



Any idea of how this could be solved? Thanks.
 
Last edited:
Write your own..... Its dead simple

Code:
void delayUs( int x )
   {
   while(x--)
      {
      NOP(); /// add these to get 1uS
      }
   }

void delayMs( int x)
   {
   while(x--)
      delayUs(1000);
   }

A while statement has about 3 clock cycles.. A nop() has 1 clock cycle

If you use a 20mHz xtal 1 clock cycle is 200nS
A 4mHz xtal... 1uS

The rest is easy....
 
Last edited:
You can figure out how long the delay is by counting the actual number of clock cycles between loops using a simulator. Why does 20ms seem absurdly long for an eeprom delay?
 
Last edited:
Why does 20ms seem absurdly long for an eeprom delay?

Just being cautious!!! Its normally 5mS for a 400khz device..... but I don't know what he's using... I know the diagram states a 24C256 device... and 100khz is much longer..

We need to find out the fault first.
 
Sorry this was a double post... (I'm going nuts)
 
Last edited:
Still doesn't go though I think everything should be alright as I think I've put the correct cycles to execute (as its an INTIO67 t should be 8 Mhz, which implies 500 ns, so for 20 ms, those are 40000 cycles (which are 10*1000*4 cycles to run the delay routine).

My code now is:

Code:
#include <p18f4620.h>
#include <i2c.h>
#include <delays.h>
//#include "key33.h"  

void delayUs( int x );
void delayMs( int x);

#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config LVP = OFF
#pragma config XINST=OFF
#pragma config OSC=INTIO67

#define CLOCK_FREQ		(80000000ul)      // Hz 

int main(void)
{
char data;

OpenI2C(MASTER, SLEW_OFF);

StartI2C();
WriteI2C(0b10100000); //control byte

delayMs(10);
WriteI2C(0b00000000); //adr hi
delayMs(10);
WriteI2C(0b00000000); //adr lo
delayMs(10);
WriteI2C(0x25); //data 0
delayMs(10);
StopI2C();



StartI2C();
WriteI2C(0b10100001); //control byte (read data)
delayMs(10);
WriteI2C(0b00000000); //adr hi
delayMs(10);
WriteI2C(0b00000000); //adr lo
delayMs(10);
data=ReadI2C();

StopI2C(); 
}

void delayUs( int x )
   {
   while(x--)
      {
      Nop(); /// add these to get 1uS
      }
   }
 
void delayMs( int x)
   {
   while(x--)
	{
      delayUs(1000);
   }
	}

(This code does an strange thing which is that it might seemingly enter an infinite loop unless you step into the calls of DelayMs function, and run into the breakpoint on delayUs(1000); once you are in, if someone wants to try it).

Everything is as in the schematic (checked with polimeter in the circuit that connections are right) except for pin 7 which doesn't have the resistor and is grounded.

I don't know what else to do... Hope anyone has an idea.


PD: Also tried changing the chip select bits to 111 but nothing.
 
Last edited:
Stick two LEDs on the scl/ sda lines and use a debugger to step through your code, you will soon find where your problem lies. I hate using libraries where all the 1's and 0's are taken care of for ya
 
Stick two LEDs on the scl/ sda lines and use a debugger to step through your code, you will soon find where your problem lies. I hate using libraries where all the 1's and 0's are taken care of for ya

I'm already using debug mode and this is where I find that data is FFh instead of 25h, if the LEDs are for checking voltage is coming I already checked it with the polimeter, although, perhaps, you might be refering to something else.

Thanks.
 
Just a question.... Are you simulating this? If you are... What software are you using?
 
I'll try and simulate the code tonight for you..... I'll also have a look at the other thread as well

This "delay" issue is bothering me...
 
I'm already using debug mode and this is where I find that data is FFh instead of 25h, if the LEDs are for checking voltage is coming I already checked it with the polimeter, although, perhaps, you might be refering to something else.

Thanks.

In my experience, 70% of the folks I have seen having problems with I2C have a state change happening when they didn't expect it. Obviously there are many possible causes for it, however the fact remains. 25% seem to have no patience to wait for a write cycle to complete, and the remainder have some other mid packet, or subtle timing problem, usually device dependent

Just slowly stepping through the code with a couple of LED's on the lines allows you to visually see what's going on. It's equally possible that one of the lines is changing state when you don't expect it to, rather than a delay issue, and doing this instantly shows you where in your code it's happening. Unless that is, you are 100% certain that this is not the case. Using programmers, debuggers and logic probes etc is all well and dandy, but it all takes time setting up, running tests etc, sometimes the simplest observation short cuts all that pain

Get yourself a pencil and a piece of paper and jot down what's happening visually, then see if it follows what you expect. If it does then great, you can concentrate on subtle timing problems
 
OK!!!!

Faults.....
1) you defined your XTAL at 80mhz... not 8mhz ( this is probably why your delays didn't work )
2) You need to set the OSCCON register to 8mhz as well
3) Your ReadI2C routine should be like this

Code:
   StartI2C();
   WriteI2C(0b10100000); // control byte (write data)
   WriteI2C(0b00000000); // adr hi ( set read )
   WriteI2C(0b00000000); // adr lo ( address )
   RestartI2C();		  // correct read of I2C requires a restart!!!
   WriteI2C(0b10100001); // control byte (read data)
   data=ReadI2C(); 
   StopI2C();

Lastly (not important).. most memories can run at 400khz, so "SLEW_ON" when initiating the I2C.

Your code wrote 0x25 to the eeprom..... but the read command was faulty.
 
Last edited:
Thanks a ton for your answers and helping me.

Just one thing, trying to set the OSCCON for 8 Mhz makes the code to hang up when doing the second WriteSPI at least for me (I have tested it with values 0x70, 0x71 and 0x72 in case the last two bits had something to do). Anyway it works nicely without having it set, so I'm not into trying to know why this happens as long as it works, but I want to write this just in case anyone finds this problem.
 
I don't use anyone else's I2C routines.... I use my own. The OSCCON can be set with 0x70 ( 8mhz) ...0x60 ( 4mhz).... 0x50 (2mhz) ... etc...

The rest of the OSCCON is for stabilizing flags and external controls.. The chip defaults to 1mhz if you don't use it , so you can set the frequency variable to that.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…