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.

MSP430G2553: I2C issues when not connected to PC

Part Number: MSP430G2553

I am experiencing issues using I2C on a msp430g2553 on a PCB. When I flash my code onto the external board by connecting via the ezFET side of the launchpad, I experience no issues (even when loading rather than going into debug mode on CCS). However, after flashing my code and disconnecting from the launchpad, my program gets stuck in my InitMPU() function. The initMPU() function simply transmits data using the TransmitByte() function in i2c.c (see below). 

 Here is my i2c.c file, where initI2C() and TransmitByte() are called from main.

/*
 * i2c.c
 *
 *  Created on: 4 Apr 2024
 *      Author: Chris
 */

#include "i2c.h"

// Function to config I2C regs - 400 kHz operating freq
void initI2C(void) {

    P1SEL |= SCL + SDA;                         // Config P1.6 SCL and 1.7 SDA
    P1SEL2 |= SCL + SDA;
    UCB0CTL1 |= UCSWRST;                        // Enable SW reset - known state
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // Make MCU master & put in synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST;              // SMCLK approx 1 MHz
    UCB0BR0 = 9;                                // /3 to get fast rate approx 400 kHz
    UCB0BR1 = 1;
    UCB0I2CSA = MPU_SLAVE_ADDRESS;              // Set slave address of mpu6050
    UCB0CTL1 &= ~UCSWRST;                       // Exit SW reset now that registers are configured
}

int IsI2CBusy(){
        if(UCB0STAT & UCBBUSY){
            return 1;                           // BUS BUSY
        } else{
            return 0;                           // BUS NOT BUSY
        }
}

// Function to read a single byte of given I2C Slave Address
char ReceiveByte(char register_address){

    volatile char byte;
    while (UCB0CTL1 & UCTXSTP);                 // Wait for our prev stop condition to be sent (just in case..)
    UCB0CTL1 |= UCTR + UCTXSTT;                 // Lets start in transmit MODE
    while((IFG2 & UCB0TXIFG) == 0);             // Wait for MPU66050 Device Address to be sent
    UCB0TXBUF = register_address;               // After we get ACK, lets send register address we want to read
    while((IFG2 & UCB0TXIFG) == 0);             // Wait for ACK...
    UCB0CTL1 &= ~UCTR ;                         // Now we can receive data from the register address
    UCB0CTL1 |= UCTXSTT + UCTXNACK;             // Send START and we respond with NACK for single byte read
    while (UCB0CTL1 & UCTXSTT);                 // Wait for start to complete...
    UCB0CTL1 |= UCTXSTP;                        // Send stop
    while(!(IFG2 & UCB0RXIFG));                 // Wait until we receive
    byte = UCB0RXBUF;                           // Read the byte
    return byte;

}

void TransmitByte(char register_address, char data){

    while (UCB0CTL1 & UCTXSTP);                 // Wait for our prev stop condition to be sent (just in case..)
    UCB0CTL1 |= UCTR + UCTXSTT;                 //
    while((IFG2 & UCB0TXIFG) == 0);             // Wait for MPU66050 Device Address to be sent
    UCB0TXBUF = register_address;               // After we get ACK, lets send register address we want to read
    while((IFG2 & UCB0TXIFG) == 0);             // Wait until our reg address is sent
    UCB0TXBUF = data;                           // Now we can send our data to that address
    while((IFG2 & UCB0TXIFG) == 0);             // Wait...
    UCB0CTL1 |= UCTXSTP;                        // STOP
    IFG2 &= ~UCB0TXIFG;                         // Clear Flag

}

And below is my main (a shortened version). Again, InitMPU() simply calls TransmitByte() from i2c.c. When I don't call InitMPU(), the code works as expected when the board is powered externally and not connected to the launchpad. When I call InitMPU(), the program must be getting stuck in a while loop present in TransmitByte(). I'm at a loss for why this might be the case when not connected to the ezFET side of the launchpad as it works when connected  with no issues.

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;                               // stop watchdog timer
    __enable_interrupt();


    IFG2 = 0x00;                                           // Reset IFG2
    initI2C();                                             // Init I2C for reading mpu6050
    while ( IsI2CBusy() );

    initMPU();  
}

  • How is your system powered when not connected to the Launchpad?

    The MPU6050 boards I've seen (from Amazon and such) run from 5V, and have on-board regulators down to 3V. 5V is available on the Launchpad (from the USB) but otherwise you have to provide your own.

  • Thank you for the response. The PCB has an on board regulator which steps down to 3.3 V. The issue is not related to the powering of the board as the board can execute code with no issues when I’m not using any I2C functionality.

    I also flashed code onto the external board when powering it with the external power source while connecting only to SBWCLK, SBWTDIO and GND of the launchpad. With that set up, the board even worked with I2C functionality. But when disconnecting from the launch pad, and pulling the ~RST pin HIGH, it seems to get stuck in TransmitByte(). Its odd because this exact setup works for running other types of functionality (timers, GPIOs) , but not my I2C functionality. 

  • Apologies, think I misinterpreted your response when I first read it. 

    I power the MPU6050 with 3.3 V. I also have a mpu6050 module from Amazon which I powered with 3.3V and that worked with no issues. Also, the one assembled onto the PCB works with Vcc=3.3 V when connected to the launchpad with the 5V jumper disconnected. I don’t think the issue is related to powering the board but may be wrong. 

  • The MPU6050 runs fine with 3.3V. The boards I mentioned (all?) seem to run from 5V, perhaps to accommodate 5V Arduino boards.

    Notably, they also supply the I2C pullups. How are you providing these?

    As a coding matter, it would be a good idea for both TransmitByte and ReceiveByte to check for UCB0STAT:UCNACKIFG, particularly during the second TXIFG loop. This would help to distinguish between a dead IMU device and (e.g.) a hung bus.

  • Thank you for the suggestions!

    Yeah I would assume it was to accommodate for Arduino. I double checked the datasheet for the module I had and 3.3 Vcc is acceptable so I don’t think thats the root of this problem. And yes I have provided pull up resistors on on the SCL and SDA lines.

    That is a good suggestion, I will include these checks when Im back at my desk and will see how that goes.

    Im just quite confused to why Im able to transmit and receive from the MPU when Im connected to the launchpads SBWCLK, SBWTDIO, and GND pins and otherwise does not. Was scraping through the datasheet to try and find a hint to why that might be but couldn’t find any clues. My setup works perfectly fine for running other things without connecting to the launchpad but it doesn’t seem to like I2C… very confused.

  • Based on your description I'm pretty sure it has to do (somehow) with the power.

    A scope is really handy if you have one of those.'

    [Edit: I (vaguely) recall that the MPU6050 takes some 10s of ms to start up. If you're powering them at the same time, the IMU might not be ready when you talk to it. Consider inserting something like:

    __delay_cycles(35000UL); // 35ms, more or less, for IMU to start

    to see if it makes a difference.]

  • Thanks Bruce, you are correct. With the addition of a delay as of your suggestion, the problem has been resolved.

    Appreciate the help!

**Attention** This is a public forum