This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335: I2C Read Write on Polling

Part Number: TMS320F28335


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;
}

  • Hi Kaushik

    Thank you for reaching out.

    But When i run the code Continuesly - data is not correct as i can analysed in watch window.

    So you are getting at least some data. Do you have access to a logic analyzer/scope to see the exact data packets which are being received by the C2000 device?

    Differences between step-wise code and normal running code indicates a timing issue. When you are stepping through the code, are you setting a break point at each instance run of the while loop? What else do you have in your main loop? You may want to move the polling from the while loop to a background task running at consistent frequency.

    You also may consider utilizing the RRDYINT native to the I2C module which will prevent you from having to continually poll the I2C register

    Regards,

    Peter