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.

MSP430G2955: I2C Communication not working..

Part Number: MSP430G2955
Other Parts Discussed in Thread: BQ78350, , TIDA-00449, BQ76930, MSP-TS430DA38

Hey TI Experts, I was working with MSP430G2955 and BQ78350 in a bms board .I'm working on the firmware of this. I got a code from TIDA-00449 software support part. I'm trying to read the voltage and current from the cells in this code. i have initialized the I2C bus according to on of the examples that we got from the TI website.

I took reference of the I2C send and receive codes from drv_i2c.c from design help from TIDA-00449. I also put  in some print statements to check where the issue was. I have attached the code that i have below along with the output. 

Also if you have any other suggestions for the codes that could be used for reference, please let me know.

Kindly help me with this.

PS. MSP is the master and BQ78350 is the slave.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <inttypes.h>
#include <msp430.h>
#include <driverlib.h>
#include <string.h>
#include "drv_i2c.h"
#include "drv_bq76930.h"
#define DELAY_LIMIT1 10
unsigned char *ptr_rx;
unsigned char RXByte[100];
unsigned char Slave_Address1 = 0x17;
// COMMANDS
#define REMAININGCAP 0X01
#define REMAININGTIME 0X02
#define BATTERYMODE 0X03
#define ATRATE 0X04
#define ATRATETIMETOFULL 0X05
#define ATRATETIMETOEMPTY 0X06
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

