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.
