EmbeddedRelated.com
Forums

problems with I2c

Started by Unknown November 25, 2006
Hi,

I'm having some problems using i2c to write to an eeprom, a 24lc515.
Sometimes it'll write to it without any problems, and sometimes it
won't write at all.
The code I am using is this:

void EE_wr_byte(int EE_address, char data)
{

unsigned char transfer;
unsigned int temp;
unsigned char control = 0xA0;
P4OUT |= SDA + SCL; //Stop
P4DIR |= SDA + SCL; //Port as output
P4OUT &= ~SDA; //Start
EE_ser_out(control); //Control-byte
temp = (EE_address >> 8); //High byte to send
transfer = temp;
EE_ser_out(transfer);
transfer = EE_address;
EE_ser_out(transfer);
EE_ser_out(data);

P4OUT |= SCL; //Stop
P4OUT |= SDA;

}

void EE_ser_out(char data)
{
unsigned int a;

P4OUT &= ~SCL; //SCL = 0
for(a=0;a<8;a++)
{
if(data & BIT7)
{
P4OUT |= SDA;
}
else
{
P4OUT &= ~SDA;
}
P4OUT |= SCL;
P4OUT &= ~SCL;
data = data << 1;
}
P4DIR &= ~SDA;
P4OUT |= SCL; //Clock-pulse
P4OUT &= ~SCL;
P4DIR |= SDA;

}

and my main had this
short int ffft;
char fffv;
int abcd;

for ( ffft = 0; ffft<25; ffft++)
{
fffv = ffft+8;
EE_wr_byte(ffft, fffv);
abcd = EE_rd_byte(ffft);
}

however, it will only write on the even numbers of the memory.

I changed my code to this:

 EE_wr_int(ffft, 1764);
  abcd = EE_rd_int(ffft);
  ffft+=1;
  EE_wr_int(ffft, 2640);
  abcd = EE_rd_int(ffft);
  ffft+=1;
  EE_wr_int(ffft, 0);
  abcd = EE_rd_int(ffft);
  ffft+=1;
  EE_wr_int(ffft, 0);
  abcd = EE_rd_int(ffft);
    ffft+=1;
  EE_wr_int(ffft, 0);
  abcd = EE_rd_int(ffft);
    ffft+=1;
  EE_wr_int(ffft, 0);
  abcd = EE_rd_int(ffft);
    ffft+=1;
  EE_wr_int(ffft, 1);
  abcd = EE_rd_int(ffft);
    ffft+=1;
  EE_wr_int(ffft, 1);
  abcd = EE_rd_int(ffft);
    ffft+=1;
  EE_wr_int(ffft, 1);
  abcd = EE_rd_int(ffft);
    ffft+=1;
  EE_wr_int(ffft, 1);
  abcd = EE_rd_int(ffft);
  ffft+=1;
and it will stop writing after the first "
  EE_wr_int(ffft, 1);
  abcd = EE_rd_int(ffft);"

I really don't understand what I'm doing wrong.  At first I thought it
was a delay issue, so I added some delays between the write and read
cycles, however this does not change anything.

Any help would be appreciated

On 25 Nov 2006 12:21:23 -0800, ddshore@gmail.com wrote:

>Hi, > >I'm having some problems using i2c to write to an eeprom, a 24lc515. >Sometimes it'll write to it without any problems, and sometimes it >won't write at all. >The code I am using is this: > >void EE_wr_byte(int EE_address, char data) >{
<snip>
> >I really don't understand what I'm doing wrong. At first I thought it >was a delay issue, so I added some delays between the write and read >cycles, however this does not change anything. > >Any help would be appreciated
It is probably a delay issue. Writing 1 bytes takes like 10 msec because it has to do some erasing internally. Writing multiple bytes in the same page also takes 10 msec. Read the part about aknowledge polling in the datasheet. If you want to verify this is your problem, add like 10 or 20 msec of delay after writing 1 byte. Patrick


> > transfer = EE_address; > EE_ser_out(transfer); > EE_ser_out(data); > > P4OUT |= SCL; //Stop > P4OUT |= SDA;
It seems that EE_ser_out leaves the SDA line high or low depending on the last bit sent i.e. LSB. That's why you can only make a valid STOP when the previous byte's LSB was a 0.
Viktor wrote:
> > > > transfer = EE_address; > > EE_ser_out(transfer); > > EE_ser_out(data); > > > > P4OUT |= SCL; //Stop > > P4OUT |= SDA; > > It seems that EE_ser_out leaves the SDA line high or low depending on > the last bit sent i.e. LSB. That's why you can only make a valid STOP > when the previous byte's LSB was a 0.
Thanks a lot, that was it!

On Nov 29, 2:25 pm, ddsh...@gmail.com wrote:
> Viktor wrote: > > > > transfer = EE_address; > > > EE_ser_out(transfer); > > > EE_ser_out(data); > > > > P4OUT |= SCL; //Stop > > > P4OUT |= SDA; > > > It seems that EE_ser_out leaves the SDA line high or low depending on > > the last bit sent i.e. LSB. That's why you can only make a valid STOP > > when the previous byte's LSB was a 0.Thanks a lot, that was it!
Glad to help. I'd just like to add that that when I see bit-banging code (like yours is) written in C, not assembler, I get an urge to bite through my mouse cord. Try doing it in asm, then link it in as a C function. It'll be easier to write, read and debug. Viktor