I send the repeated Start and the control word (slave address + Read bit) then we clean the IBIF bit. When the IBIF is set again we change to receive mode and do a dummy IBDR read to initiate byte data receiving. Slave send a data and Master get IBIF set. In this time the IBAL is set. The Master do not switch over to slave.
On the bus there are a EEPROM (M24C02), it is the only device on the bus.
On the I2C lines we can see the following signals, after that the SDA continues LOW and the SCL continues HIGH.
void I2C_Interupt(void)
{ uint8_t dummy; // Dummy variable to read I2C
if(I2C_0.IBCR.B.MS==1) /* If is in master mode */
{
if(I2C_0.IBCR.B.TX == 1) /* If TX */
{
if(I2C_0.IBSR.B.RXAK==0) /* If a acknowledge is received */
{
entery++;
ack_flag= 0;
if(entery == 1)
{
I2C_0.IBDR.R = iic_addr; /* Update IBDR, send internal address of I2C slave */
}
else if (entery <= (iic_len+1))
{
I2C_0.IBCR.B.RSTA = 1; // Set IBCR, generate repeated START
I2C_0.IBDR.R = iic_buffer[entery-2];
ack_flag = 1;
}
else
{
rd_flag = 0;
I2C_0.IBCR.B.TX = 0; // Set IBCR, Receive mode select
dummy = I2C_0.IBDR.R; // initiates next byte data receiving
entery_r = 0;
}
}
}
else /* If RX */
{
if(entery_r<(iic_rlen-1))
{
*(RData+entery_r) = I2C_0.IBDR.R; // Read the received byte from slave
entery_r++;
}
else if(entery_r==(iic_rlen-1))
{
I2C_0.IBCR.B.NOACK = 1; // In the last byte, change the ACK for NOACK
}
else
{
I2C_0.IBCR.B.MS = 0; // Set IBCR, Generate stop signal;
I2C_0.IBCR.B.NOACK = 0; // Reset the NOACK to default value
}
}
}
else /* Slave mode */
{
if(I2C_0.IBSR.B.IBAL == 1) /* Abitration Lost */
{
I2C_0.IBSR.B.IBAL = 1;
I2C_0.IBCR.B.MS=0;
if(I2C_0.IBSR.B.IAAS == 1)
{
if(I2C_0.IBSR.B.SRW == 1)
{
I2C_0.IBCR.B.TX = 1; // Set IBCR, Receive mode select
}
else
{
I2C_0.IBCR.B.TX = 0; // Set IBCR, Receive mode select
dummy = I2C_0.IBDR.R; // initiates next byte data receiving
}
}
}
else /* Abitration No Lost */
{
if(I2C_0.IBSR.B.IAAS == 1)
{
I2C_0.IBCR.B.TX = 1; // Set IBCR, Receive mode select
}
else
{
if(I2C_0.IBCR.B.TX == 1) /* If TX */
{
if(I2C_0.IBSR.B.RXAK==0) /* If a acknowledge is received */
{
entery++;
ack_flag= 0;
if(entery == 1)
{
I2C_0.IBDR.R = iic_addr; /* Update IBDR, send internal address of I2C slave */
}
else if (entery <= (iic_len+1))
{
I2C_0.IBCR.B.RSTA = 1; // Set IBCR, generate repeated START
I2C_0.IBDR.R = iic_buffer[entery-2];
ack_flag = 1;
}
else
{
rd_flag = 0;
I2C_0.IBCR.B.TX = 0; // Set IBCR, Receive mode select
dummy = I2C_0.IBDR.R; // initiates next byte data receiving
entery_r = 0;
}
}
}
else
{
if(entery_r<(iic_rlen-1))
{
*(RData+entery_r) = I2C_0.IBDR.R; // Read the received byte from slave
entery_r++;
}
else if(entery_r==(iic_rlen-1))
{
I2C_0.IBCR.B.NOACK = 1; // In the last byte, change the ACK for NOACK
}
else
{
I2C_0.IBCR.B.MS = 0; // Set IBCR, Generate stop signal;
I2C_0.IBCR.B.NOACK = 0; // Reset the NOACK to default value
}
}
}
}
}
I2C_0.IBSR.B.IBIF=1;
}