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.

Msp430g2553 master itg3200 gyro slave i2c problem

Other Parts Discussed in Thread: MSP430G2553, MSP430WARE

Hello TI community.

I'm a computer science engineer student and trying to do my engineering project with MSP430g2553 launchpad. What I'm trying to do is to get the gyro results from ITG3200 (here is the datasheet https://www.sparkfun.com/datasheets/Sensors/Gyro/PS-ITG-3200-00-01.4.pdf ) which communicates through i2c. I've been reading the datasheets and examples for i2c state machines and how they are implemented on msp launchpads. Since i use USCI i found it really easy since it has been already implemented in hardware of my launchpad. I tried msp430g2xx3_uscib0_i2c_12.c example which is provided from TI that a master receives from the slave with a Repeated start. My gyro uses a similar protocol where Master pulls down SDA for start condition, following by 7 bit slave address with a HIGH on SDA for writing. Then master releases SDA for ACK on 9th cycle. 7 following cycle master puts which register address on gyro it wants to read and 8th with another ACK. A repeated start must follow on 9th cycle. Then master gives the slave address again with a LOW on SDA for a read operation. After another ACK it reads 8 bit data and pulls the SDA to HIGH for a NACK and a stop condition. A typical i2c reading with a repeated address for register specifying. Here is the TI example code that I'm using.

    /* --COPYRIGHT--,BSD_EX
    * Copyright (c) 2012, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    *******************************************************************************
    *
    * MSP430 CODE EXAMPLE DISCLAIMER
    *
    * MSP430 code examples are self-contained low-level programs that typically
    * demonstrate a single peripheral function or device feature in a highly
    * concise manner. For this the code may rely on the device's power-on default
    * register values and settings such as the clock configuration and care must
    * be taken when combining code from several examples to avoid potential side
    * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
    * for an API functional library-approach to peripheral configuration.
    *
    * --/COPYRIGHT--*/
    //******************************************************************************
    // MSP430G2xx3 Demo - USCI_B0 I2C Master TX/RX multiple bytes from MSP430 Slave
    // with a repeated start in between TX and RX operations.
    //
    // Description: This demo connects two MSP430's via the I2C bus. The master
    // transmits to the slave, then a repeated start is generated followed by a
    // receive operation. This is the master code. This code demonstrates how to
    // implement an I2C repeated start with the USCI module using the USCI_B0 TX
    // interrupt.
    // ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.2MHz
    //
    // ***to be used with msp430x22x4_uscib0_i2c_13.c***
    //
    // /|\ /|\
    // MSP430F24x 10k 10k MSP430G2xx3
    // slave | | master
    // ----------------- | | -----------------
    // -|XIN P3.1/UCB0SDA|<-|---+->|P3.1/UCB0SDA XIN|-
    // | | | | |
    // -|XOUT | | | XOUT|-
    // | P3.2/UCB0SCL|<-+----->|P3.2/UCB0SCL |
    // | | | |
    //
    // D. Dang
    // Texas Instruments Inc.
    // February 2011
    // Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
    //******************************************************************************
    #include <msp430.h>

    #define NUM_BYTES_TX 1 // How many bytes?
    #define NUM_BYTES_RX 2

    int RXByteCtr, RPT_Flag = 0; // enables repeated start when 1
    volatile unsigned char RxBuffer[128]; // Allocate 128 byte of RAM
    unsigned char *PTxData; // Pointer to TX data
    unsigned char *PRxData; // Pointer to RX data
    unsigned char TXByteCtr, RX = 0;
    unsigned char MSData = 0x00;

    void Setup_TX(void);
    void Setup_RX(void);
    void Transmit(void);
    void Receive(void);

    int main(void)
    {
    //int i;
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0

    while(1){
    //for(i = 0 ; i<100000 ; i++);
    //Transmit process
    Setup_TX();
    RPT_Flag = 1;
    Transmit();
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent

    //Receive process
    Setup_RX();
    Receive();
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    }
    }

    //-------------------------------------------------------------------------------
    // The USCI_B0 data ISR is used to move received data from the I2C slave
    // to the MSP430 memory. It is structured such that it can be used to receive
    // any 2+ number of bytes by pre-loading RXByteCtr with the byte count.
    //-------------------------------------------------------------------------------
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
    if(RX == 1){ // Master Recieve?
    if (RXByteCtr)
    {
    *PRxData++ = UCB0RXBUF; // Move RX data to address PRxData
    }
    else
    {
    if(RPT_Flag == 0)
    UCB0CTL1 |= UCTXSTP; // No Repeated Start: stop condition
    if(RPT_Flag == 1){ // if Repeated Start: do nothing
    RPT_Flag = 0;
    }
    *PRxData = UCB0RXBUF; // Move final RX data to PRxData
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }
    RXByteCtr--; // Decrement RX byte counter
    }

    else{ // Master Transmit
    if (TXByteCtr) // Check TX byte counter
    {
    UCB0TXBUF = MSData++; // Load TX buffer
    TXByteCtr--; // Decrement TX byte counter
    }
    else
    {
    if(RPT_Flag == 1){
    RPT_Flag = 0;
    PTxData = &MSData; // TX array start address
    TXByteCtr = NUM_BYTES_TX; // Load TX byte counter
    __bic_SR_register_on_exit(CPUOFF);
    }
    else{
    UCB0CTL1 |= UCTXSTP; // I2C stop condition
    IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }
    }
    }

    }

    void Setup_TX(void){
    _DINT();
    RX = 0;
    IE2 &= ~UCB0RXIE;
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent// Disable RX interrupt
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x69; // Slave Address is 048h
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    IE2 |= UCB0TXIE; // Enable TX interrupt
    }
    void Setup_RX(void){
    _DINT();
    RX = 1;
    IE2 &= ~UCB0TXIE;
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x69; // Slave Address is 048h
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    IE2 |= UCB0RXIE; // Enable RX interrupt
    }
    void Transmit(void){
    PTxData = &MSData; // TX array start address
    TXByteCtr = NUM_BYTES_TX; // Load TX byte counter
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    }
    void Receive(void){
    PRxData = (unsigned char *)RxBuffer; // Start of RX buffer
    RXByteCtr = NUM_BYTES_RX-1; // Load RX byte counter
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTXSTT; // I2C start condition
     __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    }

