Hey all,
I have been working on a custom PCB with an MSP430F5529 and LSM6DS33 break out sensor (datasheet). I have tested this sensor using an Arduino Mega and the SparkFun Library (GitHub Library). Next, I have attempted to read data from this sensor using the USCI I2C Peripheral of the MSP430. I have read and examined the User Guide and the MSPWARE 3.60.00.10 examples. I tried mixing the examples together to write a function that will read up to twelve consecutive registers from the sensor. The code, however, gets stuck waiting for the TX buffer to finish shifting the byte (target register) into the peripheral. And I cannot figure out why.
First, I initialise the I2C peripheral:
//Set the pin 3.0 and 3.1 as I2C P3SEL |= 0x03; //Reset USCI before configuring UCB0CTL1 |= UCSWRST; //Set USCI to I2C master mode and set MSB first UCB0CTL0 |= UCMST | UCMODE_3 | UCSYNC | UCMSB; //Set the baud rate 1MHz/10 = 100kHz UCB0BR0 = 10; UCB0BR1 = 0; //Set the clock source, enabling I2C UCB0CTL1 |= UCSSEL_2; //Disable interrupt requests UCB0IE &= ~(UCTXIE + UCRXIE); //Save Slave Address UCB0I2CSA = 0x6A;
//Enable I2C module UCB0CTL1 &= ~UCSWRST;
>> Assumption: the Slave Address is shifted one bit left by the peripheral when it adds the R/W bit.
Next, I attempt to send a byte with the address to the Slave, following the protocol as described in Table 15 on Page 30 of the LSM6DS33 Datasheet. According to the User Guide, the UCTXIFG bit will be set after the Slave Address has been sent, to indicate that UCB0TXBUF is ready to receive a byte. Then I write my data to the UCB0TXBUF and wait for the UCTXIFG bit to be set again. After that, a Repeat Start must be sent again, telling the Slave that it needs to send data to me.
//Send start condition. UCB0CTL1 |= UCTR + UCTXSTT; //Wait for the start condition to be sent. while(!(UCB0IFG & UCTXIFG)){;} //Write byte into transfer buffer UCB0TXBUF = 0x28; //Wait for the data to be sent. while(!(UCB0IFG & UCTXIFG)){;} //Start receiving n bytes //Send repeat start condition UCB0CTL1 &= ~UCTR; UCB0CTL1 |= UCTXSTT;
The code, however, get stuck in the second while loop, right after the data has been written to the UCB0TXBUF.
Attempted solutions and additional information:
- Add external pull-ups on SDA and SCL lines; they are already on the break-out board (schematic) so they shouldn't be necessary anyways.
- Enable interrupts (I assumed that the corresponding bits in the UCB0IFG are set whether an interrupt is generated or not).
- Check for connection, PCB and solder errors (also measured 3.27 VCC steady).
- SDO is soldered to ground (making the LSB of the Slave Address a '0').
- Add a UCSCLLOW check after writing UCB0TXBUF; there is no external device pulling the SCL low.
Unfortunately, I do not possess an oscilloscope or digital analyzer. I might be able to borrow one next week, then I can add signal images of SDA and SCL. For now, I need to know:
- Is my code correct? It doesn't provide build errors/warnings.
- Is my code complete? I might have overlooked some crucial setting/interrupt/register value.
- Is there anything else on the hardware that might cause issues?
Any help, insights, advice, design tips, code tricks, useful links or code testing is appreciated. I will gladly provide more details if they are necessary. This is the final piece of code I need to get working; after this, I can finally finish my demo and graduate...
Kind regards,
Martin Janse