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.

Problem with I2C communication between MSP430F5529 and AD5933

Part Number: MSP430F5529
Other Parts Discussed in Thread: MSP430G2553, MSP-FET
#define SLAVE_ADDRESS 0x0D /**< Address to AD5933. */
#define BAUD_RATE 12 /**< Baud Rate value. */
#define SDA_PIN 0x00                                    // msp430F5529 UCB0SDA pin
#define SCL_PIN 0x01                                    // msp430F5529 UCB0SCL pin

P1DIR |= BIT1;
P1OUT |= BIT1;
P1OUT ^= (BIT1);   //turn on LED (is turned off when all data for initialization was send)

P3REN |= SDA_PIN + SCL_PIN;
P3OUT |= SDA_PIN + SCL_PIN;
P3SEL |= SDA_PIN + SCL_PIN;                 // Assign I2C pins to USCI_B0

UCB0CTL1 |= UCSWRST;                        // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST;              // Use SMCLK, keep SW reset
UCB0BR0 = BAUD_RATE;                        // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = SLAVE_ADDRESS;                  // Set slave address
UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
//UCB0IE = UCNACKIE;	//tried with and without this line, there isn't a difference
UCB0IE |= UCTXIE;                           // Enable TX ready interrupt

P1OUT ^= (BIT1);   //turn off LED

while (UCB0STAT & UCBBUSY)
    ;

That is my code. I know that my board works because the LED blinks fine, but I always get stuck in that last while loop.

This code is adapted from MSP430G2553 communication with AD5933 as well, where it worked fine. I did all the necessary ports and pins changes according to the datasheet.

One other difference between this and the other system is that now I am using a MSP-FET Flash Emulation Tool plus a micro UBS to power,  instead of the mini USB port. But I don't know how this may or may not affect my code.

It seems that the STAT of the MSP never changes and the communication isn't established. Can someone help me with it? I don't know what is wrong with my initialization. Maybe the problem is with the interrupts? What should I do?

