LPC1768 I2C - Setting of I2EN requires a delay of at least 4uS before I2C is usable ????

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

LPC1768 I2C - Setting of I2EN requires a delay of at least 4uS before I2C is usable ????

1,173 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MarkSBoyce on Fri Jan 01 02:42:09 MST 2016
Using CMSIS sample code I successfully executed an I2C Transfer on my LPC Dev board.

After importing a simplified example of the C code into my existing project I struggled to correctly initialise I2C 0 (I2C0)

After initialisation I attempted to Send a START command with the address of my device. The SDA line dropped to 0 followed by the CLK line 10uS Later. However the clock did not continue to run but remained low for the duration.

After many many hours I found by delaying my code by about 4uS after setting I2EN the clock did in fact run and all was well.

I then removed the delays in the original CMSIS sample code (delays waiting for user input etc) and the same problem occurred.

There is nothing in the LPC17xx User Manual about there requiring a delay or in fact anything in Newsgroups.

Any idea's please.

Mark

See code snipped below:




    U32 i2c_init()
    {
                                             //30 28 26 24  22 20 00 00
    #define I2C0_PINS 0x01400000 // 0140 0000  = 00 00 00 01  01 00 00 00 
      // Configure Port 0:27 SDA & 0:28 CLK
      LPC_PINCON->PINSEL1 &= ~0x03C00000;
      LPC_PINCON->PINSEL1 |= I2C0_PINS;


      // Configure Port 0:27 and 0:28 as Standard Drive Mode with Slew Rate and Glitch Control enabled
      LPC_PINCON->I2CPADCFG = 0x00;

 

      // Set up clock and power for I2C0 module
      LPC_SC->PCONP |=  0x00000080 & CLKPWR_PCONP_BITMASK;  //bit 7 = I2C0 
  
      // Peripheral clock has been configured to 25MHz
      // Set the I2C clock value to register 25MHz / 100kHz = 250 full cycle or 125 for half cycle

      LPC_I2C0->I2SCLH = (uint32_t)(125);  // Duty Cycle of High Clock 100kHz
      LPC_I2C0->I2SCLL = (uint32_t)(125);  // Duty Cycle of Low Clock 100kHz

      // Set I2C operation to default
      LPC_I2C0->I2CONCLR = (I2C_I2CONCLR_AAC | I2C_I2CONCLR_STAC |    I2C_I2CONCLR_I2ENC);  // Disable I2C Interface (bit 6) Clear Start Bit (Bit 5)   Clear Acknowledge (Bit 2)


      //Do a dummy transmit for logic Analyser test
      LPC_I2C0->I2CONSET = I2C_I2CONSET_I2EN; // Enable I2C Interface (Bit 6)
      delay_us(4); // No I2C clock is visible if Set to 3uS or less from setting of I2EN
  
      LPC_I2C0->I2CONSET = I2C_I2CONSET_STA;
      LPC_I2C0->I2CONCLR = I2C_I2CONCLR_SIC;

      LPC_I2C0->I2DAT = 0xA0;
      // Wait for complete
      while (!(LPC_I2C0->I2CONSET & I2C_I2CONSET_SI));
      LPC_I2C0->I2CONCLR = I2C_I2CONCLR_STAC;
      return (LPC_I2C0->I2STAT & I2C_STAT_CODE_BITMASK);
    }

Labels (1)
0 Kudos
4 Replies

897 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MarkSBoyce on Sat Jan 02 21:02:11 MST 2016
Hi Rolf,

Thanks for your advice.  Although it didn't fix my issue, it did lead me to correct other parts of the code that were not working correctly so a very useful article.

It still requires a 4uS delay before issuing any I2C commands after setting the I2EN.

Mark
0 Kudos

897 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by DF9DQ on Sat Jan 02 04:15:45 MST 2016
It looks like an issue with the way you handle the SI bit (which is notorious for that...).

Before you begin transmission with the START condition, SI is assumed to be cleared. It shouldn't be necessary to do it explicitly, because if SI were still set you would be getting I2C interrupts at that time. Yet it doesn't harm to clear it, so simply change to
I2CONCLR.SIC = 1
I2CONSET.STA = 1

Sending the START condition takes time (your 4 µs!), and before sending SLA+X you must wait for SI to get set again after the I2C block has reached state 0x08 (in I2CSTAT).
It is then when you write SLA+X to I2CDAT, clear STA, and *afterwards* clear SI.
wait_for_SI()
I2DAT = 0xA0
I2CONCLR.STAC = 1
I2CONCLR.SIC = 1

For any action in response to an I2C interrupt (SI=1) it is important that you first do all the preparations necessary for the desired next step, and only clear SI after all that is done.

Regards,
Rolf
0 Kudos

897 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MarkSBoyce on Fri Jan 01 18:25:50 MST 2016
Thanks Chris

Interesting document. Unfortunately doesn't mention the delay with respect to Enabling the I2C0 system.

Mark
0 Kudos

897 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by cfb on Fri Jan 01 14:54:11 MST 2016
Have a look at UM10204 I2C-bus specification and user manual. There is much detailed timing information included there. I'm only guessing but there are several items listed in Table 6 e.g. hold time,(repeated) START condition, setup time for STOP condition that are identified with a minimum value of 4.0uS for Standard-mode.
0 Kudos