1) Hardware used - MKE02x FRDM development board, EEPROM - ST24C16, Microchip 24C128, LED CAT9532
2) I2C Working conditions - MEK02x (Master) - EEPROM (Slave) both read and write is working fine with FBE mode i.e direct crystal frequency 10Mhz (also tested with 5Mhz and 2.5Mhz).
3) I2C Not Working conditions - MEK02x (Master) - EEPROM (Slave) both read and write not working with FEE mode i.e FLL Engaged external @ frequency 20Mhz, 10Mhz etc. Also same is the case with internal oscillator.
4) I2C with LED CAT9532 - Write operation - working fine, Read operation - Key detection working but sometime the driver get stucked or key is not detected and after this i want to reset the system.
5) KE02x I2C with LED CAT9532 sometimes it reads the input keys connected to LED CAT9532 but after 4-5 read operation and gets the I2C hang i see in the debugger it shows me MST bit is set but busy flag is bot busy.
6) Also it is hard to calculate baudspeed
I2C baudrate = I2C module clock speed(Hz)/(Mul x SCL Divider)
For I2C 100Kbps:
let I2C module clock speed(Hz) = 8Mhz
Mul = 1 (Mul = I2C0_BAUDRATE_MULT)
SCL Divider = (8000000/100000)/Mul
i will get SCL divider value and from this i want to get ICR value from refernce manual and this is going to put in the frequency divder resistor i.e ICR
I have question for some of SCL div value thier are 2-3 ICR values from this which is is to be selected from refrence manual
Is thier any auto calculation of baudspeed instead of looking this all manually.
5) Following is the sequence for read and write handle from application layer
#if(I2C_TEST == ENABLED)
switch (I2c_Slot)
{
case 0:
if (I2c__GetStatus(I2C0, I2C_STATUS_STATE) == I2C_STATE_IDLE)
{
I2c__Write(I2C0, 0x00, Rd_data, 2);
I2c_Slot++;
}
break;
case 1:
if (I2c__GetStatus(I2C0, I2C_STATUS_STATE) == I2C_STATE_IDLE)
{
I2c__Write(I2C0, 0x00, Rd_data, 0);
I2c_Slot++;
}
break;
case 2:
if (I2c__GetStatus(I2C0, I2C_STATUS_STATE) == I2C_STATE_IDLE)
{
I2c__RequestRead(I2C0, 2);
I2c_Slot++;
GPIO__PIN_TOGGLE(PORTH,1);
}
break;
case 3:
if (I2c__GetStatus(i2c_device, I2C_STATUS_STATE) == I2C_STATE_IDLE)
{
I2c_Slot++;
}
break;
case 4:
if (I2c__GetStatus(i2c_device, I2C_STATUS_STATE) == I2C_STATE_IDLE)
{
I2c__Read(i2c_device, &Rx_buf[str_data], 2);
str_data = str_data + 2;
I2c__Clear(i2c_device);
I2c__ResetBus(i2c_device);
I2c_Slot++;
}
break;
default:
I2c_Slot++;
if (I2c_Slot == 40)
{
I2c_Slot = 0;
}
break;
6) My I2C interrupt routine
void I2c0__InterruptHandler(void)
{
uint8 temp;
temp = 0;
#if (I2C0_FEATURE == ENABLED)
I2C_0.I2C_S1.BIT.IICIF = 1; //Clear Interrupt Flag - No interrupt pending
if(I2C_0.I2C_C1.BIT.MST == 1) //Check for Master Mode Select (1 - Master mode, 0 - Slave mode)
{
//Check for I2C0 Error
if (((I2C_0.I2C_S1.BYTE) & (I2C_S_ARBL_MASK | I2C_S_RXAK_MASK)) != FALSE)
{
if (((I2C_0.I2C_S1.BYTE) & (I2C_S_ARBL_MASK)) != FALSE)
{
I2c0_Ack_Error = I2C_ERROR_BUS_LOCKED; //Set the error flag - Loss of Arbitration
}
else
{
I2C0_STOP();
I2C0_Busy = I2C_STATE_IDLE;
//I2c0_Ack_Error = I2C_ERROR_ACK; //No ACK signal detected from Slave device
}
//I2C0_Busy = I2C_STATE_IDLE;
//Clear the error to accommodate the new errors
I2C_0.I2C_S1.BYTE = (0 << I2C_S_ARBL_SHIFT) | (0 << I2C_S_RXAK_SHIFT);
}
else
{
if ((I2C_0.I2C_C1.BIT.TX == TRUE)) //Tx bit = 1:Transmit Data to Slave device
{
if(I2c0_SlaveAddr & 0x01) //Slave internal address from where the data is to be read
{
if (I2C_0.I2C_S1.BIT.RXAK == 0) //Check ACK signal received from slave device for successful transmission of one byte data on the bus
{
I2C0_RxEnable(); //Enable I2C0 Receiver
temp = I2C_0.I2C_D; //Dummy Read - Copy received 1 byte data from Data I/O register
I2c0_SlaveAddr = (I2c0_SlaveAddr & 0xFE);
}
}
else
{
//I2C0 Write data to Slave device
if(I2C_0.I2C_S1.BIT.RXAK == 0) //Check ACK signal received from slave device for successful transmission of one byte data on the bus
{
if(I2C0_Flag == TRUE)
{
I2C_0.I2C_D = I2c0_InternalAddress;
I2C0_Flag = FALSE;
}
else if (I2c0_TxPointer < I2c0_SizeWrite)
{
I2C_0.I2C_D = I2c0_Buffer_Out[I2c0_TxPointer]; //Transmit Data to Slave
I2c0_TxPointer++; //Increment Transmit pointer by 1
}
else
{
I2C0_STOP(); //Generate Stop signal for I2C_0 (bit MST = 0)
I2C0_Busy = I2C_STATE_IDLE;
}
}
}
}
else //Tx bit = 0:Receive Data from Slave device
{
//I2C0 Read data from Slave device
if (I2c0_RxPointer == I2c0_SizeRead -1)
{
I2C_0.I2C_C1.BIT.TXAK = 1; //Send NACK to stop the communication
I2c0_Buffer_In[I2c0_RxPointer] = I2C_0.I2C_D; //Read Received Data from Slave//Generate Stop signal for I2C_0 (bit MST = 0)
I2c0_RxPointer++;
}
else
{
//Copy received data from Data I/O register to I2C0_Buffer_In array
I2c0_Buffer_In[I2c0_RxPointer] = I2C_0.I2C_D; //Read Received Data from Slave
I2C_0.I2C_C1.BIT.TXAK = 0; //Send ACK to Slave device
I2c0_RxPointer++; //Increment Receive pointer by 1
}
}
}
}
Thanks
Rahul
#else
//Disable the I2c Peripheral and its events
I2C_0.I2C_C1.BYTE &= ~(I2C_C1_IICEN_MASK | I2C_C1_IICIE_MASK );
#endif
}
Hello Rahul Natak:
In most cases to debug I2C problems having a scope or logic analyzer becomes very handy. Have you observed the signals generated for cases (3), (4) and (5)?
- For cases (4) and (5), what do you mean by "input key" and "key detection"?
- About (6), unfortunately there is no pattern in the ICR values table, so you cannot have some kind of formula. Possible approach to automate ICR value selection is to have a lookup table matching the one in the Reference Manual and have your code search for the one that best fits your required baudrate.
Regards!,
Jorge Gonzalez
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------