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
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
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
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
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
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;
}
}
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
Hi, Petr
Thank you very much for your help! It can work now! THX!
Best Regards,
Qiang