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.

First time using I2C with MSP430G2553, having problems.

Other Parts Discussed in Thread: MSP430G2553

To help familiarize myself with I2C and MSP430 microcontrollers I thought it would be fun to connect a Nintendo Wii nunchuck controller to the microcontroller and have it send back data to my PC using the built-in UART.

Setting up the UART was pretty easy, I'm using an MSP430 Launchpad so I took advantage of its USB->serial capabilities. For whatever reason, the Rx and Tx pins are connected in reverse when using the msp430g2553, I had to make little jumpers that swapped those two pins. Anyway, it works great (provided you stay at or below 9600bps) so I'll stop complaining.

My problem is with I2C, I can send the start signal plus the device address and it seems like the nunchuck sends back an ACK but then the bus becomes "frozen" (for lack of a better term). The microcontroller holds SCL low and the nunchuck holds SDA low.

The following is the code I'm using:

 

#include <msp430.h>

int main()
{
    WDTCTL = WDTPW + WDTHOLD;

    // Set up a 16MHz main clock
    DCOCTL  = CALDCO_16MHZ;
    BCSCTL1 = CALBC1_16MHZ;

 

   /************
    *I2C CONFIG*
    ************/

    // Set master mode, I2C operation, and synchronous mode
    UCB0CTL0 = UCMST + UCMODE1 + UCMODE0 + UCSYNC;

    UCB0CTL1 |= UCSSEL0 + UCSSEL1; // Use SMCLK
    UCB0BR0 = 160; // Set 100kHz baud rate
    UCB0BR1 = 0;

    UCB0I2CSA = 0x52; // Set the slave address for the nunchuck

    // Connect the SDA/SCL pins to the I2C module
    P1SEL  |= BIT7 + BIT6;
    P1SEL2 |= BIT7 + BIT6;

    UCB0CTL1 &= ~UCSWRST; // Enable the USCI
    UCB0CTL1 |= UCTR; // Set transmit mode
    UCB0CTL1 |= UCTXSTT; // Send START + slave address

    while (UCB0CTL1 & UCTXSTT);

    return 0;
}
The code gets stuck on that last line (the while loop), with the status registers in the following states:
Register Value Bits Set Meaning
UCB0TXBUF 0x00
UCB0RXBUF 0x00
UCB0STAT 0x50 UCSCLLOW, UCBBUSY SCL is held low, Bus busy
UCB0CTL1 0xD2 UCSSEL1, UCSSEL0, UCTR, UCTXSTT SMCLK, Transmitter, Generate START condition
UCB0CTL0 0x0F UCMST, UCMODE1, UCMODE0, USYNC Master mode, I2C mode, Synchronous mode
IFG2 0x0A UCB0TXIFG UCB0TXBUF is empty
The following picture shows the bus (SCL is trace 1, SDA is trace 2) with with the nunchuck plugged in:

 

That little spike on the data line concerned me, but it seems to come after the 9th clock pulse so I don't think it's problem, right? Here's a closer look at that pulse:

 

And this is with the nunchuck unplugged:

 

Am I doing something inherently wrong here? Why would the bus be hanging like that?

  • Some guesses in my part. The waveforms look mostly good, start bit, 7 addr bits, w bit. The slave appears to be ACKing the master by pulling down SDA but the slave also appears to be clock stretching by pulling down SCL as well. The slave is suppose to let go of the SCL when it's ready. It just nevers seems to be ready. Google would suggest that the nunchunk only works at 400kHz. You could try 400khz but I'm not sure your pullup resistors are strong enough to pull up the line quickly enough at 400kHz.

  • I thought it was holding the clock low at first, but it's actually the MSP430 that's holding SCL low; the nunchuck is holding SDA low. I say this because when I unplug the nunchuck the clock stays low, and SDA goes high. I've also measured which way the current is going with a multimeter just to confirm what I just described. Weird, eh?

     

    Also, I tried running SCL at 400kHz with 1kOhm pull-up resistors without any success. You were right about the 10k resistors, at 400kHz the pulses take a loooong time to get to 3.3V :)

  • In the the case without the nunchunk, there is the extra clock pulse where I assume the master samples the NAK'ed SDA. I would guess that is where the STT bit should clear. Your code would test for NAK'ed error condition and tear everything down with a stop. That should return SCL and SDA back to high. Otherwise, the I2C controller just leaves everything as it left it. One could write a driver that ignores ACK/NAK and blindly transact with a non-existent slave.

    With the nunchunk, I am guessing the master tries to let the SCL return to high in order to sample the ACK but the slave keeps it pulled down. Not familar with the MSP30. Don't know what if does in a clock stretching situation.

    That't all I got. Perhaps try something easier like a an I2C EEPROM or GPIO expander.

  • I went back and read how the MSP430 handles clock stretching and I found my answer.

    From page 470 of the datasheet:

    • The UCSCLLOW bit is also active if the USCI holds SCL low because it is waiting as transmitter for data being written into UCBxTXBUF or as receiver for the data being read from UCBxRXBUF.

     

    So I got rid of that while loop, and instead loaded the Tx buffer. It works! Now I need to see if I can get some data out of this thing :)

     

    Thanks Norman! Next time I'll read the datasheet better...

**Attention** This is a public forum