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.

MSP430FR2433: I2C code from Walter Schurr does not work.

Part Number: MSP430FR2433
Other Parts Discussed in Thread: MSP-EXP430FR2433, MSP430F5329

//=======================================================================

#include "msp430.h"
#include "driverlib.h"

#define DCOFREQ 8000000

#define I2C_0_BASE (EUSCI_B0_BASE)
#define I2C_RECEIVE_BUFFER_SIZE (32)

uint8_t I2C_0_rxBuffer[I2C_RECEIVE_BUFFER_SIZE];
int8_t I2C_0_rxBytesRemaining = 0;
int8_t I2C_0_rxCnt = 0;

void setup(void)
{
    EUSCI_B_I2C_initMasterParam I2C_0;

    // SMCLK = MCLK = DCO = 4MHz
    // ACL = 32kHz
    CS_initClockSignal(CS_FLLREF, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initClockSignal(CS_MCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initClockSignal(CS_SMCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initFLL((DCOFREQ/1000), DCOFREQ/32768);
    CS_clearAllOscFlagsWithTimeout(1000);

    // I2C port mux selection
    P1OUT = 0;
    P1DIR |= BIT0 | BIT1 | BIT4 | BIT5 | BIT6;
    P1SEL0 |= BIT2 | BIT3;
    PM5CTL0 &= ~LOCKLPM5;

    // I2C Setup
    I2C_0.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
    I2C_0.i2cClk = DCOFREQ;
    I2C_0.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;
    I2C_0.byteCounterThreshold = 0;
    I2C_0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;

    EUSCI_B_I2C_disable(I2C_0_BASE);
    EUSCI_B_I2C_initMaster(I2C_0_BASE, &I2C_0);
    EUSCI_B_I2C_enable(I2C_0_BASE);

    __delay_cycles(8000000);
}

uint8_t I2C_0_readCmd(uint8_t slave, uint8_t cmd)
{
    P1OUT |= BIT0 | BIT4 | BIT5 | BIT6;

    // Set slave address and wait for bus
    EUSCI_B_I2C_setSlaveAddress(I2C_0_BASE, slave);
    EUSCI_B_I2C_clearInterrupt(I2C_0_BASE,
                EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
                EUSCI_B_I2C_TRANSMIT_INTERRUPT0 |\
                EUSCI_B_I2C_STOP_INTERRUPT );
    EUSCI_B_I2C_enableInterrupt(I2C_0_BASE,
                EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
                EUSCI_B_I2C_STOP_INTERRUPT );
    I2C_0_rxBytesRemaining = 0;

    // Write command to slave
    EUSCI_B_I2C_setMode(I2C_0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
    EUSCI_B_I2C_masterSendMultiByteStart(I2C_0_BASE, cmd);
    while(!(EUSCI_B_I2C_getInterruptStatus(I2C_0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)))
    {
        if (EUSCI_B_I2C_getInterruptStatus(I2C_0_BASE, EUSCI_B_I2C_NAK_INTERRUPT))
        {

            return 0;
        }
    }

    // Read response from slave
    EUSCI_B_I2C_masterReceiveStart(I2C_0_BASE);
    while (EUSCI_B_I2C_isBusBusy(I2C_0_BASE));
    EUSCI_B_I2C_disableInterrupt(I2C_0_BASE,
                EUSCI_B_I2C_RECEIVE_INTERRUPT0 |\
                EUSCI_B_I2C_STOP_INTERRUPT );

    P1OUT &= ~BIT0;
    return I2C_0_rxCnt;
}

void run(void)
{
    I2C_0_readCmd(0x0B, 0x02);
    __no_operation();
    __delay_cycles(1000000);
}

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;
    __enable_interrupt();
    setup();
    while(1)
    {
        run();
    }
}

#pragma vector=USCI_B0_VECTOR
__interrupt void I2C_0_ISR(void)
{
    uint8_t data;

    P1OUT |= BIT1;
    switch(__even_in_range(UCB0IV,0x1E))
    {
        case 0x00: break;       // Vector 0: No interrupts break;
        case 0x02: break;       // Vector 2: ALIFG break;
        case 0x04: break;       // Vector 4: NACKIFG break;
        case 0x06: break;       // Vector 6: STT IFG break;
        case 0x08:
            P1OUT &= ~BIT5;
            break;       // Vector 8: STPIFG break;
        case 0x0a: break;       // Vector 10: RXIFG3 break;
        case 0x0c: break;       // Vector 14: TXIFG3 break;
        case 0x0e: break;       // Vector 16: RXIFG2 break;
        case 0x10: break;       // Vector 18: TXIFG2 break;
        case 0x12: break;       // Vector 20: RXIFG1 break;
        case 0x14: break;       // Vector 22: TXIFG1 break;
        case 0x16:              // Vector 24: RXIFG0 break;
            // Receive byte
            data = EUSCI_B_I2C_masterReceiveMultiByteNext(I2C_0_BASE);

            // If this is the first byte (RX Length Invalid), then save the length to read
            // and reset the receive counter to 0
            if (I2C_0_rxBytesRemaining == 0x00)
            {
                I2C_0_rxBytesRemaining = data;
                if (I2C_0_rxBytesRemaining > I2C_RECEIVE_BUFFER_SIZE)
                {
                    I2C_0_rxBytesRemaining = I2C_RECEIVE_BUFFER_SIZE;
                }
                I2C_0_rxCnt = 0;
            }

            // If this is not the first byte, append the response to the RX
            // buffer
            else
            {
                I2C_0_rxBuffer[I2C_0_rxCnt++] = data;
                I2C_0_rxBytesRemaining--;
            }

            // Send NACK and STOP on last byte coming in
            if (I2C_0_rxBytesRemaining == 1)
            {
                P1OUT &= ~BIT4;
                EUSCI_B_I2C_masterReceiveMultiByteStop(I2C_0_BASE);
            }
            break;
        case 0x18: break;       // Vector 26: TXIFG0 break;
        case 0x1a: break;       // Vector 28: BCNTIFG break;
        case 0x1c: break;       // Vector 30: clock low timeout break;
        case 0x1e: break;       // Vector 32: 9th bit break;
        default: break;
    }

    P1OUT &= ~BIT1;
}


I got this code from Walter in the "MSP430F5329: How do you send a NAK in I2C SMBus Protocol

post. 

I thought I understood it and used it to write my code. I was not getting any SDA or SCL pin movement in my code. So I decided to start with Walter's "working code" and slowly migrate to my application. 

In the main routine

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;
    __enable_interrupt();
    setup();
    while(1)
    {
        run();
    }
}

I compile no warnings or errors. 

When I single step it appears to go out of control just after the __enable_Interrupt(); when I try to step into the setup(); . 

The Disassembly looks like a valid call to #setup

But it jumped to 00C400 __program_start



Why would it do that?

Is this a watchdog timer? Or another interrupt not handled? 

I am confused. I am using the MSP-EXP430FR2433 with the IAR compiler. 

Thanks,

Kip

**Attention** This is a public forum