OUTPUT :         

  • > unsigned char Slave_Address1 = 0x17;

    My first guess is that your device/board is using address 0x16 rather than 0x17 [Ref BQ78350 TRM (SLUUAN7B) Sec 16.6]. Try instead:

    > unsigned char Slave_Address1 = 0x16;

    What platform (board set) are you using?

  • Hey, Thank you for the quick response! 

    I did try it with 0x16 as well, but it still is not working as i want it to.

     What platform (board set) are you using?

    I am using the MSP-TS430DA38 to communicate with the bq78350 chip through I2C.

  • What board is the BQ78350 mounted on? (I'm unfamiliar with the term "bms".) Of particular interest here is whether the I2C pullups are supplied, since (as far as I know) the TS430 boards don't supply them.

    I should mention here that in this code the "nack" message really reports a timeout, which might or might not result from a NACK.

  • Hey Bruce. Sorry for the delayed response. 

    BMS stands for a Battery Management System which is an in house battery management system board and the bq78350 is mounted onto this board. 

    One question, are the pull up resistors necessary for the working I2C communication(I have no clue about the PCB Designing part)??

    I should mention here that in this code the "nack" message really reports a timeout, which might or might not result from a NAC.

    I did try with the logic analyzer and did a few changes to the original code. Could you please check that as well?

    Also we have used a 100 ohms pull up resistors.

    I will attach the necessary files here below.

    Edited code:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdio.h>
    #include <inttypes.h>
    #include <msp430.h>
    #include <driverlib.h>
    #include <string.h>
    #include "drv_i2c.h"
    #include "drv_bq76930.h"
    #define DELAY_LIMIT1 10
    unsigned char *ptr_rx;
    unsigned char RXByte[100];
    unsigned char Slave_Address1 = 0x0B;
    // COMMANDS
    #define REMAININGCAP 0X01
    #define REMAININGTIME 0X02
    #define BATTERYMODE 0X03
    #define ATRATE 0X04
    #define ATRATETIMETOFULL 0X05
    #define ATRATETIMETOEMPTY 0X06
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Screenshots of the logic analyzer:

                

    I don't understanding why I'm getting this:

      

    Its this sequence that is repeated afterwards throughout the recording time:

       

  • 1) What is the value of DELAY_LIMIT? I see DELAY_LIMIT1[=10], but that doesn't appear to be used. 

    From your earlier console output, it looks like DELAY_LIMIT was =255, which is probably too aggressive. Each bit takes UCB0BR0/1 SMCLKs, so a byte  would take (minimum) (9*100)=900 SMCLKs. Software counting loops are notoriously difficult to calibrate, but with DELAY_LIMIT=255 that requires at least 4 CPU clocks per loop to avoid timing out prematurely.

    Looking at your analyzer trace, it appears the I2C is actually running at more like 50kHz (rather than 160kHz), which would mean 20us*16*9=2880 CPU clocks/byte. Allowing 10 CPU clocks/loop, that implies a DELAY_LIMIT of at least 288. Timeouts are (presumed) rare, so I suggest you multiply this by at least *10 to add some cushion, so maybe DELAY_LIMIT=3000 would be reasonable.

    2) It looks like, in the case of an Rx timeout (possibly premature), the code puts the I2C unit into reset (UCSWRST), and I don't see anything that un-does this. That might help explain the last 2 analyzer traces.

    3) In main() there are two malformed printf(missing format string) calls -- the compiler even noticed them. I'm not quite sure what those calls are doing to you.

    [Edit: (4) 100 Ohm is very strong for I2C pullups; 3-5KOhm is more typical. This probably isn't causing your current troubles.]

  • From your earlier console output, it looks like DELAY_LIMIT was =255

    Yes its is set to 0xFF.

    Looking at your analyzer trace, it appears the I2C is actually running at more like 50kHz (rather than 160kHz),

    Yes it is running at around 50kHz. I am not understanding how to set the prescaler value. I tried various values for the UCBR0 bit, i did not get the required response for a set of values. could you help me out with setting up the prescaler value? I thought it would be according to the formula given below which i found in https://www.ti.com/lit/ug/slau144k/slau144k.pdf?ts=1710323770953&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FMSP430G2955.

    I suggest you multiply this by at least *10 to add some cushion, so maybe DELAY_LIMIT=3000 would be reasonable.

    Ok will try with it once. 

    In main() there are two malformed printf(missing format string) calls -- the compiler even noticed them. I'm not quite sure what those calls are doing to you

    I will edit this accordingly. Thanks for rectifying the error.

    Also the NACK Bit is occurring after the register address being sent. Could this be due to the previous errors in the code?

  • Are you fairly certain you're seeing a NACK and not a (premature) timeout? My thought is to get the other things under control, so you can be sure of what you're seeing. Running the I2C at 50kHz is fine for now, as long as you're conscious of it.

  • Could you suggest me some more changes that could be done in my code to make the situation better?

  • What have you changed so far, and what results are you getting now? I expect the timeout change will have an effect, even if it doesn't fix everything.

    I don't have one of your devices, so you may need to experiment. It's possible the device has its own oddities.

    Also, I noticed that the device has a bus-timeout mechanism (roughly 1 second?) so avoid stopping in the debugger in the middle of a transaction.

  • Hey Bruce, I have changed the delay limit value and some other changes are done. However we found out today that the IC what was used was faulty. So we did change it and now it is able to retrieve data and there are a few errors:

    1. The first time we run the code, it works and the data retrieved is also correct and matches the multimeter value. For example we read voltage and the multimeter showed 24.196V and the logic analyzer showed 0x5EE8(24.29V). Then the next execution just doesn't work and gives a NACK bit in the first write to the slave itself. 

    2. I am unable to come up with the code to retrieve the WORD and can just retrieve BYTE.

    Could you please guide me with these two queries. 

    I will attach the current code and the relevant logic analyzer screenshots int his thread. 

    Thanks in advance! 

    This is the most recent code:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdio.h>
    #include <inttypes.h>
    #include <msp430.h>
    #include <driverlib.h>
    #include <string.h>
    #include "drv_i2c.h"
    #include "drv_bq76930.h"
    #define DELAYLIMIT 0x0BB8
    unsigned char *ptr_rx;
    unsigned char RXByte[100];
    unsigned char Slave_Address1 = 0x0B;
    // COMMANDS
    void delay_cycles(int delay)
    {
    int i=0;
    for(i=0;i<delay;i++)
    {
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Screenshots:

    1. After the first execution

           

    2. First execution: I do not have a picture of the console for this one.

  • What I see in the second trace is:

    a) A successful write(0x09) followed by a successful read of 4 bytes, which isn't what your code appears to do.

    b) Another successful write(0x09) followed by a read which gets a NACK. Here again, I don't see in your code where the second sequence originates. I also don't know why the device would NACK the read request, but once it does the code doesn't issue a Stop, and things seem to fail after that.

    Unsolicited: This code sets a number of interrupt enables (UCB0RXIE, e,g.) but I don't see an ISR. I also don't see anything that sets GIE, so I expect it all works by accident. If you ever enable global interrupts (GIE=1, __enable_interrupt()) your program will malfunction, so I suggest you remove the I2C interrupt enables.

  • Hello Bruce,

    We made a few changes in the delay that we had added and the code is now working. 

    I did learn a lot about the errors that could possibly be done and in general about a lot of things. 

    Thanks a lot for you guidance! 

**Attention** This is a public forum