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.

I2CReadWrite function with I2C3



Dear TI expert,

I am working on project with TM4C123GXL device where I need to write and read from I2C Slave Device connected to the TM4C123GXL board.
Is there any possible function to ReadWrite  from slave ?


I used I2CMRead  function available from library installed as below but looks read/write is not correct.

Error_t TI_I2C_WriteRead(unsigned char sla,
                int num_write_bytes,
                unsigned char write_data[],
                int num_read_bytes,
                unsigned char read_buffer[] )

{
    return I2CMRead(&tfa_sI2CInst, sla,
                             write_data,
                             num_write_bytes,
                             read_buffer,
                             num_read_bytes,
                             NULL,
                             NULL);
}


My sequence is as follows :

int main(void)
{

    // Configure the system frequency.
        //
        /*ROM_SysCtlClockSet*/SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                           SYSCTL_OSC_MAIN);

        //
        // Initialize the UART.
        //
        ConfigureUART();

        //
        // Clear the terminal and print the welcome message.

        // The I2C3 peripheral must be enabled before use.
        //
        /*ROM_SysCtlPeripheralEnable*/SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3);
        /*ROM_SysCtlPeripheralEnable*/SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

        //
        // Configure the pin muxing for I2C3 functions on port D0 and D1.
        // This step is not necessary if your part does not support pin muxing.
        //
        /*ROM_GPIOPinConfigure*/GPIOPinConfigure(GPIO_PD0_I2C3SCL);
        /*ROM_GPIOPinConfigure*/GPIOPinConfigure(GPIO_PD1_I2C3SDA);

        //
        // Select the I2C function for these pins.  This function will also
        // configure the GPIO pins pins for I2C operation, setting them to
        // open-drain operation with weak pull-ups.  Consult the data sheet
        // to see which functions are allocated per pin.
        //
        GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);
        /*ROM_GPIOPinTypeI2C*/GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1);
        HWREG(GPIO_PORTD_BASE + GPIO_O_PUR) = 0x3;

        //
        //Initial the GPIO for LED
        //
        /*ROM_SysCtlPeripheralEnable*/SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        /*ROM_GPIOPinTypeGPIOOutput*/GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
        /*ROM_GPIOPinWrite*/GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x00);

      
        //
        /*ROM_IntMasterEnable*/IntMasterEnable();

        //
        // Initialize I2C3 peripheral.
        //
        I2CMInit(&tfa_sI2CInst, I2C3_BASE, INT_I2C3, 0xff, 0xff,
                 /*ROM_SysCtlClockGet*/SysCtlClockGet());
 

        I2CMasterInitExpClk(I2C3_BASE, SysCtlClockGet(),true/*true*/);//400KBps

Then calling my function 


TI_I2C_WriteRead()  like
TI_I2C_WriteRead(slave_address,
    sizeof(write_data), write_data, sizeof(read_buffer), read_buffer);

}

However saw read from I2C is not rerturning correct value , is this function useful ? if no, any other possible function to read/write buffer from/To I2C ?

Any idea please ?

