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.

G2553 I2C understanding: ACK but no data transfer

Hello everyone,

(Hello Jens-Michael ;) )

i have written basic I2C libraries for the G2553 anf F5529 Launchpads and encountered an interesting problem. I got a workaround for the occuring problem but want to understand why the two approaches result in different behavior.

One of the functions of the library is called I2C_sendCommand(). It generates the starting signal, sets transmitter mode, TX's a single byte and generates a stop. For this, no interrupt is used.

void I2C_sendCommand(short command)
{	// Sends a single command over the I2C bus
	UCB0CTL1 |= UCTXSTT | UCTR;		// generate I2C start signal (sends adress automtically)
	UCB0TXBUF = command;			// send command
	__delay_cylces(300);			// wait for transmit to finish
	UCB0CTL1 |= UCTXSTP;			// generate stop condition
}

The above code works fine, but i dislike the __delay_cycles() usage so I tried

void I2C_sendCommand(short command)
{	// Sends a single command over the I2C bus
	UCB0CTL1 |= UCTXSTT | UCTR;		// generate I2C start signal (sends adress automtically)
	UCB0TXBUF = command;			// send command
	while(UCB0STAT & UCBUSY);               // wait for transmit to finish
	UCB0CTL1 |= UCTXSTP;			// generate stop condition
}

what works fine for sending single bytes, but if i call the function multiple times in a row, i end up with the adress being sent, slave ACKs, STP is generated. So no data transfer.

I wondered if the UCBUSY flag might be reset when the adress anr R/W bit are sent -> stop generated before TX buf was sent. I changed the code to

void I2C_sendCommand(short command)
{	// Sends a single command over the I2C bus
	UCB0CTL1 |= UCTXSTT | UCTR;		// generate I2C start signal (sends adress automtically)
	while(UCB0STAT & UCBUSY);
	UCB0TXBUF = command;			// send command
	while(UCB0STAT & UCBUSY);
	UCB0CTL1 |= UCTXSTP;			// generate stop condition
}

but got the same result. Using my sleep function (sending the MCU to a low power mode for a determined time) works as well as __delay_cycles().

I dont understand why the UCBUSY approach does not work and would be pleased if you have a quick hint for me.

  • I have a hint for you:

    UCBUSY != UCBBUSY

    EDIT: That explains why the bus never appears to be busy, but doesn't resolve your problem. UCBBUSY is true between I2C start and stop conditions, so waiting for it to go false before sending the stop condition is a bad idea.

    I think you need to wait until UCTXSTT=0, as that indicates when the USCI has started to send the first data byte. Setting UCTXSTP after this point means that the stop condition will be sent after the next acknowledgement from the slave.

**Attention** This is a public forum