Problem with I2C.

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

Problem with I2C.

1,048 Views
john71
Senior Contributor I

I do write operation.

unsigned int I2C0_Wait(void)

{

      unsigned int timeout = 0;

     

      while((I2C0_S & I2C_S_IICIF_MASK)==0)

      {

          timeout++;

          if(timeout > I2C_TIMEOUT)

            return I2C_ERROR;

      }

      I2C0_S |= I2C_S_IICIF_MASK;

      

      return 0;

}

 

void MAX7300_Write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data)

{

    uint8_t slave_address = (slave_addr<<1) & 0xFE;

   

    //START

    I2C0_C1 |= I2C_C1_MST_MASK;

    I2C0_C1 |= I2C_C1_TX_MASK;

 

    I2C0_D = slave_address;

    I2C0_Wait();

   

    I2C0_D = reg_addr;

    I2C0_Wait();

 

    I2C0_D = *data;

    I2C0_Wait();

 

    //STOP

    I2C0_C1 &= ~I2C_C1_MST_MASK;

    I2C0_C1 &= ~I2C_C1_TX_MASK

 

    while (I2C0_S & I2C_S_BUSY_MASK) ;

}

After stop the busy flag is not cleared – I stay in while (I2C0_S & I2C_S_BUSY_MASK).

 

In data sheet it says

BUSY

Indicates the status of the bus regardless of slave or master mode. This bit is set when a START signal is
detected and cleared when a STOP signal is detected.

7 Replies

729 Views
john71
Senior Contributor I

I suspect the MULT and ICR values in I2C0->F register the origin of the problem.

Say I want to have a baud rate 300000.

So 48000000 / 160 = 300000. But divider can be achieved by different ways - 4*40, 2*80. Divider the same but the parameters like  SDA hold time, SCL start hold time, SCL stop hold time  will be different.  And this is what driving the bus nuts (I guess). Is there some algorithm to calculate the right parameters?

0 Kudos

730 Views
john71
Senior Contributor I

Well..I found I2C_MasterSetBaudRate(I2C0, 200000, clock_hz);  doesn't help much.

0 Kudos

730 Views
mjbcswitzerland
Specialist V

Hi

1. Check whether your part is affected by errata e6070 which excludes the use of the MULT bit since it causes repeated starts to fail when not set to 0.

2. The baud rate generator doesn't follow any obvious formula so it is best to take the values from the user's manual (or use a look up table of it) - Table "I2C divider and hold values". For example, the baud rate divider is not just the IRC value in the register but is derived from it - 0x00 divides by 20 , 0x21 divides by 192 and 0x22 divides by 224, etc. etc.

If you need 300kHz from 60MHz bus, as reference, with MULT set to 0, you need to divide by 200. The closest divides possible are 192 (a little faster) or 224 (a little slower). Choosing 224 (to give 267.8kHz), ICR is 0x22. Therefore I2Cx_F is 0x22.

The setup and hold times may be tunable if you can use MULT but their effect should be insignificant for basic operation.

Regards

Mark

730 Views
mjbcswitzerland
Specialist V

Hi Evgeny

A start condition is sent when the MST flag is set and a stop condition is sent when the MST flag is cleared.

The TX flag should however not be cleared. Maybe that is the issue (?)

Regards

Mark

http://www.utasker.com/kinetis/FRDM-K82F.html
I2C: http://www.utasker.com/docs/uTasker/uTasker_I2C.pdf

0 Kudos

730 Views
john71
Senior Contributor I

I commented the line

2C0_C1 &= ~I2C_C1_TX_MASK

on stop condition. the BUSY stays high.

0 Kudos

730 Views
mjbcswitzerland
Specialist V

Hi

Have you measured the signals on the bus?

If they are not both at '1' it would also be normal that the bus is still seen as busy and the reason for why the bus is not '1' (eg. missing pull-ups) will need to be investigated.

Regards

Mark

0 Kudos

730 Views
john71
Senior Contributor I

Scope shows normal signals on SDA and SCL lines.

I noticed the clocks configured at startup are invalid. May it be related to the issue?

0 Kudos