Maw,

  • Hi Maw,
    Where do you get the I2CMRead() API from? It does not look like a TivaWare I2C API. Did you have a chance to look at some of the I2C examples from the TivaWare library? They can be a good starting point for your development. They are located in <TivaWare_Installation>/examples/peripherals/i2c.
    Below I2C app note is also a good reference with example collaterals.
    www.ti.com/.../spma073.pdf

    Please also make sure you have proper pullup resistors on the SCL and SDA bus.
  • Hi Charles,
    I got this function from your examples under
    C:\ti\TivaWare_C_Series-2.1.4.178\sensorlib
    There is i2cm_drv.c and i2cm_drv.h files




    //*****************************************************************************
    #define I2CM_RMW_STATE_IDLE 0
    #define I2CM_RMW_STATE_READ 1
    #define I2CM_RMW_STATE_WRITE 2

    //*****************************************************************************
    //
    //! Writes data to an I2C device.
    //!
    //! \param psInst is a pointer to the I2C master instance data.
    //! \param ui8Addr is the address of the I2C device to access.
    //! \param pui8Data is a pointer to the data buffer to be written.
    //! \param ui16Count is the number of bytes to be written.
    //! \param pfnCallback is the function to be called when the write has
    //! completed (can be \b NULL if a callback is not required).
    //! \param pvCallbackData is a pointer that is passed to the callback function.
    //!
    //! This function adds an I2C write to the queue of commands to be sent. If
    //! successful, the I2C write is then performed in the background using the
    //! interrupt handler. When the write is complete, the callback function, if
    //! provided, is called in the context of the I2C master interrupt handler.
    //!
    //! The first byte of the data buffer contains the I2C address of the device to
    //! access, and the remaining \e ui16Count bytes contain the data to be written
    //! to the device. The \e ui16Count parameter can be zero if there are no
    //! bytes to be written.
    //!
    //! \return Returns 1 if the command was successfully added to the queue and 0
    //! if it was not.
    //
    // The extern here provides a non-inline definition for this function to handle
    // the case where the compiler chooses not to inline the function (which is a
    // valid choice for the compiler to make).
    //
    //*****************************************************************************
    extern uint_fast8_t I2CMWrite(tI2CMInstance *psInst, uint_fast8_t ui8Addr,
    const uint8_t *pui8Data, uint_fast16_t ui16Count,
    tSensorCallback pfnCallback,
    void *pvCallbackData);

    //*****************************************************************************
    //
    //! Reads data from an I2C device.
    //!
    //! \param psInst is a pointer to the I2C master instance data.
    //! \param ui8Addr is the address of the I2C device to access.
    //! \param pui8WriteData is a pointer to the data buffer to be written.
    //! \param ui16WriteCount is the number of bytes to be written.
    //! \param pui8ReadData is a pointer to the buffer to be filled with the read
    //! data.
    //! \param ui16ReadCount is the number of bytes to be read.
    //! \param pfnCallback is the function to be called when the transfer has
    //! completed (can be \b NULL if a callback is not required).
    //! \param pvCallbackData is a pointer that is passed to the callback function.
    //!
    //! This function adds an I2C read to the queue of commands to be sent. If
    //! successful, the I2C read is then performed in the background using the
    //! interrupt handler. When the read is complete, the callback function, if
    //! provided, is called in the context of the I2C master interrupt handler.
    //!
    //! The first byte of \e pui8WriteData contains the I2C address of the device
    //! to access, the next \e ui16WriteCount bytes contains the data to be written
    //! to the device. The data read from the device is written into the first
    //! \e ui16ReadCount bytes of \e pui8ReadData. The \e ui16WriteCount or
    //! \e ui16ReadCount parameters can be zero if there are no bytes to be read or
    //! written. The write bytes are sent to the device first, and then the read
    //! bytes are read from the device afterward.
    //!
    //! \return Returns 1 if the command was successfully added to the queue and 0
    //! if it was not.
    //
    // The extern here provides a non-inline definition for this function to handle
    // the case where the compiler chooses not to inline the function (which is a
    // valid choice for the compiler to make).
    //
    //*****************************************************************************
    extern uint_fast8_t I2CMRead(tI2CMInstance *psInst, uint_fast8_t ui8Addr,
    const uint8_t *pui8WriteData,
    uint_fast16_t ui16WriteCount,
    uint8_t *pui8ReadData,
    uint_fast16_t ui16ReadCount,
    tSensorCallback pfnCallback,
    void *pvCallbackData);

    //*****************************************************************************
    //
    //! Writes data in batches to an I2C device.
    //!
    //! \param psInst is a pointer to the I2C master instance data.
    //! \param ui8Addr is the address of the I2C device to access.
    //! \param pui8Data is a pointer to the data buffer to be written.
    //! \param ui16Count is the number of bytes to be written.
    //! \param ui16BatchSize is the number of bytes in each write batch.
    //! \param pfnCallback is the function to be called when the transfer has
    //! completed (can be \b NULL if a callback is not required).
    //! \param pvCallbackData is a pointer that is passed to the callback function.
    //!
    //! This function adds an I2C write to the queue of commands to be sent. If
    //! successful, the I2C write is then performed in the background using the
    //! interrupt handler. When the write is complete, the callback function, if
    //! provided, is called in the context of the I2C master interrupt handler.
    //!
    //! The first byte of the data buffer contains the I2C address of the device to
    //! access, and the remaining \e ui16Count bytes contain the data to be written
    //! to the device. The \e ui16Count parameter can be zero if there are no
    //! bytes to be written.
    //!
    //! The data is written in batches of \e ui16WriteBatchSize. The callback
    //! function is called after each batch is written, and I2CMTransferResume()
    //! must be called when the next batch should be written.
    //!
    //! \return Returns 1 if the command was successfully added to the queue and 0
    //! if it was not.
    //
    // The extern here provides a non-inline definition for this function to handle
    // the case where the compiler chooses not to inline the function (which is a
    // valid choice for the compiler to make).
    //


    Anything wrong here ?

    Thanks a lot for your advice.

    Cheers
    Maw.
  • Hi Maw,
    Sorry, I didn't realize that this is from the sensorlib library. Normally people use the TivaWare Peripheral driver library for simple I2C communication. The Peripheral driver library is located in <TivaWare_Installation>/driverlib. The I2C examples using the Peripheral driver library can be found under <TivaWare_Installation>/examples/peripherals/i2c. As I mentioned in the last reply, the I2C app note is a good reference to use the various I2C Peripheral driver library API s. With that said, if you want to use the sensorlib library you can refer to the example code listed in the TivaWare Sensor Library User's guide on section 8.3 from page 79-82. The sensor library is implemented with several abstraction layers. It may take a little bit more effort to understand compared to the TivaWare Peripheral driver library. The Sensor Library user's guide (SW-TM4C-SENSORLIB-UG-2.1.4.178.pdf) as well as all other documents can be found under <TivaWare_Installation>/docs.
  • Hi Charles,

    Crack staff/I - were as "surprised" by this "sensorlib" code - as you!    And you are SO right - adding complexity - as always - proves the "Longest Path" to project completion - especially to simple understanding!

    Use of "KISS" - as represented by your (proper) direction to the PDL & API - surely, "Speeds, Eases, Enhances"  Poster EASE - and odds of poster success...   Not so much "sensorlib" (tall mountains are (usually) the LAST to be climbed (or attempted) - and that for good reason.)

  • Hi cb1,
    I agree. Hopefully the poster will find the TivaWare Peripheral Driver Library easy to use in accomplishing his application let alone the wealth of past forum posts related to the I2C module.
  • Dear All,

    Thanks very much, I implmented my own driver based on TI I2C specification and it worked fine.

    Best regards,

    Maw,