i2c fails to send start condition and address

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

i2c fails to send start condition and address

Jump to solution
1,053 Views
VinceTF
Contributor III

device: mcf52258

RTOS: MQX 3.8.1

 

Use the following code to send a start condition and address.

// set transmit mode: bit 4 = 1;

      MCF_I2C0_I2CR |= MCF_I2C_I2CR_MTX;

      // send ACK after receive

      MCF_I2C0_I2CR &= ~MCF_I2C_I2CR_TXAK;

      // set MSTA to 1 to generate START condition

      MCF_I2C0_I2CR |= MCF_I2C_I2CR_MSTA;

      // set slave address

      MCF_I2C0_I2DR = address;

 

//* wait for bus busy *//

loop_count2 = 0;

      while(!(MCF_I2C0_I2SR & MCF_I2C_I2SR_IBB)) //if bus is idle, wait until busy

      {

     loop_count2++;

     if(loop_count2 > LOOP_TIMEOUT)

     {

          break;

     }

      }

 

      // wait until transfer finish

      //---------------------------

     _lwsem_wait( &i2c_ready_semaphore );

 

 

     _time_delay(5);

 

     MCF_I2C0_I2DR = *(unsigned char *)(data + i); //load data onto i2c bus.

 

This code works fine, but if I remove the _time_delay(5), the start condition and address do not get sent but the data does.  For our application, we read a lot of bytes of data.  It would be a big time saver if we could remove the time delay.  Any idea what is going on here?

 

Labels (1)
Tags (2)
0 Kudos
1 Solution
573 Views
VinceTF
Contributor III

Ok, so far the feedback I have gotten from freescale support on this is sample code with time delays where I had them in my code.  Not so helpful (except for Tom, his advice has been helpful).

I have discovered something that can be done to avoid using time delays.

Check for the following items in the following order:

1) Peripheral address to be equal to what it is loaded to. while(MCF_I2C0_I2DR != (address))

2) Transfer complete flag to be set.  while(!(MCF_I2C0_I2SR & MCF_I2C_I2SR_ICF))

See snippet below for how I integrated it into my code.  So far this has worked repeatedly and reliably.  For anyone considering this method, please keep in mind this is something I came up with under an aggressive schedule and hasn't been fully regression tested.  So.... use at your own risk.

It would be nice if someone from Freescale could either validate this solution or come up with something better.

// set transmit mode: bit 4 = 1;

      MCF_I2C0_I2CR |= MCF_I2C_I2CR_MTX;

      // send ACK after receive

      MCF_I2C0_I2CR &= ~MCF_I2C_I2CR_TXAK;

      // set MSTA to 1 to generate START condition

      MCF_I2C0_I2CR |= MCF_I2C_I2CR_MSTA;

      // set slave address

      MCF_I2C0_I2DR = address;

     //* wait for bus busy *//

     loop_count2 = 0;

      while(!(MCF_I2C0_I2SR & MCF_I2C_I2SR_IBB)) //if bus is idle, wait until busy

      {

          loop_count2++;

          if(loop_count2 > LOOP_TIMEOUT)

          {

               break;

          }

      }

     loop_count2 = 0;

      while(MCF_I2C0_I2DR != address)

      {

          loop_count2++;

          if(loop_count2 > LOOP_TIMEOUT)

          {

               break;

          }

      }

      loop_count2 = 0;

      while(!(MCF_I2C0_I2SR & MCF_I2C_I2SR_ICF))

      {

          loop_count2++;

          if(loop_count2 > LOOP_TIMEOUT)

          {

               break;

          }

      }

      // wait until transfer finish

      //---------------------------

     _lwsem_wait( &i2c_ready_semaphore );

//     _time_delay(5);

     MCF_I2C0_I2DR = *(unsigned char *)(data + i); //load data onto i2c bus.

View solution in original post

0 Kudos
2 Replies
574 Views
VinceTF
Contributor III

Ok, so far the feedback I have gotten from freescale support on this is sample code with time delays where I had them in my code.  Not so helpful (except for Tom, his advice has been helpful).

I have discovered something that can be done to avoid using time delays.

Check for the following items in the following order:

1) Peripheral address to be equal to what it is loaded to. while(MCF_I2C0_I2DR != (address))

2) Transfer complete flag to be set.  while(!(MCF_I2C0_I2SR & MCF_I2C_I2SR_ICF))

See snippet below for how I integrated it into my code.  So far this has worked repeatedly and reliably.  For anyone considering this method, please keep in mind this is something I came up with under an aggressive schedule and hasn't been fully regression tested.  So.... use at your own risk.

It would be nice if someone from Freescale could either validate this solution or come up with something better.

// set transmit mode: bit 4 = 1;

      MCF_I2C0_I2CR |= MCF_I2C_I2CR_MTX;

      // send ACK after receive

      MCF_I2C0_I2CR &= ~MCF_I2C_I2CR_TXAK;

      // set MSTA to 1 to generate START condition

      MCF_I2C0_I2CR |= MCF_I2C_I2CR_MSTA;

      // set slave address

      MCF_I2C0_I2DR = address;

     //* wait for bus busy *//

     loop_count2 = 0;

      while(!(MCF_I2C0_I2SR & MCF_I2C_I2SR_IBB)) //if bus is idle, wait until busy

      {

          loop_count2++;

          if(loop_count2 > LOOP_TIMEOUT)

          {

               break;

          }

      }

     loop_count2 = 0;

      while(MCF_I2C0_I2DR != address)

      {

          loop_count2++;

          if(loop_count2 > LOOP_TIMEOUT)

          {

               break;

          }

      }

      loop_count2 = 0;

      while(!(MCF_I2C0_I2SR & MCF_I2C_I2SR_ICF))

      {

          loop_count2++;

          if(loop_count2 > LOOP_TIMEOUT)

          {

               break;

          }

      }

      // wait until transfer finish

      //---------------------------

     _lwsem_wait( &i2c_ready_semaphore );

//     _time_delay(5);

     MCF_I2C0_I2DR = *(unsigned char *)(data + i); //load data onto i2c bus.

0 Kudos
573 Views
TomE
Specialist II

Searching this forum for "MCF_I2C0_I2CR" finds your post and this one:

Another I2C problem - code works in polled mode, doesn't work from ISR

Unfortunately Freescales "conversion" from Lithium to the current Forum software has totally mangled all the sample code in the above (and hundreds of other) posts, removing all the line breaks. You'll have to cut-and-paste the samples to an editor and put the line breaks back in to understand the code.

If that doesn't answer your current question, I suggest you follow the links and discussions in there, especially see if those links get you WORKING code.

Tom