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.

TMS320F28035: I2C Can't write more than 4 bytes of data

Part Number: TMS320F28035


Hello c200 experts.

I am trying to send more than 4 bytes data via i2c but noting happens.

void I2CMaster_Transmit(Uint8 I2CSlave_Address, Uint16 I2CMaster_ByteCountTx, unsigned char *I2CMaster_TxArray, Uint16 I2CMaster_ByteCountRx, unsigned char *I2CMaster_RxArray)
{
    I2caRegs.I2CSAR = I2CSlave_Address;
    /***************Write******************/
    if(I2CMaster_ByteCountTx != 0)
    {
        I2C_s.I2CMaster_TransmitField = I2CMaster_TxArray;

        I2caRegs.I2CCNT = I2CMaster_ByteCountTx;

        while(I2CMaster_ByteCountTx > 0)    //check that there are still bytes to send
        {
            I2caRegs.I2CDXR = *I2C_s.I2CMaster_TransmitField;
            I2C_s.I2CMaster_TransmitField++;
            I2CMaster_ByteCountTx--;
        }

        I2caRegs.I2CMDR.all = 0x2E20;   // Set up the control register:
                                        // bit 14 FREE = 1
                                        // bit 13 STT = 1  (Start condition)

                                        // bit 11 STP = 1  (Stop condition after
                                        //                transfer of bytes.)
                                        // bit 10 MST = 1  Master
                                        // bit  9 TRX = 1  Transmit

                                        // bit  5 IRS = 1 to Reset I2C bus.

        StartCpuTimer0();               // Start the timer
        I2CMaster_Wait();               // Wait for I2C bus to clear
        StopCpuTimer0();                //No timeout, so stop the timer
        ReloadCpuTimer0();              //Reload the period value (35 ms timeout)
    }
    /****************Read*******************/
    if(I2CMaster_ByteCountRx != 0)
    {
        I2C_s.I2CMaster_ReceiveField = I2CMaster_RxArray;

        I2caRegs.I2CCNT = I2CMaster_ByteCountRx;
        I2caRegs.I2CMDR.all = 0x2C20;           // Send "repeated" Start with Read (TRX off)
                                                // and Stop.

        StartCpuTimer0();                       // Start the timer

        I2CMaster_Wait();                       // Wait for I2C bus to clear
    }
}

This is my write and read function. any help?

Also my master sides init function

void I2CMaster_Init(Uint8 I2CMaster_MasterAddress, Uint16 I2CMaster_Prescale)
{
    Uint16 i;

    I2C_s.TransmitBufferFirstIndex = I2C_s.I2CMaster_TransmitField;
    I2C_s.I2CMaster_ReceiveField = I2C_s.Master_ReceiveBuffer;

    for(i = 0; i<21; i++)
    {
        I2C_s.Master_ReceiveBuffer[i] = 0;
        I2C_s.Master_TransmitBuffer[i] = 0;
    }
    //Setup I2C interrupts and Cpu Timer 0 interrupt
    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.I2CINT1A = &i2c_master_int1a_isr;
    PieVectTable.TINT0 = &cpu_timer0_isr;
    EDIS;   // This is needed to disable write to EALLOW protected registers
    // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
    PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
    // Enable TINT0 in the PIE: Group 1 interrupt 7
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    // Enable CPU INT8 which is connected to PIE group 8
    IER |= M_INT8;
    // Enable CPU int1 which is connected to CPU-Timer 0
    IER |= M_INT1;

    InitI2CGpio();
    InitCpuTimers();

    ConfigCpuTimer(&CpuTimer0, 60, 35000);          //CPU Timer 0 interrupt after 35 ms (at 60MHz CPU freq.)

    // Initialize I2C
//    I2caRegs.I2CSAR = I2CMaster_SlaveAddress;       // Slave Address.
    I2caRegs.I2COAR = I2CMaster_MasterAddress;      // address as Master.
    I2caRegs.I2CPSC.all = I2CMaster_Prescale;       // Prescaler - need 7-12 Mhz on module clk
    I2caRegs.I2CCLKL = 10;                          // NOTE: must be non zero
    I2caRegs.I2CCLKH = 5;                           // NOTE: must be non zero
    I2caRegs.I2CIER.all = 0x3C;                     // Enable interrupts

    I2caRegs.I2CMDR.bit.IRS = 1;                    // Take I2C out of reset
                                                    // Stop I2C when suspended

    I2caRegs.I2CFFTX.all = 0x6000;                  // Enable FIFO mode and TXFIFO



    return;
}

