Tool/software:
I am using I2C in f28335.
I2C is connected to three IO expanders ICs -TCAL9539-Q1.
I am sharing the I2C code i am using as below.
i am using this read write functions in main loop, sequentially.
During the Read functionality, I am facing Issue.
when i run the code in debug mode, step by step - i am getting the data correctly. But When i run the code Continuesly - data is not correct as i can analysed in watch window.
i want to also verify the read and write function on polling method.
Please verify the code and let me know the possible sollution.
Thank you in advance.
/**
* @brief: Initialization of I2C C GPIOs
* @param[in]
* @param[out]
*/
void vInitI2CGPIO (void)
{
EALLOW;
//
// Enable internal pull-up for the selected pins
// Pull-ups can be enabled or disabled disabled by the user.
// This will enable the pullups for the specified pins.
// Comment out other unwanted lines.
//
GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0; // Enable pull-up for GPIO32 (SDAA)
GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0; // Enable pull-up for GPIO33 (SCLA)
//
// Set qualification for selected pins to asynch only
// This will select asynch (no qualification) for the selected pins.
// Comment out other unwanted lines.
//
GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3; // Asynch input GPIO32 (SDAA)
GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3; // Asynch input GPIO33 (SCLA)
//
// Configure SCI pins using GPIO regs
// This specifies which of the possible GPIO pins will be I2C functional
// pins. Comment out other unwanted lines.
//
GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1; // Configure GPIO32 to SDAA
GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1; // Configure GPIO33 to SCLA
EDIS;
}
/**
* @brief: I2C initialization of Special Functional registers
* @param[in]
* @param[out]
*/
void vI2CaInitSFRs(void)
{
// Default - For 150MHz SYSCLKOUT
I2caRegs.I2CPSC.all = 14; // Prescaler - need 7-12 Mhz on module clk (150/(14+1) = 10MHz)
I2caRegs.I2CCLKL = 15; // NOTE: must be non zero //10/(I2CCLKL+I2CCLKH) = i2c speed
I2caRegs.I2CCLKH = 10; // NOTE: must be non zero
I2caRegs.I2CIER.all = 0; // Enable SCD & ARDY interrupts
I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset
// Stop I2C when suspended
}
/**
* @brief: Read I2C Function
* @param[in] : uint16_t ui16SlaveAddress, Slave device address
* uint16_t ui16CmdAddress, Command Address
* uint16_t *pui16ReadBuffer, Read data buffer
* uint16_t i16Nbyte - number of bytes
* @param[out] : true or false
*/
bool bReadI2C(uint16_t ui16SlaveAddress,uint16_t ui16CmdAddress,uint16_t *pui16ReadBuffer, uint8_t ui8Nbyte)
{
uint16_t i;
// Wait for STOP from any previous transaction
while (I2caRegs.I2CMDR.bit.STP);
// Set Slave Address
I2caRegs.I2CSAR = ui16SlaveAddress;
// Check if Bus is Busy
while (I2caRegs.I2CSTR.bit.BB);
// Write Register Address (Start Condition)**
I2caRegs.I2CCNT = 1; // One byte (Register Address)
I2caRegs.I2CMDR.all = 0x6620; // Master-Transmit Mode, Start Condition
while (!I2caRegs.I2CSTR.bit.XRDY); // Wait for TX Ready
I2caRegs.I2CDXR = ui16CmdAddress; // Send Register Address
while (!I2caRegs.I2CSTR.bit.ARDY); // Wait for transaction to complete
// **Ensure STOP Condition Before Read**
I2caRegs.I2CMDR.bit.STP = 1;
while (I2caRegs.I2CMDR.bit.STP);
// Restart for Read (Repeated Start)**
I2caRegs.I2CCNT = ui8Nbyte; // Number of bytes to read
I2caRegs.I2CMDR.all = 0x6C20; // Master-Receive Mode, Repeated Start
for (i = 0; i < ui8Nbyte; i++)
{
while (!I2caRegs.I2CSTR.bit.RRDY); // Wait for RX ready
pui16ReadBuffer[i] = I2caRegs.I2CDRR; // Read data from slave
}
I2caRegs.I2CMDR.bit.STP = 1; // Send STOP condition
return true;
}
/**
* @brief: Write I2C Function
* @param[in] : uint16_t ui16SlaveAddress, Slave Device address
* uint16_t ui16CmdAddress, Command Address
* uint16_t *pui16WriteBuffer, Write Buffer address
* uint8_t ui8nbyte - number of bytes
* @param[out] : true or false
*/
bool bWriteI2C(uint16_t ui16SlaveAddress,uint16_t ui16CmdAddress,uint16_t *pui16WriteBuffer,uint8_t ui8nbyte)
{
uint16_t i = 0;
// Clear previous errors before sending new data
I2caRegs.I2CSTR.bit.NACK = 1; // Clear NACK bit
I2caRegs.I2CSTR.bit.BB = 1; // Clear bus busy if stuck
I2caRegs.I2CSTR.bit.ARDY = 1; // Clear ARDY (transaction complete) flag
// If I2C bus is stuck, reset it
if (I2caRegs.I2CSTR.bit.BB == 1)
{
I2caRegs.I2CMDR.bit.STP = 1; // Send STOP to release the bus
I2caRegs.I2CMDR.all = 0x0020; // Reset I2C module
}
// Set slave address
I2caRegs.I2CSAR = ui16SlaveAddress;
// Configure transfer
I2caRegs.I2CCNT = ui8nbyte + 1; // Total bytes to send (command + data)
I2caRegs.I2CDXR = ui16CmdAddress; // Send command
// Send Start condition
I2caRegs.I2CMDR.all = 0x6E20; // STT=1 (Start), TRX=1 (Transmit), MST=1 (Master), IRS=1 (I2C enable)
// Wait for TX ready (XRDY)
while (I2caRegs.I2CSTR.bit.XRDY == 0);
// Send data bytes
for (i = 0; i < ui8nbyte; i++)
{
I2caRegs.I2CDXR = pui16WriteBuffer[i]; // Load data to transmit buffer
// Wait for TX ready (XRDY)
while (I2caRegs.I2CSTR.bit.XRDY == 0);
}
// Send STOP condition
I2caRegs.I2CMDR.bit.STP = 1;
// Check if I2C acknowledged
if (I2caRegs.I2CSTR.bit.NACK == 1)
{
return false;
}
return true;
}
}
/**
* @brief: Initialization of I2C C GPIOs
* @param[in]
* @param[out]
*/
void vInitI2CGPIO (void)
{
EALLOW;
//
// Enable internal pull-up for the selected pins
// Pull-ups can be enabled or disabled disabled by the user.
// This will enable the pullups for the specified pins.
// Comment out other unwanted lines.
//
GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0; // Enable pull-up for GPIO32 (SDAA)
GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0; // Enable pull-up for GPIO33 (SCLA)
//
// Set qualification for selected pins to asynch only
// This will select asynch (no qualification) for the selected pins.
// Comment out other unwanted lines.
//
GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3; // Asynch input GPIO32 (SDAA)
GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3; // Asynch input GPIO33 (SCLA)
//
// Configure SCI pins using GPIO regs
// This specifies which of the possible GPIO pins will be I2C functional
// pins. Comment out other unwanted lines.
//
GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1; // Configure GPIO32 to SDAA
GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1; // Configure GPIO33 to SCLA
EDIS;
}
/**
* @brief: I2C initialization of Special Functional registers
* @param[in]
* @param[out]
*/
void vI2CaInitSFRs(void)
{
// Default - For 150MHz SYSCLKOUT
I2caRegs.I2CPSC.all = 14; // Prescaler - need 7-12 Mhz on module clk (150/(14+1) = 10MHz)
I2caRegs.I2CCLKL = 15; // NOTE: must be non zero //10/(I2CCLKL+I2CCLKH) = i2c speed
I2caRegs.I2CCLKH = 10; // NOTE: must be non zero
I2caRegs.I2CIER.all = 0; // Enable SCD & ARDY interrupts
I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset
// Stop I2C when suspended
}
/**
* @brief: Read I2C Function
* @param[in] : uint16_t ui16SlaveAddress, Slave device address
* uint16_t ui16CmdAddress, Command Address
* uint16_t *pui16ReadBuffer, Read data buffer
* uint16_t i16Nbyte - number of bytes
* @param[out] : true or false
*/
bool bReadI2C(uint16_t ui16SlaveAddress,uint16_t ui16CmdAddress,uint16_t *pui16ReadBuffer, uint8_t ui8Nbyte)
{
uint16_t i;
// Wait for STOP from any previous transaction
while (I2caRegs.I2CMDR.bit.STP);
// Set Slave Address
I2caRegs.I2CSAR = ui16SlaveAddress;
// Check if Bus is Busy
while (I2caRegs.I2CSTR.bit.BB);
// Write Register Address (Start Condition)**
I2caRegs.I2CCNT = 1; // One byte (Register Address)
I2caRegs.I2CMDR.all = 0x6620; // Master-Transmit Mode, Start Condition
while (!I2caRegs.I2CSTR.bit.XRDY); // Wait for TX Ready
I2caRegs.I2CDXR = ui16CmdAddress; // Send Register Address
while (!I2caRegs.I2CSTR.bit.ARDY); // Wait for transaction to complete
// **Ensure STOP Condition Before Read**
I2caRegs.I2CMDR.bit.STP = 1;
while (I2caRegs.I2CMDR.bit.STP);
// Restart for Read (Repeated Start)**
I2caRegs.I2CCNT = ui8Nbyte; // Number of bytes to read
I2caRegs.I2CMDR.all = 0x6C20; // Master-Receive Mode, Repeated Start
for (i = 0; i < ui8Nbyte; i++)
{
while (!I2caRegs.I2CSTR.bit.RRDY); // Wait for RX ready
pui16ReadBuffer[i] = I2caRegs.I2CDRR; // Read data from slave
}
I2caRegs.I2CMDR.bit.STP = 1; // Send STOP condition
return true;
}
/**
* @brief: Write I2C Function
* @param[in] : uint16_t ui16SlaveAddress, Slave Device address
* uint16_t ui16CmdAddress, Command Address
* uint16_t *pui16WriteBuffer, Write Buffer address
* uint8_t ui8nbyte - number of bytes
* @param[out] : true or false
*/
bool bWriteI2C(uint16_t ui16SlaveAddress,uint16_t ui16CmdAddress,uint16_t *pui16WriteBuffer,uint8_t ui8nbyte)
{
uint16_t i = 0;
// Clear previous errors before sending new data
I2caRegs.I2CSTR.bit.NACK = 1; // Clear NACK bit
I2caRegs.I2CSTR.bit.BB = 1; // Clear bus busy if stuck
I2caRegs.I2CSTR.bit.ARDY = 1; // Clear ARDY (transaction complete) flag
// If I2C bus is stuck, reset it
if (I2caRegs.I2CSTR.bit.BB == 1)
{
I2caRegs.I2CMDR.bit.STP = 1; // Send STOP to release the bus
I2caRegs.I2CMDR.all = 0x0020; // Reset I2C module
}
// Set slave address
I2caRegs.I2CSAR = ui16SlaveAddress;
// Configure transfer
I2caRegs.I2CCNT = ui8nbyte + 1; // Total bytes to send (command + data)
I2caRegs.I2CDXR = ui16CmdAddress; // Send command
// Send Start condition
I2caRegs.I2CMDR.all = 0x6E20; // STT=1 (Start), TRX=1 (Transmit), MST=1 (Master), IRS=1 (I2C enable)
// Wait for TX ready (XRDY)
while (I2caRegs.I2CSTR.bit.XRDY == 0);
// Send data bytes
for (i = 0; i < ui8nbyte; i++)
{
I2caRegs.I2CDXR = pui16WriteBuffer[i]; // Load data to transmit buffer
// Wait for TX ready (XRDY)
while (I2caRegs.I2CSTR.bit.XRDY == 0);
}
// Send STOP condition
I2caRegs.I2CMDR.bit.STP = 1;
// Check if I2C acknowledged
if (I2caRegs.I2CSTR.bit.NACK == 1)
{
return false;
}
return true;
}