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.

MSP430F5340: MSP interfaced with BQ27545 , I2C timeout happens frequently/after MSP powerup

Part Number: MSP430F5340
Other Parts Discussed in Thread: MSPWARE, BQ27545-G1

Hi 

Even i have the same configuration as in linked post -( Dipin's Post )

configuration - MSP430F5340 configured for I2C to communicate with BQ27545 fuel gauge IC.

issue - I2C timeout happens either regularly or while after MSP powerup. highlighted the code part where i get stuck.

below is the code :

#define LOOP_COUNT 10000


void BatteryFuelGuageI2CInit(void)
{
P4SEL |= 0x06; // Assign I2C pins to USCI_B1
UCB1CTL1 |= UCSWRST; // Enable SW reset
UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB1CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB1BR0 = 30; // fSCL = SMCLK/30 = ~33.33kHz
UCB1BR1 = 0;
}


uint16_t BatteryFuelGuageI2CMasterReceive(uint8_t ucSlaveAddress, uint8_t ucCmd, uint8_t ucDataLength)
{
uint8_t ucRxdata[2]={};
// set Slave Address as 0x55
UCB1I2CSA = ucSlaveAddress;
// Clear SW reset, resume operation
UCB1CTL1 &= ~UCSWRST;
//I2C time out flag
g_I2Ctimeoutflag = true;

uint16_t uloopcount = 0;

for (uloopcount = 0; uloopcount < LOOP_COUNT; uloopcount++)
{
if ((UCB1CTL1 & UCTXSTP) == 0)
{
break;
}
}
if (uloopcount == LOOP_COUNT)
{
return 0;
}

// Transmitter, Send start condition
UCB1CTL1 |= UCTR + UCTXSTT;

/* Send command to FuelGuage */
for (uloopcount = 0; uloopcount < LOOP_COUNT; uloopcount++)
{
if (UCB1IFG & UCTXIFG)
{
break;
}
}
if (g_uloopcount == LOOP_COUNT)
{
return 0;
}

// sending cmd
UCB1TXBUF = ucCmd;
// wait until cmd got sent
for (uloopcount = 0; uloopcount < LOOP_COUNT; uloopcount++)
{
if (UCB1IFG & UCTXIFG)
{
break;
}
}
if (g_uloopcount == LOOP_COUNT)
{
return 0;
}
////////////////////////////////////////////////////////////////////////////
// Set master in Receive mode, Send start condition
UCB1CTL1 &= ~UCTR;
UCB1CTL1 |= UCTXSTT; // Send repeated start condition
unsigned int uiCounter = 0;
unsigned int uiRxCounter = 2;
while (uiRxCounter > 0)
{
for (uloopcount = 0; uloopcount < LOOP_COUNT; uloopcount++)
{
if (UCB1IFG & UCRXIFG)
{
break;
}
}
if (uloopcount == LOOP_COUNT)
{
return 0;
}
ucRxdata[uiCounter] = UCB1RXBUF; // Receive data from fuel gauge
if(uiCounter == 0)
{
//Send stop condition.
UCB1CTL1 |= UCTXSTP;
}
uiCounter++;
uiRxCounter--;
}

UCB1IFG &= ~UCRXIFG;
/* Clear USCI_B1 TX int flag */
UCB1IFG &= ~UCTXIFG;
g_uBatteryInfo = (uint16_t) ucRxdata[0] << 8 | ucRxdata[1]; //Transmit received data byte by byte

g_I2Ctimeoutflag = false;
return g_uBatteryInfo;
}

need your suggestions to resolve this issue.

Thanks

Rekha

  • Hi,

    have you tried to debug the problem using our application report on these topics?

    Best regards

    Peter

  • Hi Peter,

    I have gone through pdf report that you attached. I have been debugging this with respect to all those points mentioned in report. But no luck in resolving this issue.

    I have one doubt - what is the time taken to complete one transaction over I2C , example - if I send start bit , how much time should I wait for ACK and gap to start next communication.

  • Hi Rekha,

    did you take a look at MSP430F534x_uscib0_i2c_06.c

    This is a code example of ours demonstrating how to transmit as master to a slave.

    What is see in your code is e.g.

    void BatteryFuelGuageI2CInit(void)
    {
    P4SEL |= 0x06; // Assign I2C pins to USCI_B1
    UCB1CTL1 |= UCSWRST; // Enable SW reset
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB1CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB1BR0 = 30; // fSCL = SMCLK/30 = ~33.33kHz
    UCB1BR1 = 0;
    }

    Why are you not completing the initialization in this function and set the slave address, release the SW reset of the module and set TX interrupt enable?

    I would suggest to test with our code example, modified for your baud rate and slave address, to check if that one works, as it should, and than take it from there.

    Best regards

    Peter

  • Peter,

    should i need to send slave address in init function ? is it mandatory ?

    Thanks

    Rekha

  • I included the changes suggested by you except instead of interrupt method i am polling the device and i cannot include slave address in init because we have two slaves with different address,  but still the issue occurred. 

    I also observed that Master is unable to generate clock , below is the image taken from logic analyzer.

  • Hello Rekha,

    the reason why I suggested applying our complete initialization sequence, is that only this guarantees a proper functionality of the module. The I2C is a quite complex state machine. I understand your point, but from my perspective one visible difference, between what you're trying to do and our code examples is the following:

    Your initialization function

    void BatteryFuelGuageI2CInit(void)
    {
    P4SEL |= 0x06; // Assign I2C pins to USCI_B1
    UCB1CTL1 |= UCSWRST; // Enable SW reset
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB1CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB1BR0 = 30; // fSCL = SMCLK/30 = ~33.33kHz
    UCB1BR1 = 0;
    }

    Our function looks as follows

       P3SEL |= 0x03;                            // Assign I2C pins to USCI_B0

      UCB0CTL1 |= UCSWRST;                      // Enable SW reset
      UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
      UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
      UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
      UCB0BR1 = 0;
      UCB0I2CSA = 0x48;                         // Slave Address is 048h
      UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
      UCB0IE |= UCTXIE;                         // Enable TX interrupt

    The last three marked lines are missing.

    The other question is also your HW setup. Even if no slave would be connected to the master, the signals on the master pins need to show the following sequence up to the ACK point from the slave. So if your master, with our code example and disconnected slaves is not showing this, there is definitely something wrong with your setup, let it SW or HW. As the code example from us tested, on the SW side it can be only a mismatch in the configuration relative to your HW.

    Two additional comments of mine. Please step back and use purely our code example and test, whether the master is transmitting something on the configured I2C pins. Secondly, you're using a logic analyzer. This is fine in case everything works, but as long as wired communication and especially communication with critical physical layer is not working, it is good practice to check the signals with an oscilloscope, to see the real analog signals.

    Best regards

    Peter

  • Peter,

    Thank you for detailed explanation. i will cross check the code and setup again. 

    Thanks

    Rekha

  • Hello Rekha,

    could you please give us an update on this? Did you manage to come any further?

    Best regards

    Peter

  • Hi Peter,

    i have checked this but i could not resolve this issue. 

    at some point of time master hangs in one of the while loop in I2C master receive function. 

    any inputs from your end would be more helpful

    Thanks

    Rekha

  • Hi Rekha,

    I would be happy to support you, but I need some more information, and consistent follow up on my recommendations.

    So could you please give me a more detailed explanation on the following:

    My recent recommendation was to use purely our code example for the master communication, recommending to test the master without the slave first, checking whether your master does transmit signal up to the expected Acknowledge.

    Have you performed this test, and what is the outcome?

    Best regards

    Peter

  • Hi peter,

    i have followed your comments and tested :

    - included 3 lines ( highlighted by you ) in init function but still error occurs

    - compared my code with your code the only difference is , i am using polling since my architecture does not suppose to use any interrupts

    - i cannot disconnect slave since it is embedded on PCB , please suggest any alternate options

    i have tested with above modifications suggested by you, but still i am seeing the issue.

    Thanks

    Rekha 

  • Hello Rekha,

    based on your summary, I think we still misunderstand each other. So please let me once again describe, what I am suggesting:

    I have understood, that of course you need more and would like to have a different implementation, than our code example. But to find out, what the root cause of the failures on your side is, we need to debug it step by step from a safe point. The safe point in this case should be our tested code example. So my recommendation is not, to take the code example and integrate it into your code, as probably your code contains errors in other spots, and purely the paste in of the code example does not help.

    Thus my recommendation is take the tested code example from us as is and test it in your application.

    Now potentially you're using another I2C module, as the code example, or different IOs, thus will need to adapt the code example at this point. Likewise with the slave address.

    But the intention is to change as little as needed to adapt to your HW setup and than test purely this code, nothing less nothing more.

    As soon as we have this working, we will start adding functionality towards the implementation you're aiming for, but step by step, to find out where the problem sits.

    I hope this clarifies my recommendations.

    Best regards

    Peter

  • Hi Peter,

    i understood what you are trying to tell me, i can test your code individually. can you please provide me the link for your tested code.

    i  might be having the older version of code.

    Thanks

    Rekha

  • Hi Rekha,

    the code example, like others are part of the Code Composer Studio IDE, which you can download from our home page. You can find those in the integrated TI Resource Explorer.

    Please let me know in case you should struggle with finding these. For sake of time, please find here the imported project from the MSP430Ware - v:3.80.07.00 code example set attached. You need to import the project into your CCS environment, to be able to use the project.

    Best regards

    PeterF5340_I2C.7z

  • Hi Peter,

    I tried to import the project files but is giving below error, i also installed MSP430v 18.12 compiler version. still i am unable to import the file.

  • Hi Rekha,

    which CCS version do you have installed? Did you try importing the project I have attached, or did you try importing the I2C code example from your MSP430Ware installation and its code examples? I have created the attached project with latest CCS version, means 9.2, thus if you have an older one you either need to install the latest one, or try importing the code example from your version.

    Best regards

    Peter

  • Peter,

    Thanks for the info, i have older version of CCS i.e 8.3. i will tryto import from my  MSPware examples and check it.

    i assume there are no changes in the i2C code as compared to your latest code.

    if there are any changes from older version to new version let me know.

    will update once after testing.

    Thanks

    Rekha

  • Hi Rekha,

    no there are no changes on the code example as such. It is just the newer IDE version, including a Compiler update, that's why you cannot import the project of mine.

    Best regards

    Peter

  • Thank you 

    I will update on this once after testing.

  • Hi Peter,

    i have programmed my board using your example codes. below are my observations:

    1. programmed MSP with example code MSP430F534x_uscib0_i2c_06 where master transmits data on I2C lines. i was able to see MSP was transmitting data successfully but after some time it got hung @line 

    i don't know why it got hung in that line, but otherwise code works fine for initial data transfer.

    2. programmed MSP to read data from slave. where i have used my code to read data from fuel gauge(slave).

    below is the code (i have not included any other code from my application). only I2C is tested.

    issues:

    1. master transmitted slave address->did not receive ACK from slave, it was hung totally.

    2. master transmitted slave address-> received ACK->sent command to slave->received ACK->receive data bytes... while receiving data again hanging issue occured

    3. after few successful transaction, master will keep waiting for completion of previous I2C transcation i.e. while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent

    above are few observations what i made. 

    i also have screenshot of analyzer below-

    I2C transaction successful

    I2C transaction hanging issue 


    i do have complete captured data from logic analyzer. i can send it if you need it for reference. since it is huge file i am not attaching it.

    please suggest what might be the issue. is it a timing and synchronization issue???

    Thanks

    Rekha

  • Peter,

    i did workaround for above errors: i made some modifications , now I2C looks somewhat stable. 

    right now i am not getting any errors or hanging issue. attached is my code: Let me know if you find any mistakes in code.

    7144.main.c
    #include <msp430.h> 
    
    unsigned char *PRxData;                     // Pointer to RX data
    unsigned char RXByteCtr;
    unsigned char RxBuffer[10];       // Allocate 10 byte of RAM
    unsigned char nack_flag = 0;
    int main(void)
    {
        WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
        P4SEL |= 0x06;
        UCB1CTL1 |= UCSWRST;                      // Enable SW reset
        UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
        UCB1CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
        UCB1BR0 = 30;                             // fSCL = SMCLK/30 = ~33.33kHz
        UCB1BR1 = 0;
        UCB1I2CSA = 0x55;                         // Slave Address is 048h
        UCB1CTL1 &= ~UCSWRST;                    // Clear SW reset, resume operation
    
        while (1)
        {
    
            while (UCB1CTL1 & UCTXSTP);             // Ensure stop condition got sent
            UCB1CTL1 |= UCTR | UCTXSTT;             // I2C tx, start condition
    
            while((UCB1IFG & UCTXIFG) == 0);
            /* Check for ACK */
                       if (UCB1STAT & UCNACKIFG) {
                           /* Stop the I2C transmission */
                           UCB1CTL1 |= UCTXSTP;
    
                           /* Clear the interrupt flag */
                           UCB0STAT &= ~UCNACKIFG;
                           nack_flag = 1;
    
                       }
            UCB1TXBUF = 0x2c;
            while ((UCB1IFG & UCTXIFG) == 0)
            {
                /* Check for ACK */
    
                if (UCB1STAT & UCNACKIFG)
                {
                    /* Stop the I2C transmission */
                    UCB1CTL1 |= UCTXSTP;
    
                    /* Clear the interrupt flag */
                    UCB0STAT &= ~UCNACKIFG;
                    nack_flag = 1;
                    break;
                }
    
            }
            if (nack_flag == 0)
            {
                UCB1CTL1 &= ~UCTR;
                UCB1CTL1 |= UCTXSTT;
                while ((UCB1IFG & UCTXIFG) == 0) ;
    
                /* Check for ACK */
                if (UCB1STAT & UCNACKIFG)
                {
                    /* Stop the I2C transmission */
                    UCB1CTL1 |= UCTXSTP;
    
                    /* Clear the interrupt flag */
                    UCB0STAT &= ~UCNACKIFG;
                    nack_flag = 1;
    
                }
    
                unsigned int uiCounter = 0;
                unsigned int uiRxCounter = 2;
                while (uiRxCounter > 0 && (nack_flag == 0))
                {
                    while ((UCB1IFG & UCRXIFG) == 0);
                    RxBuffer[uiCounter] = UCB1RXBUF; // Receive data from fuel gauge
                    if (uiCounter == 0)
                    {
                        //Send stop condition.
                        UCB1CTL1 |= UCTXSTP;
                    }
                    uiCounter++;
                    uiRxCounter--;
                }
            }
            UCB1IFG &= ~UCRXIFG;
            /* Clear USCI_B1 TX int flag */
            UCB1IFG &= ~UCTXIFG;
    
      }
    }
    #if 0
    //------------------------------------------------------------------------------
    // The USCIAB0_ISR is structured such that it can be used to transmit any
    // number of bytes by pre-loading TXByteCtr with the byte count.
    //------------------------------------------------------------------------------
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B1_VECTOR
    __interrupt void USCI_B1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B1_VECTOR))) USCI_B1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB1IV,12))
      {
      case  0: break;                           // Vector  0: No interrupts
      case  2: break;                           // Vector  2: ALIFG
      case  4: break;                           // Vector  4: NACKIFG
      case  6: break;                           // Vector  6: STTIFG
      case  8: break;                           // Vector  8: STPIFG
      case 10: break;                           // Vector 10: RXIFG
            RXByteCtr--;                            // Decrement RX byte counter
            if (RXByteCtr)
            {
              //  *PRxData++ = UCB1RXBUF;           // Move RX data to address PRxData
                if (RXByteCtr == 1)                   // Only one byte left?
                    UCB1CTL1 |= UCTXSTP;              // Generate I2C stop condition
            }
            else
            {
               // *PRxData = UCB1RXBUF;               // Move final RX data to PRxData
                __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
            }
            break;
    
      case 12:                                  // Vector 12: TXIFG
    #if 0
        if (TXByteCtr)                          // Check TX byte counter
        {
          UCB1TXBUF = TXData;                   // Load TX buffer
          TXByteCtr--;                          // Decrement TX byte counter
        }
        else
        {
          UCB1CTL1 |= UCTXSTP;                  // I2C stop condition
          UCB1IFG &= ~UCTXIFG;                  // Clear USCI_B1 TX int flag
          __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
        }
    #endif
        break;
    
      default: break;
      }
    }
    #endif
    

  • This code appears to be violating tPUCD [Ref data sheet (SLUSAT0E) Sec 7.3]. It doesn't say what happens if you talk sooner than 1/4 second, but "I'll ignore you" seems a good first guess.

    Data sheet section 8.5.1.2 cites some restrictions on repetition rate which this code is also violating.

    (Yes, these are some rather significant/unusual restrictions, but we have to deal with the device we have.)

    [Edit: Our posts seem to have coincided. I defer to your experience, but I still suggest you keep the documented restrictions in mind.]

  • Thanks for your feedback, 

    i agree that i have to deal with these points but i am not clear on how and where to implement these points in code flow.

    But i did not understand about your first point. are you saying that device should be given 250 ms of wait time before starting I2C communication?

    and also can you please provide me few more detailed explanation on your second point i.e. datasheet section 8.5.1.2

    Thanks

    Rekha

  • I haven't used one of these devices, so I only know what the datasheet says.

    It did seem that the items I referred to, particularly since they're rather unusual, might be getting in your way. Overall, the device seems to be rather slow -- which is fine, since battery monitoring doesn't require much speed.

  • Thank you. Do you any example code for Battery fuel gauge?

    If yes, can you please share it.

    Or can you refer anyone who can provide more details on this topic

    Thanks

    Rekha

  • I haven't used this device, so no I don't have any example code.

    I see some software listed on the BQ27545-G1 Product page. A Forum search turns up 45 hits.

  • Hello Rekha,

    do you still need support on this?

    Best regards

    Peter

  • Hi Peter,

    I have resolved this issue by including proper communication delays and handling NAK flags. 

    Thank you and your team for your constant support.

    Thanks

    Rekha