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.

TMS570LS0432: I2C communication with BQ34Z100EVM not working

Part Number: TMS570LS0432
Other Parts Discussed in Thread: BQ34Z100EVM

Hi,

I am using TMS570 launchpad (TMS570LS0432) to interface with BQ34Z100EVM (battery fuel gauge).

BQ34Z100EVM supports I2C protocol but TMS570LS0432 does not support I2C.

So, after searching on E2E community, I got to know that we can still communicate TMS570LS0432 and BQ34Z100EVM with N2HET.

I tried to run the program available in that example. But I could not figure out following points:

1. Which N2HET pins are used as SDA() and SCL() for I2C communication?

2. I am attaching the code snippet of main.c 

/** @file sys_main.c
*   @brief Application main file
*   @date 9.Sep.2014
*   @version 04.01.00
*
*   This file contains an empty main function,
*   which can be used for the application.
*/

/* (c) Texas Instruments 2009-2014, All rights reserved. */

/* USER CODE BEGIN (0) */
/* USER CODE END */

/* Include Files */

#include "sys_common.h"

/* USER CODE BEGIN (1) */
#include "het.h"
#include "HET_IO_TEST.h"
#include "HET_EMU.h"

unsigned char *I2C1_txptr = NULL, *I2C1_rxptr = NULL;
unsigned char I2C1_TxData[5] = {0, 0, 0, 0, 0};
unsigned char I2C1_RxData[20];
unsigned int Data_Send_HET = 0, Data_Rece_HET = 0;
unsigned int Data_Send_I2C = 0, Data_Rece_I2C = 0;
// unsigned int Stop_Rece_I2C = 0;
unsigned int Start_Repeat=0;
char IntEna =1;
char RW = 0; //write
char I2C_ADDR; // todo: jc 20141024 this is a hack to make the TI emukator code work, candidate for refactoring
char NumOfBytes = 1;


/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
/* USER CODE END */

void main(void)
{
/* USER CODE BEGIN (3) */

    // set the i2c address
    I2C_ADDR = 0xAB;


    int i;

    NumOfBytes = 1;
    char StopBit = 1;
    volatile unsigned int wait_counter;



    I2C1_txptr = I2C1_TxData;
    I2C1_rxptr = I2C1_RxData;

    hetInit();
    hetREG1->INTENAS = 0xFFFFFFFFU;    // todo jc 20141024 check if this is needed
    hetREG1->GCR = 0x01010001;    // todo jc 20141024 check if this is needed

     _enable_IRQ();    // todo jc 20141024 check if this is needed

     IntEna =1;
     RW = 0; //write
     NumOfBytes = 1;
     I2C1_TxData[0] = 0x02; // % charge left


    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);
    for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.


    RW = 1; //Read
    IntEna = 0;//no transmit interrupt
    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);

    while(1);

    /* USER CODE END */
}

/* USER CODE BEGIN (4) */
/* USER CODE END */

Please help me out to run the communication.

Thanks