My slave device is also a c2000 board.

  • Hi Frozen,

    The F2803x device's I2C FIFO buffer is only 4 bytes deep. You will need to re-fill it (or use non-FIFO mode) when sending more than 4 bytes.

    You should revisit the below piece of code:

    while(I2CMaster_ByteCountTx > 0)    //check that there are still bytes to send
    {
    	I2caRegs.I2CDXR = *I2C_s.I2CMaster_TransmitField;
    	I2C_s.I2CMaster_TransmitField++;
    	I2CMaster_ByteCountTx--;
    }
    
    I2caRegs.I2CMDR.all = 0x2E20;   // Set up the control register:
    								// bit 14 FREE = 1
    								// bit 13 STT = 1  (Start condition)
    
    								// bit 11 STP = 1  (Stop condition after
    								//                transfer of bytes.)
    								// bit 10 MST = 1  Master
    								// bit  9 TRX = 1  Transmit
    
    								// bit  5 IRS = 1 to Reset I2C bus.
    

    Best,

    Kevin

  • I commented out the FIFO initialization but still no progress. Here is my slave side of code.

    Slave init

    void I2CSlave_Init(Uint16 I2CSlave_OwnAddress)
    {
        //Setup Cpu Timer 0 interrupt
        EALLOW; // This is needed to write to EALLOW protected registers
        PieVectTable.TINT0 = &cpu_timer0_isr;
        PieVectTable.I2CINT1A = &i2c_slave_isr;
        EDIS;   // This is needed to disable write to EALLOW protected registers
        // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
        PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
        // Enable TINT0 in the PIE: Group 1 interrupt 7
        PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
        // Enable CPU INT8 which is connected to PIE group 8
        IER |= M_INT8;
        // Enable CPU int1 which is connected to CPU-Timer 0
        IER |= M_INT1;
    
        InitI2CGpio();
        InitCpuTimers();
    
        ConfigCpuTimer(&CpuTimer0, 60, 35000);  //CPU Timer 0 interrupt after 35 ms (at 60MHz CPU freq.)
    
        // Initialize I2C
        I2caRegs.I2COAR = I2CSlave_OwnAddress;      // Own address
        I2caRegs.I2CPSC.all = 9;        // Prescaler - need 7-12 Mhz on module clk
        I2caRegs.I2CCLKL = 10;          // NOTE: must be non zero
        I2caRegs.I2CCLKH = 5;           // NOTE: must be non zero
    
        I2caRegs.I2CIER.all = 0x3C;
    //    I2caRegs.I2CIER.all = 0x00;     // Clear interrupts - polling based method
    
        I2caRegs.I2CMDR.all = 0x0020;   // Take I2C out of reset
                                        // Stop I2C when suspended
        Uint8 i = 0;
    
        return;
    }

    interrupt void i2c_slave_isr(void)
    {
        Uint16 I2CSlave_IntSource;
        Uint8 command;
    
        command = PMBus_s.RXBuf_s.CBuffer_arr[0];
        I2CSlave_IntSource = I2caRegs.I2CISRC.bit.INTCODE & 0x7;
    
        switch(I2CSlave_IntSource)
        {
            case I2C_SCD_ISRC:
                Status_e = I2CIDLE;
                GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
                PMBus_s.TXBuf_s.CBufferField_ptr = PMBus_s.TXBuf_s.CBufferFirstIndex_ptr;
                PMBus_s.RXBuf_s.CBufferField_ptr = PMBus_s.RXBuf_s.CBufferFirstIndex_ptr;
                break;
            case I2C_RX_ISRC:   // =4
                StopCpuTimer0();        //No timeout, so stop the timer
                ReloadCpuTimer0();      //Reload the period value (35 ms timeout)
                *PMBus_s.RXBuf_s.CBufferField_ptr = I2caRegs.I2CDRR;
                PMBus_s.RXBuf_s.CBufferField_ptr++;
                Status_e = I2CRX;
                PMBus_s.TXBuf_s.ByteCount_ui8 = PMBusTXData_Filler(command, &PMBus_s.TXBuf_s);
                break;
            case I2C_TX_ISRC:   // =5
                StopCpuTimer0();        //No timeout, so stop the timer
                ReloadCpuTimer0();      //Reload the period value (35 ms timeout)
                Status_e = I2CTX;
                while(PMBus_s.TXBuf_s.ByteCount_ui8 > 0)
                {
                    I2caRegs.I2CDXR = *PMBus_s.TXBuf_s.CBufferField_ptr;
                    PMBus_s.TXBuf_s.CBufferField_ptr++;
                    PMBus_s.TXBuf_s.ByteCount_ui8--;
                }
                break;
        }
    
       // Enable future I2C (PIE Group 8) interrupts
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
    }

  • Frozen,

    If you're not using FIFO mode you'll have to handle the filling of the I2CDXR register differently then. The way you have it now you're likely overwriting the byte before it gets transmitted out.

    Frozen said:
                while(PMBus_s.TXBuf_s.ByteCount_ui8 > 0)
                {
                    I2caRegs.I2CDXR = *PMBus_s.TXBuf_s.CBufferField_ptr;
                    PMBus_s.TXBuf_s.CBufferField_ptr++;
                    PMBus_s.TXBuf_s.ByteCount_ui8--;
                }

    You should include some form of checking for end of TX. See the example function code I provided at the end of this E2E post:

    https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/773846

    Best,

    Kevin