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.

TMS320F280049C: F280049C - I2C Example

Part Number: TMS320F280049C
Other Parts Discussed in Thread: C2000WARE

Hello dear colleagues.

I am trying to learn the I2C module but the examples below the driverlib was complex for me. Can someone share a basic I2C example(Read/Write operation) without interrupt?

  • We don't currently have any examples in C2000Ware that don't use the I2C interrupts. You should be able to adjust the code to use I2C_getInterruptStatus() to check if there's data to receive or if the I2C is ready to send more data.

    You can try searching the forum for examples too. People sometimes share snippets that might help.

    Whitney

  • Hi Mohammad,

    Can you share your I2C config and write/read function code that's giving issues?
  • //#############################################################################
    //
    // FILE:   i2c_ex2_eeprom.c
    //
    // TITLE:  I2C EEPROM
    //
    //! \addtogroup driver_example_list
    //! <h1>I2C EEPROM</h1>
    //!
    //! This program will write 1-14 words to EEPROM and read them back. The data
    //! written and the EEPROM address written to are contained in the message
    //! structure, i2cMsgOut. The data read back will be contained in the message
    //! structure i2cMsgIn.gIn.
    //!
    //! \b External \b Connections \n
    //!  - Connect external I2C EEPROM at address 0x50
    //!  - Connect GPIO32/SDAA on controlCARD to external EEPROM SDA (serial data) pin
    //!  - Connect GPIO33/SCLA on controlCARD to external EEPROM SCL (serial clock) pin
    //!
    //! \b Watch \b Variables \n
    //!  - \b i2cMsgOut - Message containing data to write to EEPROM
    //!  - \b i2cMsgIn - Message containing data read from EEPROM
    //!
    //
    //#############################################################################
    // $TI Release: F28004x Support Library v1.05.00.00 $
    // $Release Date: Thu Oct 18 15:43:57 CDT 2018 $
    // $Copyright:
    // Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //#############################################################################
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    
    //
    // Defines
    //
    #define SLAVE_ADDRESS               0xCE
    #define EEPROM_HIGH_ADDR            0x02
    #define EEPROM_LOW_ADDR             0x03
    #define NUM_BYTES                   8
    #define MAX_BUFFER_SIZE             14      // Max is currently 14 because of
                                                // 2 address bytes and the 16-byte
                                                // FIFO
    
    //
    // I2C message states for I2CMsg struct
    //
    #define MSG_STATUS_INACTIVE         0x0000 // Message not in use, do not send
    #define MSG_STATUS_SEND_WITHSTOP    0x0010 // Send message with stop bit
    #define MSG_STATUS_WRITE_BUSY       0x0011 // Message sent, wait for stop
    #define MSG_STATUS_SEND_NOSTOP      0x0020 // Send message without stop bit
    #define MSG_STATUS_SEND_NOSTOP_BUSY 0x0021 // Message sent, wait for ARDY
    #define MSG_STATUS_RESTART          0x0022 // Ready to become master-receiver
    #define MSG_STATUS_READ_BUSY        0x0023 // Wait for stop before reading data
    
    //
    // Error messages for read and write functions
    //
    #define ERROR_BUS_BUSY              0x1000
    #define ERROR_STOP_NOT_READY        0x5555
    #define SUCCESS                     0x0000
    
    //
    // Typedefs
    //
    struct I2CMsg {
        uint16_t msgStatus;                  // Word stating what state msg is in.
                                             // See MSG_STATUS_* defines above.
        uint16_t slaveAddr;                  // Slave address tied to the message.
        uint16_t numBytes;                   // Number of valid bytes in message.
        uint16_t memoryHighAddr;             // EEPROM address of data associated
                                             // with message (high byte).
        uint16_t memoryLowAddr;              // EEPROM address of data associated
                                             // with message (low byte).
        uint16_t msgBuffer[MAX_BUFFER_SIZE]; // Array holding message data.
    };
    
    //
    // Globals
    //
    struct I2CMsg i2cMsgOut = {MSG_STATUS_SEND_WITHSTOP,
                               SLAVE_ADDRESS,
                               NUM_BYTES,
                               EEPROM_HIGH_ADDR,
                               EEPROM_LOW_ADDR,
                               0x01,                // Message bytes
                               0x23,
                               0x45,
                               0x67,
                               0x89,
                               0xAB,
                               0xCD,
                               0xEF};
    struct I2CMsg i2cMsgIn  = {MSG_STATUS_SEND_NOSTOP,
                               SLAVE_ADDRESS,
                               NUM_BYTES,
                               EEPROM_HIGH_ADDR,
                               EEPROM_LOW_ADDR};
    
    struct I2CMsg *currentMsgPtr;                   // Used in interrupt
    
    uint16_t passCount = 0;
    uint16_t failCount = 0;
    
    //
    // Function Prototypes
    //
    void initI2C(void);
    uint16_t readData(struct I2CMsg *msg);
    uint16_t writeData(struct I2CMsg *msg);
    
    void fail(void);
    void pass(void);
    
    __interrupt void i2cAISR(void);
    
    //
    // Main
    //
    void main(void)
    {
        uint16_t error;
        uint16_t i;
    
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pullups.
        //
        Device_initGPIO();
    
        //
        // Initialize GPIOs 32 and 33 (35 and 37 on LaunchPad)
        // for use as SDA A and SCL A respectively
        //
        GPIO_setPinConfig(GPIO_26_SDAA);
        GPIO_setPadConfig(26U, GPIO_PIN_TYPE_PULLUP);
        GPIO_setQualificationMode(26U, GPIO_QUAL_ASYNC);
    
        GPIO_setPinConfig(GPIO_27_SCLA);
        GPIO_setPadConfig(27U, GPIO_PIN_TYPE_PULLUP);
        GPIO_setQualificationMode(27U, GPIO_QUAL_ASYNC);
    
        //
        // Initialize PIE and clear PIE registers. Disable CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // Interrupts that are used in this example are re-mapped to ISR functions
        // found within this file.
        //
        Interrupt_register(INT_I2CA, &i2cAISR);
    
        //
        // Set I2C use, initializing it for FIFO mode
        //
        initI2C();
    
        //
        // Clear incoming message buffer
        //
        for (i = 0; i < MAX_BUFFER_SIZE; i++)
        {
            i2cMsgIn.msgBuffer[i] = 0x0000;
        }
    
        //
        // Set message pointer used in interrupt to point to outgoing message
        //
        currentMsgPtr = &i2cMsgOut;
    
        //
        // Enable interrupts required for this example
        //
        Interrupt_enable(INT_I2CA);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //
        // Loop indefinitely
        //
        while(1)
        {
            //
            // **** Write data to EEPROM section ****
            //
            // Check the outgoing message to see if it should be sent. In this
            // example it is initialized to send with a stop bit.
            //
    //        if(i2cMsgOut.msgStatus == MSG_STATUS_SEND_WITHSTOP)
    //        {
    //            //
    //            // Send the data to the EEPROM
    //            //
    //            error = writeData(&i2cMsgOut);
    //
    //            //
    //            // If communication is correctly initiated, set msg status to busy
    //            // and update currentMsgPtr for the interrupt service routine.
    //            // Otherwise, do nothing and try again next loop. Once message is
    //            // initiated, the I2C interrupts will handle the rest. See the
    //            // function i2cAISR().
    //            //
    //            if(error == SUCCESS)
    //            {
    //                currentMsgPtr = &i2cMsgOut;
    //                i2cMsgOut.msgStatus = MSG_STATUS_WRITE_BUSY;
    //            }
    //        }
    
            //
            // **** Read data from EEPROM section ****
            //
            // Check outgoing message status. Bypass read section if status is
            // not inactive.
            //
            if (i2cMsgOut.msgStatus == MSG_STATUS_INACTIVE)
            {
                //
                // Check incoming message status
                //
                if(i2cMsgIn.msgStatus == MSG_STATUS_SEND_NOSTOP)
                {
                    //
                    // Send EEPROM address setup
                    //
                    while(readData(&i2cMsgIn) != SUCCESS)
                    {
                        //
                        // Maybe setup an attempt counter to break an infinite
                        // while loop. The EEPROM will send back a NACK while it is
                        // performing a write operation. Even though the write
                        // is complete at this point, the EEPROM could still be
                        // busy programming the data. Therefore, multiple
                        // attempts are necessary.
                        //
                    }
    
                  //
                  // Update current message pointer and message status
                  //
                  currentMsgPtr = &i2cMsgIn;
                  i2cMsgIn.msgStatus = MSG_STATUS_SEND_NOSTOP_BUSY;
               }
    
                //
                // Once message has progressed past setting up the internal address
                // of the EEPROM, send a restart to read the data bytes from the
                // EEPROM. Complete the communique with a stop bit. msgStatus is
                // updated in the interrupt service routine.
                //
                else if(i2cMsgIn.msgStatus == MSG_STATUS_RESTART)
                {
                    //
                    // Read data portion
                    //
                    while(readData(&i2cMsgIn) != SUCCESS)
                    {
                        //
                        // Maybe setup an attempt counter to break an infinite
                        // while loop.
                        //
                    }
    
                    //
                    // Update current message pointer and message status
                    //
                    currentMsgPtr = &i2cMsgIn;
                    i2cMsgIn.msgStatus = MSG_STATUS_READ_BUSY;
                }
            }
        }
    }
    
    //
    // Function to configure I2C A in FIFO mode.
    //
    void initI2C()
    {
        //
        // Must put I2C into reset before configuring it
        //
        I2C_disableModule(I2CA_BASE);
    
        //
        // I2C configuration. Use a 400kHz I2CCLK with a 33% duty cycle.
        //
        I2C_initMaster(I2CA_BASE, DEVICE_SYSCLK_FREQ, 400000, I2C_DUTYCYCLE_33);
        I2C_setBitCount(I2CA_BASE, I2C_BITCOUNT_8);
        I2C_setSlaveAddress(I2CA_BASE, SLAVE_ADDRESS);
        I2C_setEmulationMode(I2CA_BASE, I2C_EMULATION_FREE_RUN);
    
        //
        // Enable stop condition and register-access-ready interrupts
        //
        I2C_enableInterrupt(I2CA_BASE, I2C_INT_STOP_CONDITION |
                                       I2C_INT_REG_ACCESS_RDY);
    
        //
        // FIFO configuration
        //
        I2C_enableFIFO(I2CA_BASE);
        I2C_clearInterruptStatus(I2CA_BASE, I2C_INT_RXFF | I2C_INT_TXFF);
    
        //
        // Configuration complete. Enable the module.
        //
        I2C_enableModule(I2CA_BASE);
    }
    
    //
    // Function to send the data that is to be written to the EEPROM
    //
    uint16_t writeData(struct I2CMsg *msg)
    {
        uint16_t i;
    
        //
        // Wait until the STP bit is cleared from any previous master
        // communication. Clearing of this bit by the module is delayed until after
        // the SCD bit is set. If this bit is not checked prior to initiating a new
        // message, the I2C could get confused.
        //
        if(I2C_getStopConditionStatus(I2CA_BASE))
        {
            return(ERROR_STOP_NOT_READY);
        }
    
        //
        // Setup slave address
        //
        I2C_setSlaveAddress(I2CA_BASE, SLAVE_ADDRESS);
    
        //
        // Check if bus busy
        //
        if(I2C_isBusBusy(I2CA_BASE))
        {
            return(ERROR_BUS_BUSY);
        }
    
        //
        // Setup number of bytes to send msgBuffer and address
        //
        I2C_setDataCount(I2CA_BASE, (msg->numBytes + 2));
    
        //
        // Setup data to send
        //
        I2C_putData(I2CA_BASE, msg->memoryHighAddr);
        I2C_putData(I2CA_BASE, msg->memoryLowAddr);
    
        for (i = 0; i < msg->numBytes; i++)
        {
            I2C_putData(I2CA_BASE, msg->msgBuffer[i]);
        }
    
        //
        // Send start as master transmitter
        //
        I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
        I2C_sendStartCondition(I2CA_BASE);
        I2C_sendStopCondition(I2CA_BASE);
    
        return(SUCCESS);
    }
    
    //
    // Function to prepare for the data that is to be read from the EEPROM
    //
    uint16_t readData(struct I2CMsg *msg)
    {
        //
        // Wait until the STP bit is cleared from any previous master
        // communication. Clearing of this bit by the module is delayed until after
        // the SCD bit is set. If this bit is not checked prior to initiating a new
        // message, the I2C could get confused.
        //
        if(I2C_getStopConditionStatus(I2CA_BASE))
        {
            return(ERROR_STOP_NOT_READY);
        }
    
        //
        // Setup slave address
        //
        I2C_setSlaveAddress(I2CA_BASE, SLAVE_ADDRESS);
    
        //
        // If we are in the the address setup phase, send the address without a
        // stop condition.
        //
        if(msg->msgStatus == MSG_STATUS_SEND_NOSTOP)
        {
            //
            // Check if bus busy
            //
            if(I2C_isBusBusy(I2CA_BASE))
            {
                return(ERROR_BUS_BUSY);
            }
    
            //
            // Send data to setup EEPROM address
            //
            I2C_setDataCount(I2CA_BASE, 2);
            I2C_putData(I2CA_BASE, msg->memoryHighAddr);
            I2C_putData(I2CA_BASE, msg->memoryLowAddr);
            I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
            I2C_sendStartCondition(I2CA_BASE);
        }
        else if(msg->msgStatus == MSG_STATUS_RESTART)
        {
            //
            // Address setup phase has completed. Now setup how many bytes expected
            // and send restart as master-receiver.
            //
            I2C_setDataCount(I2CA_BASE, (msg->numBytes));
            I2C_setConfig(I2CA_BASE, I2C_MASTER_RECEIVE_MODE);
            I2C_sendStartCondition(I2CA_BASE);
            I2C_sendStopCondition(I2CA_BASE);
        }
    
        return(SUCCESS);
    }
    
    //
    // I2C A ISR (non-FIFO)
    //
    __interrupt void i2cAISR(void)
    {
        I2C_InterruptSource intSource;
        uint16_t i;
    
        //
        // Read interrupt source
        //
        intSource = I2C_getInterruptSource(I2CA_BASE);
    
        //
        // Interrupt source = stop condition detected
        //
        if(intSource == I2C_INTSRC_STOP_CONDITION)
        {
            //
            // If completed message was writing data, reset msg to inactive state
            //
            if(currentMsgPtr->msgStatus == MSG_STATUS_WRITE_BUSY)
            {
                currentMsgPtr->msgStatus = MSG_STATUS_INACTIVE;
            }
            else
            {
                //
                // If a message receives a NACK during the address setup portion of
                // the EEPROM read, the code further below included in the register
                // access ready interrupt source code will generate a stop
                // condition. After the stop condition is received (here), set the
                // message status to try again. User may want to limit the number
                // of retries before generating an error.
                //
                if(currentMsgPtr->msgStatus == MSG_STATUS_SEND_NOSTOP_BUSY)
                {
                    currentMsgPtr->msgStatus = MSG_STATUS_SEND_NOSTOP;
                }
                //
                // If completed message was reading EEPROM data, reset message to
                // inactive state and read data from FIFO.
                //
                else if(currentMsgPtr->msgStatus == MSG_STATUS_READ_BUSY)
                {
                    currentMsgPtr->msgStatus = MSG_STATUS_INACTIVE;
                    for(i=0; i < NUM_BYTES; i++)
                    {
                        currentMsgPtr->msgBuffer[i] = I2C_getData(I2CA_BASE);
                    }
    
                    //
                    // Check received data
                    //
                    for(i=0; i < NUM_BYTES; i++)
                    {
                        if(i2cMsgIn.msgBuffer[i] == i2cMsgOut.msgBuffer[i])
                        {
                            passCount++;
                        }
                        else
                        {
                            failCount++;
                        }
                    }
    
                    if(passCount == NUM_BYTES)
                    {
                        pass();
                    }
                    else
                    {
                        fail();
                    }
                }
            }
        }
        //
        // Interrupt source = Register Access Ready
        //
        // This interrupt is used to determine when the EEPROM address setup
        // portion of the read data communication is complete. Since no stop bit
        // is commanded, this flag tells us when the message has been sent
        // instead of the SCD flag.
        //
        else if(intSource == I2C_INTSRC_REG_ACCESS_RDY)
        {
            //
            // If a NACK is received, clear the NACK bit and command a stop.
            // Otherwise, move on to the read data portion of the communication.
            //
            if((I2C_getStatus(I2CA_BASE) & I2C_STS_NO_ACK) != 0)
            {
                I2C_sendStopCondition(I2CA_BASE);
                I2C_clearStatus(I2CA_BASE, I2C_STS_NO_ACK);
            }
            else if(currentMsgPtr->msgStatus == MSG_STATUS_SEND_NOSTOP_BUSY)
            {
                currentMsgPtr->msgStatus = MSG_STATUS_RESTART;
            }
        }
        else
        {
            //
            // Generate some error from invalid interrupt source
            //
            asm("   ESTOP0");
        }
    
        //
        // Issue ACK to enable future group 8 interrupts
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    }
    
    //
    // Function to be called if data written matches data read
    //
    void pass(void)
    {
        asm("   ESTOP0");
        for(;;);
    }
    
    //
    // Function to be called if data written does NOT match data read
    //
    void fail(void)
    {
        asm("   ESTOP0");
        for(;;);
    }
    

    I'm trying to modify to code to read voltage value from LTC4151 and ADR1=H ADR0=L. Can you tell me what am I doing wrong here?

  • I'm not familiar with the LTC4151, but the way the EEPROM in this example works is that you need to send a two word address (memoryHighAddr, memoryLowAddr) first in every interaction. I don't think the LTC4151 has this same message format. Please study its datasheet to get a better idea of what kind of message it expects.

    Also, I2C addresses are typically 7 bits, so a slave address of 0xCE seems unlikely. That uppermost bit will be ignored.

    Whitney
  • According to LT4151 datasheet

    So. According to my connections my slave address is 0xCE but when I send the second start command I have to send 0xCF. Still somethings are not right :\

  • I think this table is treating the R/W bit like the 0th bit of the address. With our hardware though, the R/W bit will be configured by the I2C module based off of whether or not you're in I2C_MASTER_SEND_MODE or I2C_MASTER_RECEIVE_MODE. So when you program the slave address in the slave address register use the hex value in the table right shifted by one--so (0xCE >> 1) or 0x67.

    Whitney
  • Okay I will try that out and let you know but first can you see any mistake in my code? It's based on driverlib i2c_eeprom code.

  • I managed to get some readings thanks to you. I am doing my readings in a while loop and each loop the voltage I have been measured through IC is changing. For example my Vin = 20V and I have to read like 19.5V- 20V but in one cycle I read like 19.8 and at the other I read 40 etc. How can we solve this? Do I need any delay between reads?
  • Glad you hear you can communicate with the LTC4151 now. Does it's datasheet give any indication whether it needs a delay between reads? From a C2000 I2C standpoint, as long as the I2C flags say that you've sent the stop condition and the register access is ready to send another message, you shouldn't have to delay unless the slave device needs you to.

    Whitney
  • I somehow managed to read the data I need. But now I am trying to write a library for it. I managed to read Vin value and sense current value but I can't read them at the same time. Can you review my codes if I share at here?
  • If you have questions about a particular section of the code or about the I2C, I'd be happy to help answer it. I can't review an entire application though.

    Whitney
  • Okay this is my interrupt side. I used tags to store data values (Sense Reg, Vin, ADIN and control reg. values) to different variables to prevent any mistake.

    __interrupt void i2cAISR(void)
    {
        I2C_InterruptSource intSource;
        intSource = I2C_getInterruptSource(I2CA_BASE);
    
        if(intSource == I2C_INTSRC_STOP_CONDITION)
        {
            if(Tags_s.TAG_u16 == 0)
            {
                SENSE_MSB_u16 = I2C_getData(I2CA_BASE);
                SENSE_LSB_u16 = I2C_getData(I2CA_BASE);
                Tags_s.TAG_u16 = 4;
            }
            else if(Tags_s.TAG_u16 == 1)
            {
                VIN_MSB_u16 = I2C_getData(I2CA_BASE);
                VIN_LSB_u16 = I2C_getData(I2CA_BASE);
                Tags_s.TAG_u16 = 4;
            }
            else if(Tags_s.TAG_u16 == 2)
            {
                ADIN_MSB_u16 = I2C_getData(I2CA_BASE);
                ADIN_LSB_u16 = I2C_getData(I2CA_BASE);
                Tags_s.TAG_u16 = 4;
            }
            else if(Tags_s.TAG_u16 == 3)
            {
                CONTROL_MSB_u16 = I2C_getData(I2CA_BASE);
                Tags_s.TAG_u16 = 4;
            }
            RegAccessRdyFlag_b = false;
    
        }
        else if(intSource == I2C_INTSRC_REG_ACCESS_RDY)
        {
                RegAccessRdyFlag_b = true;
        }
    
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    }
    

    I created these functions to read values

    void LTC4151_Read_Input_Voltage(uint16_t RegisterToRead, uint16_t NumberOfBytes, uint16_t TAG);
    void LTC4151_Read_ADIN_Voltage(uint16_t RegisterToRead, uint16_t NumberOfBytes, uint16_t TAG);
    void LTC4151_Read_Control_Register(uint16_t RegisterToRead, uint16_t NumberOfBytes, uint16_t TAG);
    
    // To show what is inside of them I will share one of them
    
    void LTC4151_Read_Input_Voltage(uint16_t RegisterToRead, uint16_t NumberOfBytes, uint16_t TAG)
    {
        F28x_usDelay(1000000);
        LTC4151_Get_ADC(RegisterToRead, NumberOfBytes,  TAG);
        LTC4151_Variables_s.Input_Voltage_f32 = LTC4151_Calculations(RegisterToRead, NumberOfBytes, TAG);
    }

    And lastly I have an adcread function

    void LTC4151_Get_ADC(uint16_t RegisterToRead, uint16_t NumberOfBytes, uint16_t TAG)
    {
        if(I2C_getStopConditionStatus(I2CA_BASE))
        {
            LTC4151_Variables_s.Message_Status_u16 = D_ERROR_STOP_NOT_RDY;
        }
        /*
         * Set slave address
         */
        I2C_setSlaveAddress(I2CA_BASE, LTC4151_Variables_s.Slave_Address_u16);
        /*
         * Check if bus busy
         */
        if(I2C_isBusBusy(I2CA_BASE))
        {
            LTC4151_Variables_s.Message_Status_u16 = D_ERROR_I2C_BUS_BUSY;
        }
    
            I2C_setDataCount(I2CA_BASE, 1);
            I2C_putData(I2CA_BASE, RegisterToRead);
            I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
            I2C_sendStartCondition(I2CA_BASE);
    
        if(RegAccessRdyFlag_b == true)
        {
            I2C_setDataCount(I2CA_BASE, NumberOfBytes);
            I2C_setConfig(I2CA_BASE, I2C_MASTER_RECEIVE_MODE);
            I2C_sendStartCondition(I2CA_BASE);
            I2C_sendStopCondition(I2CA_BASE);
    
        }
    
        F28x_usDelay(10000);
        LTC4151_Variables_s.Message_Status_u16 = D_I2C_NO_ERROR;
    
    
    }

    As I said earlier my functions works indivicually but not when I put all of them in a loop.

  • Okay I managed to make my library work but with a little question mark on my head. The code below is my read code. I am doing repeated start but If I don't use delays the code doesn't work. My I2C configured to 400khz and if I am not wrong f280049C works at 60mhz. I thing the mcu is too fast for I2C but how can I calculate the correct time I need? I don't want to use delays I am thinking about adding timer interrupts but first I need to learn how to calculate how much time I need.

    uint16_t LTC4151_Get_ADC(uint16_t RegisterToRead, uint16_t NumberOfBytes)
    {
        /*
         * Wait until the STP bit is cleared from any previous master
         * communication. Clearing of this bit by the module is delayed until after
         * the SCD bit is set. If this bit is not checked prior to initiating a new
         * message, the I2C could get confused.
         *
         */
        if(I2C_getStopConditionStatus(I2CA_BASE))
        {
            return D_LTC4151_STOP_NOT_RDY;
        }
        /*
         * Set slave address
         */
        I2C_setSlaveAddress(I2CA_BASE, LTC4151_Variables_s.Slave_Address_u16);
    
    
        /*
         * Check if bus busy
         */
            if(I2C_isBusBusy(I2CA_BASE))
            {
                return D_LTC4151_BUS_BUSY;
            }
    
                I2C_setDataCount(I2CA_BASE, 1);
                I2C_putData(I2CA_BASE, RegisterToRead);
                I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
                I2C_sendStartCondition(I2CA_BASE);
    
                DEVICE_DELAY_US(33000);
    
        if(LTC4151_Variables_s.Message_Status_u16 == D_LTC4151_I2C_RESTART)
        {
            I2C_setDataCount(I2CA_BASE, NumberOfBytes);
            I2C_setConfig(I2CA_BASE, I2C_MASTER_RECEIVE_MODE);
            I2C_sendStartCondition(I2CA_BASE);
            I2C_sendStopCondition(I2CA_BASE);
    
        }
    
        DEVICE_DELAY_US(33000);
        return D_LTC4151_I2C_SUCCESS;
    
    }

  • Hi Frozen,

    Were you able to structure your code to work without delays?

    You might want to use an oscilloscope on the I2C bus to better understand the timings to understand why things are going wrong without the delays.

    It isn't clear to me exactly which I2C ISRs you are using, but it seems like maybe you are trying to send too much data through the I2C before it is done sending?  Maybe you need to include a TX FIFO ready interrupt and only send additional data at that time?

  • Were you able to resolve this issue?

    Whitney

  • I resolved my issue by changing the clock of the I2C module to 380khz %50 duty cycle but I really dont undertand why it didnt work with 400khz and %33 duty cycle. According to my calculation it has to work. Because in f280049C datasheet says

    SCLLOW minimum -->1.3us

    SCLHIGH minimum --> 0.6us

    According to my calculation 400khz with %33 duty

    SCLLOW --> 1.6us

    SCLHIGH --> 0.82us

    For 380khz %50 duty (This one works)

    SCLLOW --> 1.3us

    SCLHIGH --> 1.3us

    Can you explain to me what the real problem is? The picture below is from LTC4151 datasheet.

  • I couldn't say off the top of my head what would cause this. I agree that you appear to be meeting the minimum required high/low timings based on your calculation. Did you look at the waveforms on an oscilloscope/logic analyzer to confirm that the actual signal matched your calculations? Did you check the other required minimum timings?

    Whitney