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.

TMS320F28388D: F28388d / I2C Interface / Reading multiple bytes of data from slave

Part Number: TMS320F28388D
Other Parts Discussed in Thread: C2000WARE

Hi TI technical team!!

There is a question related to I2C reading.

** the current situation

1) Subject to control

Master - F28388d

Slave - IIS328DQ

2) The progress.

Read/Write One byte of data

Please refer to the attached code..

3) Q&A

Case 1. Uncomment line 100 and comment line 101 in the code.
status = I2CRead(I2CB_BASE, 24, 32, buffer, 1, 5); // READ CTRL_REG1 TO CTRL_REG5 registers
//status = I2CRead_T(I2CB_BASE, 24, 32, buffer, 5); // READ CTRL_REG1 TO CTRL_REG5 registers

---> Read 1-byte data five times repeatedly.
---> Read the following five register values consecutively from the start point register address. Refer to Figure 1.
---> (ST / SAD + W / SAK / SUB / SAK / SR / SAD + R / SAK / DATA_n / NMAK / SP) X 5


Case 2. Comment line 100 and uncomment line 101 in the code.
//status = I2CRead(I2CB_BASE, 24, 32, buffer, 1, 5); // READ CTRL_REG1 TO CTRL_REG5 registers
status = I2CRead_T(I2CB_BASE, 24, 32, buffer, 5); // READ CTRL_REG1 TO CTRL_REG5 registers

---> The value of the start point register address is read 5 times (same value). See Figure 2.
---> (ST / SAD + W / SAK / SUB / SAK / SR / SAD + R / SAK / DATA1 / DATA1 / DATA1 / DATA1 / DATA1 / SP)

Q. I want to read multi-byte data and get the same result as Case 1.
---> (ST / SAD + W / SAK / SUB / SAK / SR / SAD + R / SAK / DATA1 / MAK / DATA2 / MAK / DATA3 / .... / DATA5 / NMAK / SP)

How can I modify the 'i2cRead_T' function in the attached code?

I need a help

Kind regard

