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.

Problem with I2C interface

Hi all,

I am facing a big problem in communicate with bq27441(battery management) by I2C protocol (I use F28335 I2C module) . Write or read  registers of these chip is really strange. Sometime got right results but sometime i got wrong result again and again. Such as: when i try reading a register many time (for example designed capacity) i get many different values (of course true value is one of them). Please help me if you know why.

Below is my program config I2C:

// Initial for I2C

// Initial for I2C module
void init_I2C(void)
{

    EALLOW;
    /* Enable internal pull-up for the selected pins */
    // Pull-ups can be enabled or disabled disabled by the user.
    // Comment out other unwanted lines.

    GpioCtrlRegs.GPBPUD.bit.GPIO32 = 1;     // Disable pull-up for GPIO32 (SDAA)
    GpioCtrlRegs.GPBPUD.bit.GPIO33 = 1;     // Disnable 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 for SDAA operation
    GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1;    // Configure GPIO33 for SCLA operation

    EDIS;


    I2caRegs.I2CPSC.all = 14;   // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz)


    I2caRegs.I2CCLKL = 12;          // NOTE: must be non zero    1.7us
    I2caRegs.I2CCLKH = 5;           // NOTE: must be non zero     1us --> I2C freq: 370KHz
    I2caRegs.I2CIER.all = 0x24;     // Enable SCD & ARDY interrupts


    I2caRegs.I2CMDR.all = 0x0020;   // Take I2C out of reset
                                    // Stop I2C when suspended

    I2caRegs.I2CFFTX.all = 0x6000;  // Enable FIFO mode and TXFIFO
    I2caRegs.I2CFFRX.all = 0x2040;  // Enable RXFIFO, clear RXFFINT



    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.I2CINT1A    = &i2c_rxa_isr;
    EDIS;   // This is needed to disable write to EALLOW protected registers


    //  PieCtrlRegs.PIECTRL.bit.ENPIE = 1;      // Use in init_Sci_B

    // Enable I2C interrupt 1  in the PIE: Group 8
    PieCtrlRegs.PIEIER8.bit.INTx1 = 1;

    // Enable CPU INT8 which is connected to PIE group 8
    IER |= M_INT8;

}

// Write function 

// write i2c function
void I2C_write_data(unsigned int slave_addr, unsigned int length)
{

    unsigned int jdex;


    while(I2caRegs.I2CMDR.bit.STP == 1);

    // Check if bus busy
    while(I2caRegs.I2CSTR.bit.BB == 1);




    // Setup slave address
    I2caRegs.I2CSAR = slave_addr;

    // Setup number of bytes to send
    // MsgBuffer + Address
    I2caRegs.I2CCNT = length;

    // Setup data to send
    for (jdex=0; jdex<length; jdex++)
    {
      I2caRegs.I2CDXR = *(i2c_write_buff+jdex);   // i2c_write_buff[] data will be write
    }

    // Send start as master transmitter
    I2caRegs.I2CMDR.all = 0x6E20;
}

// Function read from I2C

// I2C read function
void I2C_read_data(unsigned int slave_addr, unsigned int cmd_length)
{

    unsigned int jdex;


    // 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.
    while(I2caRegs.I2CMDR.bit.STP == 1);

    // Check if bus busy
    while(I2caRegs.I2CSTR.bit.BB == 1);



    I2caRegs.I2CSAR = slave_addr;

    I2caRegs.I2CCNT = cmd_length;

    // Setup data to send
    for (jdex=0; jdex<cmd_length; jdex++)
    {
        I2caRegs.I2CDXR = i2c_cmd[jdex];    // start address will be read
    }

    I2caRegs.I2CMDR.all = 0x2620;           // Send cmd with no stop

    user_delay(10000);       --> delay 940us

    I2caRegs.I2CCNT = i2c_receive_length;           // Setup how many bytes to expect
    I2caRegs.I2CMDR.all = 0x2C20;                   // Send restart as master receiver
}


// Program read data from bq27441:

// Read from address 0x43 and 0x44 (slave return 2 byte 0x43 MSB, 0x44 LSB)

        i2c_write_buff[0] = 0x43;    // buffer i2c master write to slave
        I2C_write_data(0x55, 1);     // write
        user_delay(1000);   --> delay 94us > 66us

        i2c_cmd[0] = 0x43;         // adress master read from slave
        i2c_receive_length = 1;    // global variable: length of data I2c master will receive
        I2C_read_data(0x55, 1);   
        user_delay(1000);

        temp[0] = i2c_read_buff[0];    // data received from I2c will store in i2c_read_buff

        i2c_write_buff[0] = 0x43;    // 
        I2C_write_data(0x55, 1);
        user_delay(1000);   --> delay 94us > 66us

        i2c_cmd[0] = 0x44;
        i2c_receive_length = 1;    // global variable: length of data I2c master will receive
        I2C_read_data(0x55, 1);
        user_delay(1000);

        temp[1] = i2c_read_buff[0];

        // designed capacity = temp[1]+ temp[0]*256

This is the best code that i can communicate with bqxx chip (got more right result). 

Thanks for reading.

Best Regards.

Phien Nguyen