After i connect the SDA and SCL bus to oscilloscope, i traced down the bus conditions. It seemed fine until the repeated start part. I can see the first 9 cycle correct as the slave address and ACK on the SDA bus. I can see that following 7 cycle is my correct register address 0x00. 8th cycle is ACK which is low (not sure if this is from 0x00 or ACK) but then on the 9th cycle, there is no repeated start. SDA keeps LOW status until the stop condition. Can you help me point out what is the problem here?

  • My understanding that on transmit part, UCB0TXBUF is a 8 bit register so it is trying to transmit 8 bits into the slave. But i need to send 7 bit following by a repeated start. Does this mean that i cannot use the specified state machine on g2553?

  • Well, I2C is 8 bit. Period.

    If the slave requires 7 bit only, then it isn't using I2C but something different.

    But perhaps it only means that it takes a 7-bit value  (0-127) even though the data byte transmitted is  8 bit. (MSB must be 0).

    However...

        int RXByteCtr, RPT_Flag = 0; // enables repeated start when 1

    It is 0, so no repeated start.
    You make a send, then send a stop, then init for RX (resetting the USCI) and then receive. No repeated start. What you observed on the scope is exactly what you would expect when going through the code step by step (not in the debugger, but simply on the printed source)

  • Hello and thanks for your answer in short time. 

    If you have read the datasheet that i provided for Itg3200, in the single byte reading sequence, it has been shown that after the first 7bit slave address - R/W - ACK sequence, which is general in all I2c, 7-bit register address followed with an ACK and a repeated start. Here is the figure : 

    Note that all I2c address are 7-bit long but normally followed by a R/W. 

    Another issue is that Repeated start flag in my code clearly indicates a repeated start. Even though it is 0 in the initiation, RPT_Flag = 1; after the SetupTX() meaning before the Start Condition.


    Putting all this aside, I've been checking the Adruino codes coming with this device. After i checked a fully operating bus in oscillator, i realised that they do not use a repeated start like in the sequence but a Stop-Start condition. So actually, the sequence that device use actually look like this:

    So it's quite similar to the code example msp430g2xx3_uscib0_i2c_12.c. I changed a little bit and the code came out like this:

    #include <msp430.h>

    unsigned char *PRxData; // Pointer to RX data
    unsigned char RX = 0;
    unsigned char MSData = 0x1C;

    void Setup_TX(void);
    void Setup_RX(void);
    void Transmit(void);
    void Receive(void);

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    while(1){

    //Transmit process
    Setup_TX();
    Transmit();
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent

    //Receive process
    Setup_RX();
    Receive();
    UCB0CTL1 |= UCTXSTP;
    }
    }

    //-------------------------------------------------------------------------------
    // The USCI_B0 data ISR is used to move received data from the I2C slave
    // to the MSP430 memory. It is structured such that it can be used to receive
    // any 2+ number of bytes by pre-loading RXByteCtr with the byte count.
    //-------------------------------------------------------------------------------
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
    if(RX == 1){ // Master Recieve?
    UCB0CTL1 |= UCTXSTP;
    *PRxData = UCB0RXBUF; // Move final RX data to PRxData
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }

    else{ // Master Transmit
    UCB0CTL1 |= UCTXSTP; // I2C stop condition
    IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }
    }

    void Setup_TX(void){
    _DINT();
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x69; // Slave Address is 069h
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    RX = 0; //Transmit mode
    IE2 &= ~UCB0RXIE; //Disable RX Interrupt
    IE2 |= UCB0TXIE; // Enable TX interrupt

    }
    void Setup_RX(void){
    _DINT();
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x69; // Slave Address is 069h
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    RX = 1; //Receive mode
    IE2 &= ~UCB0TXIE; //Disable TX Interrupt
    IE2 |= UCB0RXIE; // Enable RX interrupt
    }
    void Transmit(void){
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0TXBUF = MSData; // MSData into TX Buffer
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    }
    void Receive(void){
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    // UCB0CTL1 &= ~UCTR //Clearing UCTR
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    }

    I tried this code today in the lab and saw that it locks down the busses to LOW. Since i have no luxury to have a oscilloscope in my house, tomorrow i will post out the lock results as a capture from the oscilloscope. Please keep in touch because i really need to fix this. I could not really come up with a good and clear example similar to what i'm trying to obtain here. TI examples have somehow a bit high-level comments in my opinion :) Maybe this can help more people in my position.



  • Barışcan Kayaoğlu said:
    Note that all I2c address are 7-bit long but normally followed by a R/W. 

    Yes, of course. And all I2C data bytes, read or written, are 8 bit too, followed by an ACK cycle.
    No matter whether the value is 7 bit or 9 bit, there's always 8 bit an an ack being sent. And in case of the 9 bit value, a second 8 bit data wth 1 bit ACK follows.

    That's how I2C is specified.

    Yes, the register address is a 7 bit vlaue. But that only means that the MSB of the RA byte has to be blank.

    In your case, you don't want to send a stop condition when the write is done. But you also don't want to reconfigure the USCI (especially set UCSWRST) between the two transmission.

    Problem is that the demo code ensbales RXIE and TXIE isniode the SETUP funcitons - but also reset the USCI in these.

    What you'd need is to setup the USCI, enable RXIE and TXIE if you  want interrupts (in I2C mode, only one of them can ever occur, depending on UCTR, so it is safe to have both enabled) and set the repeates start flag if using these ISRs. So the TX ISR won't set UCTXSTP when al data is sent, before ending LPM.
    Then after waking from transmit, you simply call receive. No call of Setup_RX before!

  • When the datasheet point out the bit counts in the sequence that i provided, i realised that all periods are 9 bit periods. But since the register address is 7 bit and no R/W followed by, i thought that its a 8-bit period. So MSB can be 0 to make it 8-bit, thanks for making me realise that.

    Let me get this straight, So if i make an initialization with both RXIE and TXIE flags, it will work? Because i always thought that setting the TXIE flag and UCTR will give the rights to the master so that master holds the bus, preventing slaves to write anything. And for a repeated start, do i just need to set the UCTXSTT and that starts the state machine even without a stop condition?

  • Hello again.

    I'm at the school lab right now trying to accomplish what you said earlier. Here is the code that I am using:

    /* --COPYRIGHT--,BSD_EX
    * Copyright (c) 2012, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    *******************************************************************************
    *
    * MSP430 CODE EXAMPLE DISCLAIMER
    *
    * MSP430 code examples are self-contained low-level programs that typically
    * demonstrate a single peripheral function or device feature in a highly
    * concise manner. For this the code may rely on the device's power-on default
    * register values and settings such as the clock configuration and care must
    * be taken when combining code from several examples to avoid potential side
    * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
    * for an API functional library-approach to peripheral configuration.
    *
    * --/COPYRIGHT--*/
    //******************************************************************************
    // MSP430G2xx3 Demo - USCI_B0 I2C Master TX/RX multiple bytes from MSP430 Slave
    // with a repeated start in between TX and RX operations.
    //
    // Description: This demo connects two MSP430's via the I2C bus. The master
    // transmits to the slave, then a repeated start is generated followed by a
    // receive operation. This is the master code. This code demonstrates how to
    // implement an I2C repeated start with the USCI module using the USCI_B0 TX
    // interrupt.
    // ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.2MHz
    //
    // ***to be used with msp430x22x4_uscib0_i2c_13.c***
    //
    // /|\ /|\
    // MSP430F24x 10k 10k MSP430G2xx3
    // slave | | master
    // ----------------- | | -----------------
    // -|XIN P3.1/UCB0SDA|<-|---+->|P3.1/UCB0SDA XIN|-
    // | | | | |
    // -|XOUT | | | XOUT|-
    // | P3.2/UCB0SCL|<-+----->|P3.2/UCB0SCL |
    // | | | |
    //
    // D. Dang
    // Texas Instruments Inc.
    // February 2011
    // Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
    //******************************************************************************
    #include <msp430.h>


    int RXByteCtr;
    volatile unsigned char RxBuffer[128]; // Allocate 128 byte of RAM
    unsigned char *PTxData; // Pointer to TX data
    unsigned char *PRxData; // Pointer to RX data
    unsigned char TXByteCtr, Rx = 0;
    unsigned char WHO_AM_I = 0x00;

    void init_I2C(void);
    void Transmit(void);
    void Receive(void);

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    init_I2C();
    while(1){
    //Transmit process
    Rx = 0;
    UCB0TXBUF = WHO_AM_I;
    Transmit();
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent

    //Receive process
    Rx = 1;
    UCB0CTL1 &= ~UCTR ; // Clear UCTR
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    }
    }

    //-------------------------------------------------------------------------------
    // The USCI_B0 data ISR is used to move received data from the I2C slave
    // to the MSP430 memory. It is structured such that it can be used to receive
    //-------------------------------------------------------------------------------
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
    if(Rx == 1){ // Master Recieve?
    UCB0CTL1 |= UCTXSTP;
    *PRxData = UCB0RXBUF; // Move final RX data to PRxData
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }

    else{ // Master Transmit
    //UCB0CTL1 |= UCTXSTP; // I2C stop condition
    //IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }

    }

    void init_I2C(void) {
    _DINT();
    IE2 |= UCB0RXIE; //Enable RX interrupt
    IE2 |= UCB0TXIE; // Enable TX interrupt
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x69; // Slave Address is 069h
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    }

    void Transmit(void){
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    }
    void Receive(void){
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    }

     I have tried with a repeated start first, then with a stop condition between them, but the outcome rest the same. Both SCL and SDA busses locked down to 0V somehow and SDA does not ever change if i do not remove the bus and put it on again.

  • Here is another cleaner version that i combined a single read and write examples of TI, but still SDA and SCL locks down somehow.

    #include <msp430.h>


    int TXByteCtr = 1;
    unsigned char PRxData; // Pointer to RX data
    int Rx = 0;
    unsigned char WHO_AM_I = 0x00;

    void init_I2C(void);
    void Transmit(void);
    void Receive(void);

    int main(void)
    {
        WDTCTL = WDTPW + WDTHOLD; // Stop WDT
        P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
        P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
        init_I2C();
        while(1){
            //Transmit process
            Rx = 0;
            UCB0TXBUF = WHO_AM_I;
            Transmit();
            while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent

            //Receive process
            Rx = 1;
            Receive();
            while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
            }
    }

    //-------------------------------------------------------------------------------
    // The USCI_B0 data ISR is used to move received data from the I2C slave
    // to the MSP430 memory. It is structured such that it can be used to receive
    //-------------------------------------------------------------------------------
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
        if(Rx == 1){     // Master Recieve?
             PRxData = UCB0RXBUF; // Get RX data
             __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
        }

        else{     // Master Transmit
            if (TXByteCtr) // Check TX byte counter
            {
                UCB0TXBUF = WHO_AM_I; // Load TX buffer
                TXByteCtr--; // Decrement TX byte counter
            }
            else
            {
                UCB0CTL1 |= UCTXSTP; // I2C stop condition
                IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
                __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
            }
    }

    }

    void init_I2C(void) {
        _DINT();
        IE2 |= UCB0RXIE; //Enable RX interrupt
        IE2 |= UCB0TXIE; // Enable TX interrupt
        while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
        UCB0CTL1 |= UCSWRST; // Enable SW reset
        UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
        UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
        UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
        UCB0BR1 = 0;
        UCB0I2CSA = 0x69; // Slave Address is 069h
        UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    }

    void Transmit(void){
        while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
        UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
        __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    }
    void Receive(void){
        UCB0CTL1 &= ~UCTR ; // Clear UCTR
        while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
        UCB0CTL1 |= UCTXSTT; // I2C start condition
        while (UCB0CTL1 & UCTXSTT); // Start condition sent?
        UCB0CTL1 |= UCTXSTP; // I2C stop condition
        __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    }

**Attention** This is a public forum