MCF52233 I2C no STOP state???

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MCF52233 I2C no STOP state???

2,234 Views
osanz
Contributor I
Hi to all ( again... )
 
Now is time to talk about I2C module on MCF52233.
 
I need to read multiple bytes from a I2C FRAM ( RAMTRON ). Everything is OK except for the last control status on the bus.
 
When is supposed to drive a STOP condition on to the bus, this is releasing SDA while SCL is high, nothing happens.
So i can read 8 bytes from the memory for example, but then there is no way to generate the stop condition.
 
I mean that nothing happens when:
 
 MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;     /* generates stop condition */   
 
Any idea?
 
Maybe the code will clarify something:
( This is based on a code foun on this forum, not mine i'm only has adapted to multiple reading )
 
Code:
 MCF_I2C_I2CR |= MCF_I2C_I2CR_MTX;     /* setting in Tx mode */               MCF_I2C_I2CR |= MCF_I2C_I2CR_MSTA;     /* send start condition */ MCF_I2C_I2DR = adressaI2c;       /* devide ID to write */               while( !(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF ));  /* wait until one byte transfer completion */ MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;     /* clear the completion transfer flag */               i=50;            /* Wait for a bit */ while(i--);  MCF_I2C_I2DR = (adressa>>8);      /* memory address */              /* wait until one byte transfer completion */ while( !(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF ));  /* wait until one byte transfer completion */               MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;      /* clear the completion transfer flag */  i=50;            /* Wait for a bit */ while(i--);  MCF_I2C_I2DR = (adressa&0xff);      /* memory address */              /* wait until one byte transfer completion */ while( !(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF ));  /* wait until one byte transfer completion */               MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;      /* clear the completion transfer flag */ i=50;            /* Wait for a bit */ while(i--);  MCF_I2C_I2CR |= MCF_I2C_I2CR_RSTA;     /* resend start */  i=50;            /* Wait for a bit */ while(i--);  MCF_I2C_I2DR = adressaI2c | 0x01;     /* device id to read */               while( !(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF ));  /* wait until one byte transfer completion */ MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;     /* clear the completion transfer flag */   MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;     /* setting in Rx mode */      i=50;            /* Wait for a bit */ while(i--);  Buffer[0] = MCF_I2C_I2DR;       /* dummy read */               while( !(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF ));  /* wait until one byte transfer completion */ MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;     /* clear the completion transfer flag */  MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;  for(i=0;i<nBytes;i++) {  Buffer[i + blockOffset ]= MCF_I2C_I2DR;    /* read data received */             while( !(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF ));  /* wait until one byte transfer completion */ MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;      /* clear the completion transfer flag */    if(i<nBytes-1)  {   //SCL_low();   //SDA_low();        //delay(TPLS);   //SCL_high();    //delay(TPLS);     /* send NO ACK */ // MCF_I2C_I2CR |= MCF_I2C_I2CR_RSTA;  MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;    /* send ACK */  }  else   {   MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;     /* send NO ACK */    }  }  i=50;            /* Wait for a bit */ while(i--); MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;     /* generates stop condition */                 return 1;         

 
Labels (1)
0 Kudos
3 Replies

364 Views
mjbcswitzerland
Specialist V
Hi

Here's the termination of a read sequence in the uTasker project code:

if last but one byte to be read, don't send an ack:
    I2CR = (IIC_IEN | IIC_IIEN | IIC_MSTA | IIC_TXAK);
else if not last byte
    I2CR = (IIC_IEN | IIC_IIEN | IIC_MSTA);
else (last byte)
    I2CR = (IIC_IEN | IIC_TXAK);

This uses interrupts.
Perhaps the stop condition is commanded too early in your code. Even if you don't use interrupts you can still poll the interrupt flag but rather than using loops, which could result in critical timing (also dependent on actual I2C bus speed) and writing a command too early.
Eg. (not tested but something like this)
while (I2SR != 0) {}      // wait until last unacked byte read has completed
I2SR = 0;                      // reset the flag for later
MCF_I2C_I2CT &= ~MCF_I2C_I2C_MSTA; /7 stop condition

You can also take a look at the uTasker solution for the M52233. It also includes well tested interrupt driven I2C driver (the project allows also simulating the I2C devices for more efficient development and project testing) - the demo tests ad its use are described here: http://www.utasker.com/docs/uTasker/uTaskerIIC_002.PDF

Regards

Mark

www.uTasker.com




0 Kudos

364 Views
osanz
Contributor I
Dear Mark;
 
Thanks a lot for your reply.
 
I have enabled the I2C IRQ, with no success....
Definetively i can not use this I2c, there is no way to control it, the IRQ is triggered too fast and the behaviour is worst than when the done flag is poolled.
 
This is the second time i try to use the I2C periperal, on this MCF52233, and  by the moment is the last.
 
Luckyly i have a I2C software driver, that i'm currently using on this project, that works fine up to 250Khz.
 
My idea was to spped up the system by using the native I2C hardware but there is no way...
 
Thanks a lot again.
0 Kudos

364 Views
mjbcswitzerland
Specialist V
Hi

The I2C interface in the M5223X is specified to work at 100kHz with maximum bus loading and timing. Some chips support up to 400kHz and if this a requirement the other chips will of course have an advantage.
However the I2C interface has been used in interrupt mode intensively at 100kHz in various projects and so basically does work very well.

Regards

Mark

www.uTasker.com
0 Kudos