Thank you all in advance for trying to help me.

  • Hello Gabriela,

    Please see the following application note for debugging I2C issues. Solutions to Common eUSCI and USCI Serial Communication Issues on MSP430 MCUs

    I would also suggest starting from one of our I2C code examples. From your code above a few things are amiss. First, you enable the TX interrupt, but do not have an ISR. This means you will jump to a trap ISR and do nothing. It also means you are not filling the TXBUFF so nothing is sent on the I2C lines. In addition, If you ever do break out of your while statement, your program will end and do nothing else. This means you would send one byte and then do nothing. You need an application loop [while(1)] to ensure the device keeps performing.

    For other I2C debug efforts, please see the application report linked to above.

  • Thank you a lot! I checked that AP and I already have tried these solutions they didn't work. The code jumped into a trap ISR sometimes, but just if I delete that while and continue running my code. I don't understand why didn't it happen in MSP430G2553? I wasn't aware of ISR, although I couldn't correct that despite all my efforts.

    I found the I2C code examples but I can't run them either, it gets stuck in:

    __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0, enable interrupts

    I tried to adapt those examples to my code, but I didn't succeed so I try to run the examples for itself they didn't work.

    http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP-EXP430F5529LP/latest/index_FDS.html

    I pick the examples from here, the windows version and the I2C, then I selected the ones that said "This is the MASTER CODE.", for read or write one or multiple bytes.


    My code actually continues, I send the start bit and read data, etc. I just past the code before the loop where it stops. If I solve it there the rest of it should work fine since it worked in MSP43G2553 system.

    I hope you can help me with it, this is my master's project and I am behind the deadline with all those stepbacks.

    Thank you so much for your time!

    Kind regards,

    Gabriela

  • Hello! Could someone help me with this?

  • You are not initializing the ports correctly. The built-in pull-up resistors are too weak for 100 kHz, and the SDA_PIN/SCL_PIN values are wrong (they must use BITx).
  • Why aren't the ports correct?  What is missing or wrong? Can you please be more specific?
    About the SDA_PIN/SCL_PIN, they are carrect for P3.0 and 3.1 (BIT0/BIT1 = 0x00 / 0x01).

  • msp430‍f5529.h uses alternative facts:

    #define BIT0                   (0x0001)
    #define BIT1                   (0x0002)
    #define BIT2                   (0x0004)
    ...
  • Also, how do you know that pull-up resistors are too weak for kHz?
    My pull-up resistors are 4.7kOhm each.
    Maybe I have the baud rate wrong, can you tell me how it should be calculated?
  • The internal pull-up resistors are much larger than 4.7 kΩ. If you have external ones, you do not need to enable the internal ones in PxREN.

    The I²C clock frequency is calculated by dividing the clock source's frequency by the divisor value.
  • Oh right! Thank you :) I changed it, but it didn't solve my problem.
    I am going directly to an ISR trap or the (UCB0STAT & UCBBUSY) is always 0.
  • As Jace already told you, you get an interrupt because you enabled the interrupt.

    Start with a super-simple program that does nothing but doing a one-byte I²C transaction.

  • Ah ok, I remove that line. Although, the problem continues :/
  • What problem? That you get into an ISR trap?
  • Yes, I understand. He said: "First, you enable the TX interrupt, but do not have an ISR."

    Can you explain to me how should I do an ISR? I am not familiar with it, I already searched but I don't understand how should be done.

    The problem is that UCB0STAT & UCBBUSY is always 0 no matter what. Which means that the communication isn't established. Sometimes I get in an ISR trap, but the most common is that.

    Thank you so much for trying to help me!

  • Do you actually need an ISR? How did you do this with the G2553? (All I²C example programs have ISRs.)

    UCBBUSY is set between the start and the stop condition. The code you've shown never sends a start condition, so of course the I²C module is never busy.
  • In G2553 system I did it that same way and it worked perfectly. I didn't use any ISR.
    I send the start condition after that, to send data and receive. Just like in the G2553 system. I made the adjustments from G2553 to F5529.
    The only thing that I found most different between them was the interrupts:
    According to each one of the User's Guide in I2C mode: The G2553 have two interrupt vectors, one associated with the transmit and receive interrupt flags and the other with the four state change interrupt flags, for the USCI module in I2C mode. And the F5529 has only one interrupt vector shared for transmission, reception and the state change.
    I thing the problem is with that, because I didn't made any change relative to it. Can you please tell me if the problem can be because of that? If so, how can I try to solve this?
    Thank you so much for all of your patience and comprehension about my problem.
  • Did "the same way" include enabling the interrupt?
    Anyway, if you do not use interrupts, it does not matter what their vectors might be.

    Well, if the code you have shown works, and if you have a problem with some other code that you are executing afterwards, it might be helpful to show that other code.
  • The problem is with that code because I can't proceed any further.

    My initialization code for G2553, that worked:

    P1SEL |= SDA_PIN + SCL_PIN;                 // Assign I2C pins to USCI_B0
    P1SEL2 |= SDA_PIN + SCL_PIN;                 // Assign I2C pins to USCI_B0
    
    UCB0CTL1 = UCSWRST;                        // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST;              // Use SMCLK, keep SW reset
    UCB0BR0 = prescale;                         // set prescaler
    UCB0BR1 = 0;
    UCB0I2CSA = slave_address;                  // Set slave address
    UCB0CTL1 &= ~UCSWRST;                    // Clear SW reset, resume operation
    UCB0I2CIE = UCNACKIE;
    IE2 = UCB0TXIE;                            // Enable TX ready interrupt
    
    while (UCB0STAT & UCBBUSY)
        ;

    The prescale was 0x12 and  SDA_PIN 0x80, SCL_PIN 0x40. But it also includes the enabling of the interrupt.

  • I do have interrupts, sorry about my mistake. Here it is the code of them bellow.

    #pragma vector = USCIAB0RX_VECTOR
    __interrupt void USCIAB0RX_ISR(void) {
    	if (UCB0STAT & UCNACKIFG) {            // send STOP if slave sends NACK
    		UCB0CTL1 |= UCTXSTP;
    		UCB0STAT &= ~UCNACKIFG;
    	}
    
    }
    
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void) {
    	if (UCB0IFG & UCRXIFG) {
    		if (byteCtr == 0) {
    			UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
    			*TI_receive_field = UCB0RXBUF;
    			TI_receive_field++;
    		} else {
    			*TI_receive_field = UCB0RXBUF;
    			TI_receive_field++;
    			byteCtr--;
    		}
    	} else {
    		if (byteCtr == 0) {
    			UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
    			UCB0IFG &= ~UCRXIFG;                 // Clear USCI_B0 TX int flag
    		} else {
    			UCB0TXBUF = *TI_transmit_field;
    			TI_transmit_field++;
    			byteCtr--;
    		}
    	}
    }

    But they have both a warning: "#2580-D pragma vector= accepts numeric arguments or "unused_interrupts" but not USCIAB0RX_VECTOR "


  • Why didn't you tell us previously that the compiler complained about that code?

    On the F5529, the USCI B0 module has a single interrupt vector. The easiest way to check the interrupt source is the interrupt vector register:

    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_interrupt(void)
    {
        switch (UCB0IV) {
        case USCI_I2C_UCNACKIFG:
            ...
            break;
        case USCI_I2C_UCRXIFG:
            ...
            break;
        case USCI_I2C_UCTXIFG:
            ...
            break;
        default:
            break;
        }
    }

    (Please note that reading UCB0IV automatically clears the corresponding interrupt flag.)

  • Thank you so much! I think that will solve the problem. I changed the ISR to this:

    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
        switch (__even_in_range(UCB0IV, 12))
        {
        case 0:
            break;                           // Vector  0: No interrupts
        case 2:
            break;                           // Vector  2: ALIFG
        case 4:
            UCB0CTL1 |= UCTXSTP;
            UCB0IFG &= ~UCNACKIFG;
            break;                           // Vector  4: NACKIFG
        case 6:
            break;                           // Vector  6: STTIFG
        case 8:
            break;                           // Vector  8: STPIFG
        case 10:                                  // Vector 10: RXIFG
            if (byteCtr == 0)
            {
                UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
                *TI_receive_field = UCB0RXBUF;
                TI_receive_field++;
            }
            else
            {
                *TI_receive_field = UCB0RXBUF;
                TI_receive_field++;
                byteCtr--;
            }
            break;
        case 12:                                     // Vector 12: TXIFG
            if (byteCtr == 0)
            {
                UCB0CTL1 |= UCTXSTP;                 // I2C stop condition
                UCB0IFG &= ~UCRXIFG;                 // Clear USCI_B0 TX int flag
            }
            else
            {
                UCB0TXBUF = *TI_transmit_field;
                TI_transmit_field++;
                byteCtr--;
            }
            break;
        default:
            break;
    
        }
    }
    

    Since I adjust the interrupt with the code above, the confirmation of the presence of the slave doesn't happen. The function bellow never gets true, what means the interrupt is pending. How can I correct that?

    unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address) {
        unsigned char ie2_bak, slaveadr_bak, ucb0i2cie, returnValue;
        ucb0i2cie = UCB0IE;                      // restore old UCB0IE
        ie2_bak = UCB0IE;                              // store IE2 register
        slaveadr_bak = UCB0I2CSA;                   // store old slave address
        UCB0IE &= ~ UCNACKIE;                    // no NACK interrupt
        UCB0I2CSA = slave_address;                  // set slave address
        UCB0IE &= ~(UCTXIE + UCRXIE);              // no RX or TX interrupts
        __disable_interrupt();
        UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP;       // I2C TX, start condition
        while (UCB0CTL1 & UCTXSTP)
            ;                 // wait for STOP condition
    
        returnValue = !(UCB0IFG & UCNACKIFG);
        __enable_interrupt();
        UCB0IE = ie2_bak;                              // restore IE2
        UCB0I2CSA = slaveadr_bak;                   // restore old slave address
        UCB0IE = ucb0i2cie;                      // restore old UCB0CTL1
        return returnValue;                         // return whether or not
                                                    // a NACK occured
    }

  • What happens on the bus when you look at if with an oscilloscope or logic analyzer?
  • I will check with the oscilloscope.

    It shows a warning now "#238-D controlling expression is constant " in the line: which means that no interrupt is done, they are always pending.

        while(TI_USCI_I2C_slave_present);

    Regarding the function code I posted before. Which means that no interrupt is created/done, they are always pending.

  • To call the function, add parantheses:

    while (TI_USCI_I2C_slave_present())
       ;

    In C, a function name without parantheses is just the address of the function.

  • Oh right! And I need to send the SLAVE_ADDRESS as well. I did it, now it get stuck in that while, the STOP condition isn't send.

    unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address) {
        unsigned char ie2_bak, slaveadr_bak, ucb0i2cie, returnValue;
    
        ucb0i2cie = UCB0IE;                      // restore old UCB0IE
        ie2_bak = UCB0IE;                              // store IE2 register
        slaveadr_bak = UCB0I2CSA;                   // store old slave address
        UCB0IE &= ~ UCNACKIE;                    // no NACK interrupt
        UCB0I2CSA = slave_address;                  // set slave address
        UCB0IE &= ~(UCTXIE + UCRXIE);              // no RX or TX interrupts
        __disable_interrupt();
        UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP;       // I2C TX, start condition
        while (UCB0CTL1 & UCTXSTP)
            ;                 // wait for STOP condition
    
        returnValue = !(UCB0IFG & UCNACKIFG);
        __enable_interrupt();
        UCB0IE = ie2_bak;                              // restore IE2
        UCB0I2CSA = slaveadr_bak;                   // restore old slave address
        UCB0IE = ucb0i2cie;                      // restore old UCB0CTL1
        return returnValue;                         // return whether or not
                                                    // a NACK occured
    }

  • Also, if I delete that verification. The initial problem continues:

    while (UCB0STAT & UCBBUSY)
            ;

    Gets stuck here forever. The STAT doesn't change.

    I will check what happen in oscilloscope and then I back to you.

    Thank you so so much for all of your effort to help me with this!

  • One more thing, I tried to run one of the code examples, and the one attached works! I just changed the slave address. Although I can't understand the why. Could you check it, please?

    Sorry for bothering you so much. But I am really grateful for all the attention and patience with my problem. I really need that my code works asap.

    Thank you do much.

    0257.MSP430F55xx_uscib0_i2c_04.c
    /* --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--*/
    //******************************************************************************
    //  MSP430F552x Demo - USCI_B0 I2C Master RX single bytes from MSP430 Slave
    //
    //  Description: This demo connects two MSP430's via the I2C bus. The master
    //  reads from the slave. This is the MASTER CODE. The data from the slave
    //  transmitter begins at 0 and increments with each transfer. The received
    //  data is in R5 and is checked for validity. If the received data is
    //  incorrect, the CPU is trapped and the P1.0 LED will stay on. The USCI_B0
    //  RX interrupt is used to know when new data has been received.
    //  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz
    //
    // ***to be used with "MSP430F55xx_uscib0_i2c_05.c" ***
    //
    //                                /|\  /|\
    //               MSP430F5529      10k  10k     MSP430F5529
    //                   slave         |    |        master
    //             -----------------   |    |   -----------------
    //           -|XIN  P3.0/UCB0SDA|<-|----+->|P3.0/UCB0SDA  XIN|-
    //            |                 |  |       |                 | 32kHz
    //           -|XOUT             |  |       |             XOUT|-
    //            |     P3.1/UCB0SCL|<-+------>|P3.1/UCB0SCL     |
    //            |                 |          |             P1.0|--> LED
    //
    //   Bhargavi Nisarga
    //   Texas Instruments Inc.
    //   April 2009
    //   Built with CCSv4 and IAR Embedded Workbench Version: 4.21
    //******************************************************************************
    
    #include <msp430.h>
    
    unsigned char RXData;
    unsigned char RXCompare;
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      P1OUT &= ~0x01;                           // P1.0 = 0
      P1DIR |= 0x01;                            // P1.0 output
      P3SEL |= 0x03;                            // Assign I2C pins to USCI_B0
      UCB0CTL1 |= UCSWRST;                      // Enable SW reset
      UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
      UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK
      UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
      UCB0BR1 = 0;
      UCB0I2CSA = 0x48;                         // Slave Address is 048h
      UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
      UCB0IE |= UCRXIE;                         // Enable RX interrupt
      RXCompare = 0x0;                          // Used to check incoming data
    
      while (1)
      {
        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(LPM0_bits + GIE);     // Enter LPM0, enable interrupts
        __no_operation();                       // For debugger
      
        if (RXData != RXCompare)                // Trap CPU if wrong
        {
          P1OUT |= 0x01;                        // P1.0 = 1
          while(1);
        }
    
        RXCompare++;                            // Increment correct RX value
      }
    }
    
    // USCI_B0 Data ISR
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB0IV,12))
      {
      case  0: break;                           // Vector  0: No interrupts
      case  2: break;                           // Vector  2: ALIFG
      case  4: break;                           // Vector  4: NACKIFG
      case  6: break;                           // Vector  6: STTIFG
      case  8: break;                           // Vector  8: STPIFG
      case 10:                                  // Vector 10: RXIFG
        RXData = UCB0RXBUF;                     // Get RX data
        __bic_SR_register_on_exit(LPM0_bits);   // Exit active CPU
        break;
      case 12: break;                           // Vector 12: TXIFG
      default: break; 
      }
    }
    
    
    

  • Is that ICBBUSY check the one shown in your first post, or some other one?
  • Yes, it's the same of the initial post.
  • My whole code is shown bellow. The highlighted line is where it stops. Can you see something wrong with it?

    #include <msp430.h> 
    
    /*
     * main.c
     */
    
    #define SLAVE_ADDRESS 0x0D /**< Address to AD5933. */
    #define BAUD_RATE 0x12 /**< Baud Rate value. */
    #define SDA_PIN BIT0                                    // msp430F5529 UCB0SDA pin
    #define SCL_PIN BIT1                                    // msp430F5529 UCB0SCL pin
    signed char byteCtr;
    unsigned char *TI_transmit_field;
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
        P3OUT |= SDA_PIN + SCL_PIN;
        P3SEL |= SDA_PIN + SCL_PIN;                 // Assign I2C pins to USCI_B0
    
        //P1SEL |= BIT1;
        //P1OUT &= ~BIT1; //piscar led
    
        UCB0CTL1 |= UCSWRST;                        // Enable SW reset
        UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // I2C Master, synchronous mode
        UCB0CTL1 = UCSSEL_2 + UCSWRST;              // Use SMCLK, keep SW reset
        UCB0BR0 = BAUD_RATE;                         // set prescaler
        UCB0BR1 = 0;
        UCB0I2CSA = SLAVE_ADDRESS;                  // Set slave address
        UCB0CTL1 &= ~UCSWRST;                    // Clear SW reset, resume operation
        UCB0IE = UCNACKIE;
        UCB0IE |= UCTXIE;                           // Enable interrupts
        UCB0IE |= UCRXIE;
    
        while (UCB0STAT & UCBBUSY)
            ;
    
    
        unsigned char field[2] = { 0x80, 0xB1 };
        TI_transmit_field = field;
        byteCtr = 2;
        UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
        while (UCB0STAT & UCBBUSY)
            ;
    
        while (1)
            ;
    }
    
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
        switch (__even_in_range(UCB0IV, 12))
        {
        case 0:
            break;                           // Vector  0: No interrupts
        case 2:
            break;                           // Vector  2: ALIFG
        case 4:
            UCB0CTL1 |= UCTXSTP;
            UCB0IFG &= ~UCNACKIFG;
            break;                           // Vector  4: NACKIFG
        case 6:
            break;                           // Vector  6: STTIFG
        case 8:
            break;                           // Vector  8: STPIFG
        case 10:                                  // Vector 10: RXIFG
    
        case 12:                                     // Vector 12: TXIFG
            if (byteCtr == 0)
            {
                UCB0CTL1 |= UCTXSTP;                 // I2C stop condition
                UCB0IFG &= ~UCRXIFG;                 // Clear USCI_B0 TX int flag
            }
            else
            {
                UCB0TXBUF = *TI_transmit_field;
                TI_transmit_field++;
                byteCtr--;
            }
            break;
        default:
            break;
    
        }
    }
    

  • Directly after initialization, the TX buffer is empty, so TXIFG is set. You are enabling TXIE, so the interrupt handler is run immediately, and it sets TXSTP. This is not allowed without a start.

    You should set TXIE only when you actually are ready to send.
  • I checked the bus with an oscilloscope with the same I used with G2553, menu options for the channels.
    Unfurtunately, no changes happened. The SDA always low and SCL always high.
    What do you suggest I do now?
    This can't be more frustrating!
  • That makes a lot of sense, thank you.
    Although, I tried commenting the "UCB0IE |= UCRXIE;" line, and then also "UCB0IE = UCNACKIE;", and the result is the same.
  • The difference is that, immediately after initialization, there is no received data, and no NACK happened, so the interrupt does not get called for those reasons.
  • Where should I put the "UCB0IE |= UCTXIE;" line? Please check my code bellow.

    Note that if I comment the first "while (UCB0STAT & UCBBUSY)" it stops on the other one.

    #include <msp430.h> 
    
    /*
     * main.c
     */
    
    #define SLAVE_ADDRESS 0x0D /**< Address to AD5933. */
    #define BAUD_RATE 0x12 /**< Baud Rate value. */
    #define SDA_PIN BIT0                                    // msp430F5529 UCB0SDA pin
    #define SCL_PIN BIT1                                    // msp430F5529 UCB0SCL pin
    
    signed char byteCtr;
    unsigned char *TI_transmit_field;
    unsigned char *TI_receive_field;
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;	                // Stop watchdog timer
    
        //LED configurations
        P1DIR |= BIT1;
        P1OUT |= BIT1;
        P1OUT ^= (BIT1);   //turn on LED
    
        //MSP configurations to transmit
        P3SEL |= SDA_PIN + SCL_PIN;                 // Assign I2C pins to USCI_B0
    
        UCB0CTL1 |= UCSWRST;                        // Enable SW reset
        UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // I2C Master, synchronous mode
        UCB0CTL1 = UCSSEL_2 + UCSWRST;              // Use SMCLK, keep SW reset
        UCB0BR0 = BAUD_RATE;                         // set prescaler
        UCB0BR1 = 0;
        UCB0I2CSA = SLAVE_ADDRESS;                  // Set slave address
        UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
        UCB0IE = UCNACKIE;
        UCB0IE |= UCTXIE;                           // Enable interrupts
    
        P1OUT ^= (BIT1);                            //turn off LED
        while (UCB0STAT & UCBBUSY)                  //wait for previous traffic to clear
        ;
    
        //Starting the configuration of the slave registers
        unsigned char field[2] = { 0x80, 0xB1 };
        TI_transmit_field = field;
        byteCtr = 2;
        UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
        while (UCB0STAT & UCBBUSY)
            ;
    
        while (1)
            ;
    }
    
    //INTERRUPTS
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
        switch (__even_in_range(UCB0IV, 12))
        {
        case 0:
            break;                           // Vector  0: No interrupts
        case 2:
            break;                           // Vector  2: ALIFG
        case 4:
            if (UCB0IFG & UCNACKIFG)         // send STOP if slave sends NACK
            {
                UCB0CTL1 |= UCTXSTP;
                UCB0IFG &= ~UCNACKIFG;
            }
            break;                           // Vector  4: NACKIFG
        case 6:
            break;                           // Vector  6: STTIFG
        case 8:
            break;                           // Vector  8: STPIFG
        case 10:                                  // Vector 10: RXIFG -- I am not using it yet (but I'll need it)
            if (byteCtr == 0)
            {
                UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
                *TI_receive_field = UCB0RXBUF;
                TI_receive_field++;
            }
            else
            {
                *TI_receive_field = UCB0RXBUF;
                TI_receive_field++;
                byteCtr--;
            }
            break;
        case 12:                                     // Vector 12: TXIFG
            if (byteCtr == 0)
            {
                UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
                UCB0IFG &= ~UCTXIFG;                 // Clear USCI TX int flag
            }
            else
            {
                UCB0TXBUF = *TI_transmit_field;
                TI_transmit_field++;
                byteCtr--;
            }
            break;
        default:
            break;
    
        }
    }
    
    
    

  • You should REMOVE it.

    Put it where you want the first TX interrupt to happen, i.e., directly after setting TXSTT.
  • As you can see bellow (and in the complete code above) I have that same line right after the STT, however, even when I comment the first while (the one I should remove, I understood) it gets stuck in that one, right after STT.

    Please, check the code above again and ignore that first highlighted while.

        UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
        while (UCB0STAT & UCBBUSY)
            ;

  • I am talking about the line that sets TXIE.
  • Oh I see. I tried it too, the same happened, stoped in the loop.

        WDTCTL = WDTPW | WDTHOLD;	                // Stop watchdog timer
    
        //LED configurations
        P1DIR |= BIT1;
        P1OUT |= BIT1;
        P1OUT ^= (BIT1);   //turn on LED
    
        //MSP configurations to transmit
        P3SEL |= SDA_PIN + SCL_PIN;                 // Assign I2C pins to USCI_B0
    
        UCB0CTL1 |= UCSWRST;                        // Enable SW reset
        UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // I2C Master, synchronous mode
        UCB0CTL1 = UCSSEL_2 + UCSWRST;              // Use SMCLK, keep SW reset
        UCB0BR0 = BAUD_RATE;                         // set prescaler
        UCB0BR1 = 0;
        UCB0I2CSA = SLAVE_ADDRESS;                  // Set slave address
        UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
        UCB0IE = UCNACKIE;
        //UCB0IE |= UCTXIE;                           // Enable interrupts
    
        P1OUT ^= (BIT1);                            //turn off LED
        //while (UCB0STAT & UCBBUSY)                  //wait for previous traffic to clear
        //;
    
        //Starting the configuration of the slave registers
        unsigned char field[2] = { 0x80, 0xB1 };
        TI_transmit_field = field;
        byteCtr = 2;
        UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
        UCB0IE |= UCTXIE;
        while (UCB0STAT & UCBBUSY)
            ;
    
        while (1)
            ;

  • The solution was enabling the global interrupts in the initialization.

    I used that line:

    __enable_interrupt();

    Thank you all who tried so hard to help me.

    The best regards,

    Gabriela

**Attention** This is a public forum