Ritul Shah

  • Hello Ritul,

    The sample code uses HET0 for I2C SDA, and HET2 for I2C SCL.

    0363.N2HET_EMU_I2C_AppNote.pdf

  • Thanks QJ Wang for your reply.

    I have made following connections:

    TMS570 : BQ34Z100EVM

    Gnd : Gnd

    NHET0 : SDA

    NHET2 : SCL

    I have run HET_IO_Test file on CCS7.0 to perform I2C communication.

    I am getting following result at I2C1_RXDATA for the below code:


    /* (c) Texas Instruments 2009-2014, All rights reserved. */

    /* USER CODE BEGIN (0) */
    /* USER CODE END */

    /* Include Files */

    #include "sys_common.h"

    /* USER CODE BEGIN (1) */
    #include "het.h"
    #include "HET_IO_TEST.h"
    #include "HET_EMU.h"

    unsigned char *I2C1_txptr = NULL, *I2C1_rxptr = NULL;
    unsigned char I2C1_TxData[5] = {0, 0, 0, 0, 0};
    unsigned char I2C1_RxData[20];
    unsigned int Data_Send_HET = 0, Data_Rece_HET = 0;
    unsigned int Data_Send_I2C = 0, Data_Rece_I2C = 0;
    // unsigned int Stop_Rece_I2C = 0;
    unsigned int Start_Repeat=0;
    char IntEna =1;
    char RW = 0; //write
    char I2C_ADDR; // todo: jc 20141024 this is a hack to make the TI emukator code work, candidate for refactoring
    char NumOfBytes = 1;


    /* USER CODE END */

    /** @fn void main(void)
    *   @brief Application main function
    *   @note This function is empty by default.
    *
    *   This function is called after startup.
    *   The user can use this function to implement the application.
    */

    /* USER CODE BEGIN (2) */
    /* USER CODE END */

    void main(void)
    {
    /* USER CODE BEGIN (3) */

        // set the i2c address
        I2C_ADDR = 0x55;


    //    int i;

        NumOfBytes = 1;
        char StopBit = 1;
        volatile unsigned int wait_counter;



        I2C1_txptr = I2C1_TxData;
        I2C1_rxptr = I2C1_RxData;

        hetInit();
        hetREG1->INTENAS = 0xFFFFFFFFU;    // todo jc 20141024 check if this is needed
        hetREG1->GCR = 0x01010001;    // todo jc 20141024 check if this is needed

         _enable_IRQ();    // todo jc 20141024 check if this is needed

         IntEna =1;
         RW = 0; //write
         NumOfBytes = 1;
         I2C1_TxData[0] = 0x20; // % charge left


        HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);
        for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.


        RW = 1; //Read
        IntEna = 0;//no transmit interrupt
        HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);

        while(1);

        /* USER CODE END */
    }

    /* USER CODE BEGIN (4) */
    /* USER CODE END */

    Can you help me to get a basic program for reading SOC% value from BQ34Z100EVM ?

  • Hello,

    Please use the I2C communication protocol defined one page 41 of bq34z100-q1.pdf.

       RW = 1; //Read

       IntEna = 0;//no transmit interrupt

       HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);

    The I2C_ADDR should be the address of the data. The I2C transfer sequence for reading the SOC is:

    Start-0xAA-ACK-0x02-ACK-Start-0xAB-ACK-(LSB of SOC)-ACK-(MSB of SOC)-ACK-STOP

    0xAA and 0xAB are the BQ I2C address (7-bit address) + read/write bit. 0x02 is register address for SOC.

  • Hi QJ Wang,

    Thanks for your reply.

    I tried to follow your response to write the code.

    RW = 1; //Read

    IntEna = 0;//no transmit interrupt

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);

    I2C communication Read sequence is:  Start-0xAA-       ACK       -0x02-     ACK        -Start-0xAB-      ACK       -(LSB of SOC)-ACK-(MSB of SOC)-ACK-       STOP

    As per the sequence what i understand is: Device Address = 0xAA (Write operation), 

                                                                                  Register address = 0x02 (SOC % register command code address)

                                                                                  Device Address = 0xAB (Read operation)

    Now when, " HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit); " command is written,

    Questions:

    1.  How would I know, when to use Device Address and Register Address in the "I2C2_ADDR" ?

    2.  How would I know whether Slave has given an acknowledgement or not ?

    3. Which register do i need to see whether we have received any data ?

    4. I am referring the N2HET emulated I2C code :

    Please help me with the Code (I am new to I2C programming).

  • Hello,

    In your application, MCU is a master, and the BQ34 is the slave. The general procedure for a master to access a slave is the following:

    1. The master wants to send data to a slave:

    • Master sends a START condition and addresses the slave
    • Master sends data to slave
    • Master terminates the transfer with a STOP condition

    2. If a master wants to receive/read data from a slave (for BQ34):

    • Master sends a START condition and addresses the slave
    • Master sends the requested register to read to slave
    • Master sends a START (repeated START) condition and addresses the slave
    • Master sends the requested register to read to slave
    • Master receives data from the slave
    • Master terminates the transfer with a STOP condition

    3. ACK:

    Each byte of data (including the address byte) is followed by one ACK bit from the receiver. The ACK bit allows the receiver to communicate to the transmitter that the byte was successfully received and another byte may be sent. Before the receiver can send an ACK, the transmitter must release the SDA line. To send an ACK bit, the receiver shall pull down the SDA line during the low phase of the clock period, so that the SDA line is stable low during the high phase of the clock period.

    4.  Use HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit) to send command (0x2) to BQ34

    5.  Once the address bits move to the shift register, a transmit interrupt will be generated.  Inside the interrupt service routine, HetI2CPutData() write the data to be transmitted into the transmit buffer.

    6. Once the N2HET emulated I2C receives the data, a receive interrupt will be generated.  Inside the interrupt, the received data will be copied to the main memory.

    If you want to read the data manually (pooling mode):

      *I2C_rxptr++ = (hetRAM1->Instruction[0x2C].Data>>8) & 0xFF

  • Hi  QJ Wang,

    Thanks for your reply. As per the procedure to read,

    If a master wants to receive/read data from a slave (for BQ34):

    • Master sends a START condition and addresses the slave
    • Master sends the requested register to read to slave
    • Master sends a START (repeated START) condition and addresses the slave
    • Master sends the requested register to read to slave
    • Master receives data from the slave
    • Master terminates the transfer with a STOP condition

    Questions:

    1. What is the Code to send START condition?

    2. What is the Code to send Address of Slave ?

    3. What is the Code to send requested register to read to slave ?

    4. What is the Code to send repeated START condition?

    Can you please give me a complete code to Read (0X02) register address (SOC %) of BQ34Z100EVM having device slave Address (0X55) on TMS570LS0432 launchpad?

    Please help me out.

    Eagerly waiting for your reply.

    Thanks

    Ritul Shah

  • Hello Ritul,

    For write data:

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);--> Send START, send BQ34 I2C address (0x55), RW=0 for write operation, and send data (data can be register's address, for example, 0x02), intEna=1, StopBit=0 (next START is repeated start) 

    For read data:

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);--> Send repeated START, send BQ34 I2C address (0x55), RW=1 for read operation, and read data (data from address 0x2 and 0x03), intEna=1, StopBit=1

    Please refer to the example code.

    0434.N2HET_EMU_I2C_AppNote.pdf

    6237.sys_main.c

  • Hi QJ Wang,

    I have followed your method for the DATA using I2C in the below code:

       Master sends a START condition and addresses the slave

       Master sends the requested register to read to slave

       Master sends a START (repeated START) condition and addresses the slave

       Master sends the requested register to read to slave

       Master receives data from the slave

       Master terminates the transfer with a STOP condition

    void main(void)

    {

    /* USER CODE BEGIN (3) */

       // set the i2c address

       I2C_ADDR = 0x55;

       volatile unsigned int wait_counter;

       I2C1_txptr = I2C1_TxData;

       I2C1_rxptr = I2C1_RxData;

       hetInit();

       hetREG1->INTENAS = 0xFFFFFFFFU; // todo jc 20141024 check if this is needed

       hetREG1->GCR = 0x01010001;  // todo jc 20141024 check if this is needed

        _enable_IRQ(); // todo jc 20141024 check if this is needed

        //I2C1_TxData[0] = 0x2; //

       // Master sends a START condition and addresses slave

       IntEna =1;

       RW = 0; //write

       NumOfBytes = 0x0;

       StopBit = 0;

       HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);

       for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.

       // Master sends the requested register to read to slave

       IntEna =1;

       RW = 0; //write

       NumOfBytes = 0x0;

       StopBit = 0;

       HetI2CPutAddr(0x2, RW, NumOfBytes, IntEna, StopBit);

       for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.

       // Master sends a Repeated START condition and addresses slave

           IntEna =1;

           RW = 0; //write

           NumOfBytes = 0x0;

           StopBit = 0;

           Start_Repeat = 1;

           HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);

           for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.

           // Master sends the requested register to read to slave

           Start_Repeat = 0;

           IntEna =1;

           RW = 0; //write

           NumOfBytes = 0x0;

           StopBit = 0;

           HetI2CPutAddr(0x1, RW, NumOfBytes, IntEna, StopBit);

           for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.

           // Master receives data from slave

                   IntEna =1;

                   RW = 1; // read

                   NumOfBytes = 0x1;

                   StopBit = 0;

                   HetI2CPutAddr(0x1, RW, NumOfBytes, IntEna, StopBit);

                   for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.

                   // Master receives data from slave

                                   IntEna =1;

                                   RW = 0; // read

                                   NumOfBytes = 0x0;

                                   StopBit = 1;

                                   HetI2CPutAddr(0x1, RW, NumOfBytes, IntEna, StopBit);

                                   for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.

       while(1);

    Questions:

    1. We have used HetI2CPutAddr function 5 times once for each of the steps mentioned by you. Is this method correct?

    1. How to check the acknowledgement from SLAVE?

    2. Using the above code, HetI2CPutAddr(0x1, RW, NumOfBytes, IntEna, StopBit);

         program goes into the HETNOTIFICATION, it goes always in the Transmit interrupt, But never goes into Receive Interrupt.

    What can be the solution for it?

  • Hi QJ Wang,

    I have used,

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);  //  Master sends a START condition and addresses the slave

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);  //  Master sends the requested register to read to slave

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);  //  Master sends a START (repeated START) condition and addresses the slave

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);  //     Master sends the requested register to read to slave

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);  //  Master sends the requested register to read to slave

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);  //  Master receives data from the slave

    HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);  //   Master terminates the transfer with a STOP condition

    For reading the SOC of (BQ34). Is this code written right ?

    Also,  how to use HetI2CPutData() ? Which data should be put in this function?

  • Hello,

    1. HetI2CPutAddr(0x55, 0, 1, 1, 0);

    This one function sends a START condition, and slave address, and sends the requested register 0x02. The data is I2C_TxData[0].

    2. HetI2CPutAddr(0x55, 1, 2, 1, 1);

    This function sends a START condition, and slave address, and read 2 bytes of data from the requested register 0x02. The data is I2C_RxData[1:0].

    3. HetI2CPutData()

    This function is called in interrupt routine:

    /** @fn void het1HighLevelInterrupt(void)

    * @brief Level 0 Interrupt for HET1

    */

    #pragma CODE_STATE(het1HighLevelInterrupt, 32)

    #pragma INTERRUPT(het1HighLevelInterrupt, IRQ)

    void het1HighLevelInterrupt(void)

    {

    uint32_t vect = hetREG1->OFF1;

    switch (vect)

    {

    case 11: /*---------------------------> Transmit interrupt */

    if(Data_Send_HET<3)

    {

    HetI2CPutData(*I2C1_txptr++, IntEna);

    Data_Send_HET++;

    }

    if(Start_Repeat==1)

    {

    if(Data_Send_HET<5)

    {

    HetI2CPutData(*I2C1_txptr++, IntEna);

    Data_Send_HET++;

    }

    else if(Data_Send_HET==5)

    {

    RW = 1; //Read

    IntEna = 0;//no transmit interrupt

    HetI2CPutAddr(I2C2_ADDR, RW, 2, IntEna, 1);//now, start to receive two data bytes and generate stop bit

    }

    }

    break;

    case 15: /*---------------------------> Receive interrupt */

    *I2C1_rxptr++ = (hetRAM1->Instruction[0x2C].Data>>8) & 0xFF; // read the data

    Data_Rece_HET++;

    break;

    case 18: /*---------------------------> No ACK interrupt */

        case 29: /* timeout2*/

    case 8: /* timeout6*/

    case 2: /* timeout9*/

        default:

    /* timeout + phantom interrupt, clear flags and return */

    while(1);

    break;

    }

    }

     

  • Hello QJ Wang,

    I have tested the code as per your above post. This way it is not working. So, I have attached you the complete project. Kindly look into this problem and help me with a working solution for SOC reading on TMS570LS0432. Waiting for your reply.

    Also I am pasting the sys_main.c file here.


    /* Include Files */

    #include "sys_common.h"

    /* USER CODE BEGIN (1) */
    #include "het.h"
    #include "HET_IO_TEST.h"
    #include "HET_EMU.h"

    unsigned char *I2C1_txptr = NULL, *I2C1_rxptr = NULL;
    unsigned char I2C1_TxData[5] = {0, 0, 0, 0, 0};
    unsigned char I2C1_RxData[5];
    unsigned int Data_Send_HET = 0, Data_Rece_HET = 0;
    unsigned int Data_Send_I2C = 0, Data_Rece_I2C = 0;
    // unsigned int Stop_Rece_I2C = 0;
    unsigned int Start_Repeat=0;
    char IntEna =1;
    char RW = 0; //write
    char I2C_ADDR; // todo: jc 20141024 this is a hack to make the TI emukator code work, candidate for refactoring
    char NumOfBytes = 1;
    char StopBit = 1;


    /* USER CODE END */

    /** @fn void main(void)
    *   @brief Application main function
    *   @note This function is empty by default.
    *
    *   This function is called after startup.
    *   The user can use this function to implement the application.
    */

    /* USER CODE BEGIN (2) */
    /* USER CODE END */

    void main(void)
    {
    /* USER CODE BEGIN (3) */

        // set the i2c address
        I2C_ADDR = 0x55;
        
        volatile unsigned int wait_counter;

        I2C1_txptr = I2C1_TxData;
        I2C1_rxptr = I2C1_RxData;

        hetInit();
        hetREG1->INTENAS = 0xFFFFFFFFU; // todo jc 20141024 check if this is needed
        hetREG1->GCR = 0x01010001;  // todo jc 20141024 check if this is needed

         _enable_IRQ(); // todo jc 20141024 check if this is needed

         // Start, slave address, register address
         // Master sends a START condition and addresses the slave
         // Master sends the requested register to read to slave
         IntEna = 1;
         RW = 0; //write
         NumOfBytes = 1;
         StopBit = 0;
         I2C1_TxData[0] = 0x02; // % charge left

         HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);
         for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.

         // Re-Start, slave address, register address, read, stop
         // Master sends a START (repeated START) condition and addresses the slave
         // Master sends the requested register to read to slave
         // Master receives data from the slave
         // Master terminates the transfer with a STOP condition
         Start_Repeat = 1;
         RW = 1; //Read
         IntEna = 1;//no transmit interrupt
         NumOfBytes = 2;
         StopBit = 1;
         
         HetI2CPutAddr(I2C_ADDR, RW, NumOfBytes, IntEna, StopBit);
         for(wait_counter=0;wait_counter<0x18;wait_counter++); //wait some time.
         

         while(1);

        /* USER CODE END */
    }

    /* USER CODE BEGIN (4) */
    /* USER CODE END */

    8424.I2C using N2HET on TMS570LS0432 with BQ34Z100.zip

  • Hi QJ Wang,

    We have taken readings of the I2C communication using logic analyzer. We are able to get the Reading values as expected. (Kindly refer to the images attached)

    But we are unable to view the same readings in the RX_Data register. I am attaching the complete project.

    We are unable trace what is happening in this interrupt function.

    case 15: /*--------------------------->      Receive interrupt */
            *I2C1_rxptr++ = (hetRAM1->Instruction[0x2C].Data>>8) & 0xFF;  // read the data
            Data_Rece_HET++;

    Please help me out to solve our problem.

    1524.I2C using N2HET on TMS570LS0432 with BQ34Z100_28-07-2017.zip

  • Hello Ritul,

    Good job. This means BG34 gets command from MCU and replies the MCU with the register''s data.

    I will take a look at your project, and come back to you soon.
  • Hello Rital,

    Can you post the whole waveform showing SDA and SCL for TX and RX (in one picture)? BTW, the number of bytes to read is 2 bytes rather than 10 bytes. If data is 0x02 on your 3rd waveform, the BQ34 doesn't ACK your TX (it is NACK, high).
  • Hello QJ Wang,

    Thanks for your reply.

    Kindly find the attached image of waveform showing SDA and SCL for TX and RX (in one picture).

    I agree that  BQ34 doesn't ACK TX (it is NACK, high) at data transmit 0x02. But it is seen that all other acknowledgements are there at Write and Read.

    Please help me out.

    thanks

    ritul shah

  • Hi QJ Wang,

    Eagerly Waiting for your response.

    Thanks
    Ritul Shah
  • Hello Ritul,

    Have you make your code work?
  • Hi  QJ Wang,

    I have made the I2C code work, but i am getting the SOC values on registers after a long delay. 

     What can be the probable reason?

  • Hello Ritul,

    What do you mean the "long delay"? The SCO data may not be ready when you send command to BQ34.