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.

I2C read command with repeated start condition fails to stop after read byte

Dear community

I'm currently working on a project with a MSP430 launchpad connected to a compass module (MPU-9150). With the following code, I try to read two registers of the compass module. The module thereby requires a repeated start condition, in order to initiate a read command. The full sequence to read a register is: "Start | Slave Address | Write bit | ACK | Register address | ACK | Start | Slave address | Read bit | ACK | Slave response | NACK". The attached figure shows what I get as response from the compass module. The problem is that the for the first register, the read byte is followed by two 0x00 bytes, and for the second register, the read byte is followed by one 0x00 byte. How can I terminate the communication earlier, so that the trailing zero bytes vanish? The response from the slave should only be one byte (0x68).


#define TEST_REG 0x75
#define DEV_ADDRESS 0x68
#define ADDRESSING 1
#define RESTARTING 2
#define READING 3
#define FINISHING 4

const unsigned char regAddress[] = {TEST_REG, TEST_REG};
unsigned char magData[6] = {};
unsigned char i = 0;
unsigned char mode = ADDRESSING;

int main(void)
{
    //--- IO settings --------------------------------------------------------------------
    WDTCTL = WDTPW + WDTHOLD;                   // Stop WDT
    P1SEL |= BIT6 + BIT7;                                         // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7;                                        // Assign I2C pins to USCI_B0
    //------------------------------------------------------------------------------------
    //--- I2C controller settings --------------------------------------------------------
    UCB0CTL1 |= UCSWRST;                                                 // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST;                         // Use SMCLK, keep SW reset
    UCB0BR0 = 3;                                                                      // fSCL = SMCLK/3 = ~400kHz
    UCB0BR1 = 0;
    UCB0I2CSA = DEV_ADDRESS;                                      // Set slave address
    UCB0CTL1 &= ~UCSWRST;                                             // Clear SW reset, resume operation
    UCB0CTL1 |= UCTR;                                                          // Configure controller as transmitter
    //------------------------------------------------------------------------------------
    __bis_SR_register(GIE);                                                    // Global interrupt enable

    while(1)
    {
        while(i < sizeof regAddress)                                         // All registers read?
        {
            UCB0CTL1 |= UCTXSTT;                                          // Generate start condition
            IE2 |= UCB0TXIE;                 	                                   // Enable TX interrupt
            while (UCB0STAT & UCBBUSY);                            // Wait for current transmission to finish
            i++;                                                                                // Proceed with next register
        }
    }
}
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
	switch(mode)
	{
		case ADDRESSING:
			UCB0TXBUF = regAddress[i];                    // Put register address on bus
			mode = RESTARTING;                                // Proceed with next mode
			break;

		case RESTARTING:
			IE2 &= ~UCB0TXIE;					// Diable TX interrupt
			IE2 |= UCB0RXIE;					// Enable RX interrupt
			UCB0CTL1 &= ~UCTR;				// Reconfigure controller as receiver
			UCB0CTL1 |= UCTXSTT;                           // Generate a reapeated start condition
			IFG2 &= ~UCB0TXIFG;				// Clear TX interrupt flag
			mode = READING;                  	                // Proceed with next mode
			break;

		case READING:
			magData[i] = UCB0RXBUF;                      // Save read values
			mode = FINISHING;                                    // Proceed with next mode
			break;

		case FINISHING:
			UCB0CTL1 |= UCTXSTP;				// Generate stop condition
			IFG2 &= ~UCB0RXIFG;				// Clear RX interrupt flag
			IE2 &= ~UCB0RXIE;					// Disable RX interrupt
			UCB0CTL1 |= UCTR;					// Reconfigure controller as transmitter
			mode = ADDRESSING;                              // Reset mode
			break;

		default:
			break;
	}
}

Note that in the figure, the ACK bits are not displayed for the write and read command-parts, because of lack of space. They are however present.

Thanks in advance.

  • Section 17.3.4.2.2 of the User's Guide says:

    If a master wants to receive a single byte only, the UCTXSTP bit must be set while the byte is being received. For this case, the UCTXSTT may be polled to determine when it is cleared.

**Attention** This is a public forum