JM LEE

  • // https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/773723/ccs-tms320f28379d-c2000-microcontrollers-forum
    // IIS328DQ TEST Project
    //
    // Included Files
    //
    #include "F28x_Project.h"
    #include "driverlib.h"
    #include "device.h"
    
    //
    // Defines
    //
    
    #define MAX_BUF_SIZE                6
    #define ERROR_STOP_NOT_READY        0x5555
    #define ERROR_BUS_BUSY              0x1000
    
    //
    // Globals
    //
    
    volatile int data_ready_flag = 0;
    volatile int data_count;
    volatile uint16_t reg_ready;
    volatile I2C_InterruptSource intSource;
    
    // buffer to store data read
    //uint16_t data_temp;
    uint16_t buffer[MAX_BUF_SIZE];
    uint16_t status = 0;
    
    //
    // Function Prototypes
    //
    void I2Cinit(void);
    void I2C_GPIO_init(void);
    int16_t I2CRead(uint32_t base, uint16_t slaveAddr, uint16_t regAddr,uint16_t *data, uint16_t data_length, uint16_t read_count);
    int16_t i2cRead(uint32_t base, uint16_t slaveAddr, uint16_t regAddr, uint16_t *data, uint16_t data_length);
    int16_t I2CRead_T(uint32_t base, uint16_t slaveAddr, uint16_t regAddr,uint16_t *data, uint16_t data_length);
    int16_t i2cRead_T(uint32_t base, uint16_t slaveAddr, uint16_t regAddr, uint16_t *data, uint16_t data_length);
    int16_t i2cWriteMulti(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t *data,uint16_t data_length);
    int16_t i2cWrite(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t data);
    __interrupt void i2cISR();
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pullups.
        //
        Device_initGPIO();
    
        //
        // Initialize I2C pins
        //
        I2C_GPIO_init();
    
        //
        // 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();
    
        I2Cinit();
    
        //
        // Interrupts that are used in this example are re-mapped to ISR functions
        // found within this file.
        //
        Interrupt_register(INT_I2CB, &i2cISR);
        Interrupt_enable(INT_I2CB);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //i2cWrite(I2CB_BASE,24,32,7);
        i2cWrite(I2CB_BASE,24,36,3);
        DELAY_US(400);
        i2cWrite(I2CB_BASE,24,33,35);
        DELAY_US(400);
    
    
        while (1)
        {
            //status = I2CRead(I2CB_BASE, 24, 32, buffer, 1, 5);    // READ CTRL_REG1 TO CTRL_REG5 registers
            status = I2CRead_T(I2CB_BASE, 24, 32, buffer, 5);       // READ CTRL_REG1 TO CTRL_REG5 registers
    
            DELAY_US(400);                                          // Trigger Monitoring delay(No meaning)
        }
    
    }
    
    void I2C_GPIO_init(void)
    {
        // I2CB pins (SDAA / SCLA)
        GPIO_setDirectionMode(35, GPIO_DIR_MODE_IN);
        GpioCtrlRegs.GPBPUD.bit.GPIO35 = 1;
        GPIO_setMasterCore(35, GPIO_CORE_CPU1);
        GPIO_setQualificationMode(35, GPIO_QUAL_ASYNC);
    
        GPIO_setDirectionMode(40, GPIO_DIR_MODE_IN);
        GpioCtrlRegs.GPBPUD.bit.GPIO40 = 1;
        GPIO_setMasterCore(40, GPIO_CORE_CPU1);
        GPIO_setQualificationMode(40, GPIO_QUAL_ASYNC);
    
        GPIO_setPinConfig(GPIO_35_I2CB_SCL);
        GPIO_setPinConfig(GPIO_40_I2CB_SDA);
    }
    
    void I2Cinit(void)
    {
        I2C_disableModule (I2CB_BASE);
        I2C_disableLoopback(I2CB_BASE);
    
        // I2C configuration. Use a 100KHz I2C clock with a 50% duty cycle
        I2C_initMaster(I2CB_BASE, DEVICE_SYSCLK_FREQ, 100000, I2C_DUTYCYCLE_50);
    
        I2C_setBitCount(I2CB_BASE, I2C_BITCOUNT_8);
    
        I2C_setEmulationMode(I2CB_BASE, I2C_EMULATION_FREE_RUN);
    
        // enable stop condition and register-access-ready interrupts
        I2C_enableInterrupt(I2CB_BASE, I2C_INT_STOP_CONDITION | I2C_INT_REG_ACCESS_RDY);
    
        // FIFO configuration
        I2C_enableFIFO(I2CB_BASE);
        I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_RXFF | I2C_INT_TXFF);
    
        I2C_enableModule(I2CB_BASE);
    }
    
    int16_t i2cRead(uint32_t base, uint16_t slaveAddr, uint16_t regAddr, uint16_t *data, uint16_t data_length)
    {
        //  uint16_t count;
        if (I2C_getStopConditionStatus(base))
        {
            return ERROR_STOP_NOT_READY;
        }
        if (data_ready_flag == 0)
        {
            I2C_setSlaveAddress(base, slaveAddr);
            I2C_setDataCount(base, 1);
            I2C_putData(base, regAddr);
            I2C_setConfig(base, I2C_MASTER_SEND_MODE);
            I2C_sendStartCondition(base);
            reg_ready = 1;
        }
    
        if (data_ready_flag == 1)
        {
            I2C_setDataCount(base, data_length);
            I2C_setConfig(base, I2C_MASTER_RECEIVE_MODE);
            I2C_sendStartCondition(base);
            I2C_sendStopCondition(base);
            while (data_ready_flag == 1);
        }
    
        return SUCCESS;
    }
    int16_t I2CRead(uint32_t base, uint16_t slaveAddr, uint16_t regAddr,uint16_t *data, uint16_t data_length, uint16_t read_count)
    {
        for (data_count = 0; data_count < read_count; data_count++)
        {
            while (i2cRead(base, slaveAddr, regAddr, data, data_length) != SUCCESS);
            while (data_ready_flag != 1);
            i2cRead(base, slaveAddr, regAddr, data, data_length);
            *(data + data_count) = I2C_getData(base);
            regAddr++;
        }
        return 1;
    }
    
    int16_t i2cRead_T(uint32_t base, uint16_t slaveAddr, uint16_t regAddr, uint16_t *data, uint16_t data_length)
    {
        //  uint16_t count;
        if (I2C_getStopConditionStatus(base))
        {
            return ERROR_STOP_NOT_READY;
        }
        if (data_ready_flag == 0)
        {
            I2C_setSlaveAddress(base, slaveAddr);
            I2C_setDataCount(base, 1);
            I2C_putData(base, regAddr);
            I2C_setConfig(base, I2C_MASTER_SEND_MODE);
            I2C_sendStartCondition(base);
            reg_ready = 1;
        }
    
        if (data_ready_flag == 1)
        {
            I2C_setDataCount(base, data_length);
            I2C_setConfig(base, I2C_MASTER_RECEIVE_MODE);
            I2C_sendStartCondition(base);
            I2C_sendStopCondition(base);
            while (data_ready_flag == 1)
                ;
            for (data_count = 0; data_count < data_length; data_count++)
            {
                *(data + data_count) = I2C_getData(base);
            }
        }
    
        return SUCCESS;
    }
    int16_t I2CRead_T(uint32_t base, uint16_t slaveAddr, uint16_t regAddr,uint16_t *data, uint16_t data_length)
    {
        while (i2cRead_T(base, slaveAddr, regAddr, data, data_length) != SUCCESS)
            ;
        while (data_ready_flag != 1)
            ;
        i2cRead_T(base, slaveAddr, regAddr, data, data_length);
        return 1;
    }
    
    __interrupt void i2cISR()
    {
        intSource = I2C_getInterruptSource(I2CB_BASE);
        switch(intSource)
        {
        case I2C_INTSRC_STOP_CONDITION:
        {
    
            if(data_ready_flag == 1)
            {
                data_ready_flag = 0;
            }
    
        }
        break;
        case I2C_INTSRC_REG_ACCESS_RDY:
        {
    
            if((I2C_getStatus(I2CB_BASE)&I2C_STS_NO_ACK)!=0)
            {
                I2C_sendStopCondition(I2CB_BASE);
                I2C_clearStatus(I2CB_BASE, I2C_STS_NO_ACK);
            }
            data_ready_flag = 1;
    
        }
        break;
        }
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    }
    
    int16_t i2cWrite(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t data)
    {
        if(I2C_getStopConditionStatus(base))
        {
            return ERROR_STOP_NOT_READY;
        }
        I2C_setSlaveAddress(base, slaveAddr);
        if(I2C_isBusBusy(I2CB_BASE))
            {
                return(ERROR_BUS_BUSY);
            }
        I2C_setDataCount(base,2);
        I2C_putData(base,regAddr);
        I2C_putData(base, data);
        I2C_setConfig(base,I2C_MASTER_SEND_MODE);
        I2C_sendStartCondition(base);
        I2C_sendStopCondition(base);
        return SUCCESS;
    }
    int16_t i2cWriteMulti(uint32_t base,uint16_t slaveAddr, uint16_t regAddr, uint16_t *data,uint16_t data_length)
    {
        uint16_t i;
        if(I2C_getStopConditionStatus(base))
        {
            return ERROR_STOP_NOT_READY;
        }
        I2C_setSlaveAddress(base, slaveAddr);
        if(I2C_isBusBusy(I2CB_BASE))
            {
                return(ERROR_BUS_BUSY);
            }
        I2C_setDataCount(base,data_length+1);
        I2C_putData(base,regAddr);
        for(i=0; i<data_length;i++)
        {
            I2C_putData(base, *(data+i));
        }
        I2C_setConfig(base,I2C_MASTER_SEND_MODE);
        I2C_sendStartCondition(base);
        I2C_sendStopCondition(base);
        return SUCCESS;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

  • Lee,

    Please consider adapting i2c_ex6_eeprom_interrupt.c example code available in latest C2000Ware. This examples uses I2C to read / write 'N' bytes using interrupt method.

    Regards,

    Manoj

  • Hi TI technical team!!

    There is a question related to I2C reading.

    Debugging was performed by slightly modifying the ex6 eeprom interrupt example.

    Still, one byte read/write operates normally.

    However, when reading the read 'N' byte, the same issue as the previous code appears.

    This time, the data of the fifth register(or first register) address is read five times and stored in the rx buffer.

    Please refer to the modified example code.

    Please review it in detail!

    Kind regard

    JM LEE

    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "i2cLib_FIFO_master_interrupt.h"
    
    #define BUFFER_SIZE 5
    //
    // Defines
    //
    #define EEPROM_SLAVE_ADDRESS        0x18
    
    //
    // Globals
    //
    
    struct I2CHandle EEPROM;
    struct I2CHandle *currentResponderPtr;                   // Used in interrupt
    uint16_t AvailableI2C_slaves[20];
    uint16_t TX_MsgBuffer[BUFFER_SIZE];
    uint16_t RX_MsgBuffer[BUFFER_SIZE];
    uint32_t ControlAddr;
    uint16_t status=0;
    
    //
    // Function Prototypes
    //
    
    interrupt void i2cFIFO_isr(void);
    interrupt void i2c_isr(void);
    void I2C_GPIO_init(void);
    void I2Cinit(void);
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pullups.
        //
        Device_initGPIO();
    
        //
        // Initialize I2C pins
        //
        I2C_GPIO_init();
    
        //
        // 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();
    
        I2Cinit();
        //
        // Interrupts that are used in this example are re-mapped to ISR functions
        // found within this file.
        //
        Interrupt_register(INT_I2CB_FIFO, &i2cFIFO_isr);
    
        Interrupt_enable(INT_I2CB_FIFO);
    
        Interrupt_register(INT_I2CB, &i2c_isr);
    
        Interrupt_enable(INT_I2CB);
    
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //I2Cs connected to I2CA will be found in AvailableI2C_slaves buffer
        //after you run I2CBusScan function.
        uint16_t *pAvailableI2C_slaves = AvailableI2C_slaves;
        status = I2CBusScan(I2CB_BASE, pAvailableI2C_slaves);
    
        //uint16_t i;
    
        currentResponderPtr = &EEPROM;
    
        EEPROM.currentHandlePtr     = &EEPROM;
        EEPROM.SlaveAddr            = EEPROM_SLAVE_ADDRESS;
        EEPROM.WriteCycleTime_in_us = 10000;    //6ms for EEPROM this code was tested
        EEPROM.base = I2CB_BASE;
        EEPROM.pControlAddr = &ControlAddr;
        EEPROM.NumOfAddrBytes = 1;
    
    
        TX_MsgBuffer[0] = 0x07;
        TX_MsgBuffer[1] = 0x23;
        TX_MsgBuffer[2] = 0;
        TX_MsgBuffer[3] = 0;
        TX_MsgBuffer[4] = 0x03;
    
        ControlAddr = 0x20;   
        EEPROM.NumOfDataBytes = BUFFER_SIZE;
        EEPROM.pTX_MsgBuffer = TX_MsgBuffer;
        status = I2C_MasterTransmitter(&EEPROM);
        DEVICE_DELAY_US(EEPROM.WriteCycleTime_in_us);
    
    
        while (1)
        {        
            ControlAddr = 0x20;
            EEPROM.pControlAddr = &ControlAddr;
            EEPROM.pRX_MsgBuffer = RX_MsgBuffer;
            EEPROM.NumOfDataBytes = BUFFER_SIZE;
    
            status = I2C_MasterReceiver(&EEPROM);
            DEVICE_DELAY_US(EEPROM.WriteCycleTime_in_us);
    
        }
    
    
    }
    
    interrupt void i2c_isr(void)
    {
        uint16_t MasterSlave = HWREGH(currentResponderPtr->base + I2C_O_MDR);
    
        handleI2C_ErrorCondition(currentResponderPtr);
    
        if(MasterSlave & I2C_MDR_MST)
        {
            I2C_enableInterrupt(currentResponderPtr->base, I2C_INT_RXFF);
            I2C_clearInterruptStatus(currentResponderPtr->base,(I2C_INT_RXFF));
        }
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    }
    
    interrupt void i2cFIFO_isr(void)
    {
        Write_Read_TX_RX_FIFO(currentResponderPtr);
    
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    }
    
    
    void I2C_GPIO_init(void)
    {
        // I2CB pins (SDAA / SCLA)
        GPIO_setDirectionMode(35, GPIO_DIR_MODE_IN);
        GPIO_setPadConfig(35, GPIO_PIN_TYPE_PULLUP);    
        GPIO_setMasterCore(35, GPIO_CORE_CPU1);
        GPIO_setQualificationMode(35, GPIO_QUAL_ASYNC);
    
        GPIO_setDirectionMode(40, GPIO_DIR_MODE_IN);
        GPIO_setPadConfig(40, GPIO_PIN_TYPE_PULLUP);    
        GPIO_setMasterCore(40, GPIO_CORE_CPU1);
        GPIO_setQualificationMode(40, GPIO_QUAL_ASYNC);
    
        GPIO_setPinConfig(GPIO_35_I2CB_SCL);
        GPIO_setPinConfig(GPIO_40_I2CB_SDA);
    
    }
    
    void I2Cinit(void)
    {
        I2C_disableModule(I2CB_BASE);
    
        I2C_initMaster(I2CB_BASE, DEVICE_SYSCLK_FREQ, 100000, I2C_DUTYCYCLE_50); // I2C configuration. Use a 100kHz I2CCLK with a 50% duty cycle.
        I2C_setConfig(I2CB_BASE, I2C_MASTER_SEND_MODE);
        I2C_setSlaveAddress(I2CB_BASE, 80);
        //I2C_setOwnSlaveAddress(I2CB_BASE, 96);
        I2C_disableLoopback(I2CB_BASE);
        I2C_setBitCount(I2CB_BASE, I2C_BITCOUNT_8);
        I2C_setDataCount(I2CB_BASE, 2);
        I2C_setAddressMode(I2CB_BASE, I2C_ADDR_MODE_7BITS);
        I2C_enableFIFO(I2CB_BASE);
        I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_ARB_LOST | I2C_INT_NO_ACK);
        I2C_setFIFOInterruptLevel(I2CB_BASE, I2C_FIFO_TXEMPTY, I2C_FIFO_RX2);
        I2C_enableInterrupt(I2CB_BASE, I2C_INT_ADDR_SLAVE | I2C_INT_ARB_LOST | I2C_INT_NO_ACK | I2C_INT_STOP_CONDITION);
        I2C_setEmulationMode(I2CB_BASE, I2C_EMULATION_FREE_RUN);
    
        I2C_enableModule(I2CB_BASE);
    }
    //
    // End of File
    //
    
    

  • Jim,

    In IIS328DQ datasheet, it clearly states that you need to enable autoincrement by setting the MSB bit. Your ControlAddr should 0xA0 instead of 0x20. Hopefully this should fix this issue.

    Snippet from IIS328DQ datasheet.

    Regard,

    Manoj

  • HI !! Manoj

    Thank you so much!

    ControlAddr = 0xA0;

    After modifying the address, 'N' byte W/R operated normally.

    Next time, I'll take a closer look at the data sheet.

    Anyway, thank you!

    Kind regard

    JM LEE