I2C STOP mode generation problem

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

I2C STOP mode generation problem

1,513 Views
huqiang
Contributor IV

Hi, everybody!

 

When I want to generate a stop signal in I2C of MPC5748G, there is something puzzle me.

 

In master transmiting and slave receiving mode

(I2C_2 is the master node, I2C_3 is the slave node),

the stop signal can be generated right by

153162_153162.pngpastedImage_3.png

Here's the question,

In master receiving and slave transmiting mode

(I2C_2 is the master node, I2C_3 is the slave node),

why the stop signal can not be generated right by

153163_153163.pngpastedImage_4.png

After I run this function, the IBB bit of IBCR register is still equals to 1, which means the bus is busy, the stop signal isn't generated. The whole program will stuck at

153161_153161.pngpastedImage_0.png

What should I do when I want to generate a stop signal in master receiving and slave transmiting mode?

 

Attachment is my program project for reference.

 

Thanks a lot!

Original Attachment has been moved to: mpc5748g_Z4_1.zip

Labels (1)
Tags (3)
0 Kudos
4 Replies

1,096 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

You have to properly follow recommended interrupt service flow, as shown in Fig 44-13 of the RM.

So if a master receiver wants to terminate a data transfer, it must inform the slave transmitter by not

acknowledging the last byte of data which can be done by setting the NOACK bit before reading the 2nd last byte of data. This read initiates next byte (last) data receiving. In this case the slave transmits the byte (last) which is not acknowledged by master. In slave transmitter routine, the received acknowledge bit (RXAK) must be tested before transmitting the next byte of data. Setting RXAK means an 'end of data' signal from the master receiver, after which slave must be switched from transmitter mode to receiver mode by software. A dummy read then releases the SDA line so that the master can generate a STOP signal.

So your Slave_transmit and Master_Receive function should be modified little bit as

void I2C_Slave_Transmit(void)

{

uint8_t dummy;

                //I2C_3.IBSR.B.IBIF = 0; // writing 0 have no effect

                I2C_3.IBDR.R = TxData;

                TxCount = TxCount - 1;

                while (I2C_3.IBSR.B.IBIF == 0);

                if (I2C_3.IBSR.B.RXAK == 1)

                {

                                I2C_3.IBCR.B.TXRX = 0;

                              dummy = I2C_3.IBDR.R;

                }

                I2C_3.IBSR.B.IBIF = 1;

}

void I2C_Master_Receive(void)

{

                uint8_t RxData;

                // I2C_2.IBSR.B.IBIF = 0;  // writing 0 have no effect

               if (RxCount == 2)

                {

                                I2C_2.IBCR.B.NOACK = 1;

                }

               if (RxCount == 1)

                {

                                   I2C_2.IBCR.B.MSSL = 0; // generate STOP

                                I2C_2.IBCR.B.NOACK = 0;

                }

                RxData = I2C_2.IBDR.R;

                RxCount = RxCount - 1;

               

}

Then Stop function is not used in main().

BR, Petr

0 Kudos

1,096 Views
huqiang
Contributor IV

Hi Petr,

Thanks a lot for your answer.

I’ve tried your program but it still cannot work, and will be stuck at the same place. After one cycle transmit and receive, the IBB bit of IBSR register still equals to 1, which means there is not a stop signal generated, why?

Thanks a lot!

BR, Qiang

int main(void)

{

  xcptn_xmpl ();                //Configure and Enable Interrupts

  peri_clock_gating();          //configure gating/enabling peri. clocks for modes

                               //configuraiton occurs after mode transition

  system160mhz();               //sysclk=160MHz, dividers configured, mode trans

  SIUL2_Init ();

  INTC.PSR[444].R = 0x8001;

  I2C_2_Init();

  I2C_3_Init();

  while(1)

  {

     I2C_Start();

     I2C_Slave_Set();

     for (i = 0; i <= 2; i++)

     {

      I2C_Slave_Transmit();

      I2C_Master_Receive();

     }

     count = count + 1;

  }

}

0 Kudos

1,096 Views
PetrS
NXP TechSupport
NXP TechSupport

Within a I2C_Start() you need to set "transmit" mode again as at the end a Master stays in "receive" mode.

Use

void I2C_Start(void)

{

    uint8_t calling_address = 0xAB;  //Transmit string

    while (I2C_2.IBSR.B.IBB == 1); //IBB=1 bus is busy

    I2C_2.IBCR.B.TXRX = 1;          //Transmit/Receive mode    1 = Transmit  0 = Receive

    I2C_2.IBCR.B.MSSL = 1;          // generate Start

    I2C_2.IBDR.R = calling_address;

....

BR, Petr

0 Kudos

1,096 Views
huqiang
Contributor IV

Hi, Petr

         Thank you very much for your help! It can work now! THX!

Best Regards,

Qiang

0 Kudos