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.

  • Resolved

MSP430F5529: Problem with the code for MSP430F5529 I2C Master communication

Part Number: MSP430F5529

Hello everyone, first of all, thank you in advance for the attention and the time dispensed understanding my problem.

So, I am developing a system that includes an MSP430F5529 communicating with an AD5933 via I2C. Previously, I did the same thing with an MSP430G2553 everything went smoothly and my code worked perfectly. I did check with an oscilloscope and every data was being sent. I started with that code for my new system and did all the necessary changes, ports, interrupts, registers, from G2553 to F5529.

No matter what, my code stop in verification loops. Especially this one:

while (UCB0STAT & UCBBUSY);

When I check the bus with an oscilloscope, the SCL is always high and SDA always low. So nothing happened on the bus.

I blink a LED during the code, and that works fine.

My code is bellow, please check it and let me know if you find something wrong, or if you have some idea for me to try out.

#include <msp430.h> 

#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
    ;

    //Configuration of the slave registers (SEND DATA)
    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:
        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)
        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;

    }
}

  • Hello Gabriela,

    You never set the global interrupt enable bit (GIE of the SR register) so the USCI_B0 interrupt is never accessed. Therefore a start condition is sent but nothing else and the UCBBUSY bit is never cleared by a stop condition.

    Regards,
    Ryan

    To better aid the community, please click on the "This Resolved my issue" button whenever a post answers your question!

  • In reply to Ryan Brown1:

    Hello Ryan, thank you so much for your time.

    I added this line:

      __enable_interrupt();

    Right after the other interrupts enabling. Still the same problem, it gets stuck on the same while.

    Kind regards,

    Gabriela

  • In reply to Gabriela Costa:

    The first or second while loop? Is the stop condition ever sent from case 12 of the IFG? Some further interrupt debugging is required.

    Regards,
    Ryan

    To better aid the community, please click on the "This Resolved my issue" button whenever a post answers your question!

  • In reply to Ryan Brown1:

    The first one, the code doesn't go any further.
    I really don't know if the stop condition is sent. It should since the interrupt is enabled, right? How can I check it?
    Through the oscilloscope, I can't see anything, the SCL always high and the SDA always low.

  • In reply to Gabriela Costa:

    If it doesn't get farther then the first while loop then you haven't even intentionally sent the start condition yet, in which case this sounds like a hardware issue keeping the SDA line low.

    Regards,
    Ryan

    To better aid the community, please click on the "This Resolved my issue" button whenever a post answers your question!

  • In reply to Ryan Brown1:

    Thank you so much Ryan! I found out that if when I stop my code I unplug the USB and plug again, the data is send. And I can see the bus on oscilloscope. So it's working now!
  • In reply to Ryan Brown1:

    I have just one more question. Why isn't need in G2553 that line enabling the global interrupts?
  • In reply to Gabriela Costa:

    It is required to set the GIE in the MSP430G2553 as well.

    Regards,
    Ryan

    To better aid the community, please click on the "This Resolved my issue" button whenever a post answers your question!

  • In reply to Ryan Brown1:

    But I didn't do it in the G5223 system. And it works really well. That's why it was so hard understood what was wrong with this one (the F5529 system).

    In G5223 system I just initialize:

    	UCB0I2CIE = UCNACKIE;
    	IE2 = UCB0TXIE;                            // Enable TX ready interrupt

    Or:

    	UCB0I2CIE = UCNACKIE;
    	IE2 = UCB0RXIE;                            // Enable RX interrupt

    If you know some reason why that could happen, please let me know.

    Anyway thank you so much, my system now works. I was really frustrated! You saved my life :)

    Kind regards,

    Gabriela

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.