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.

MSP430FR5969: MSP430FR5969 writing byte to Sparkfun MPU9250 with I2C problem

Part Number: MSP430FR5969

Hello TI community,

i can so far succesfully read the WHOAMI register of the MPU9250. My next step was to write a write-able register (0x6B) and then read it again to see if the write process was successful.

This is my code:

#include "driverlib.h"
#include "MPU9250_reg.h"

/* Slave address  */
#define SLAVE_ADDRESS 0x68

volatile uint8_t a =  0;
volatile uint8_t byte_counter = 0;
volatile uint8_t write_read = 0;

uint8_t transmitData;
uint8_t RXData;

void my_EUSCI_B_I2C_masterSendSingleByte (uint16_t baseAddress,
    uint8_t txData
    );
int main(void) {

    WDT_A_hold(WDT_A_BASE);


        GPIO_setAsPeripheralModuleFunctionInputPin(
            GPIO_PORT_P1,
            GPIO_PIN6 + GPIO_PIN7,
            GPIO_SECONDARY_MODULE_FUNCTION
        );

        /*
         * Disable the GPIO power-on default high-impedance mode to activate
         * previously configured port settings
         */
        PMM_unlockLPM5();
        //Enter LPM4 w/interrupt
        /* WICHTIG, NICHT VERGESSEN */
        __bis_SR_register(GIE);

        //Initialize transmit data packet
        transmitData = 0x75;

        //Initialize Master
        EUSCI_B_I2C_initMasterParam param = {0};
        param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
        param.i2cClk = CS_getSMCLK();
        param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS;
        param.byteCounterThreshold = 1;
        param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
        EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, &param);

        //Specify slave address
        EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE,
            SLAVE_ADDRESS
            );

        //Set in transmit mode
        EUSCI_B_I2C_setMode(EUSCI_B0_BASE,
            EUSCI_B_I2C_TRANSMIT_MODE
            );

        //Enable I2C Module to start operations
        EUSCI_B_I2C_enable(EUSCI_B0_BASE);

        // enable txi interrupt
        EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

        // sending
        /* start condition */
        // interrupt should be activated afterwards
        byte_counter = 1;
        write_read = 1;
        UCB0CTLW0 |= UCTXSTT;

        while(!(UCB0CTLW0 & UCBBUSY)){}

        byte_counter = 1;
        write_read = 0;
        EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
        UCB0CTLW0 |= UCTXSTT;

    while(1)
    {
        _nop();
    }
}
void my_EUSCI_B_I2C_masterSendSingleByte (uint16_t baseAddress,
    uint8_t txData
    )
{
    //Store current TXIE status
    uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE;

    //Disable transmit interrupt enable
    HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE);

    //Send start condition.
    HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT;

    //Poll for transmit interrupt flag.
    while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;

    //Send single byte data.
    HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;

    //Poll for transmit interrupt flag.
    while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;

    //Send stop condition.
    //HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;

    //Clear transmit interrupt flag before enabling interrupt again
    HWREG16(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG);

    //Reinstate transmit interrupt enable
    HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus;
}


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_B0_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(USCI_B0_VECTOR)))
#endif
void USCIB0_ISR(void)
{
    switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
    {
        case USCI_NONE:             // No interrupts break;
            break;
        case USCI_I2C_UCALIFG:      // Arbitration lost
            break;
        case USCI_I2C_UCNACKIFG:    // NAK received (master only)
            break;
        case USCI_I2C_UCSTTIFG:     // START condition detected with own address (slave mode only)
            break;
        case USCI_I2C_UCSTPIFG:     // STOP condition detected (master & slave mode)
            break;
        case USCI_I2C_UCRXIFG3:     // RXIFG3
            break;
        case USCI_I2C_UCTXIFG3:     // TXIFG3
            break;
        case USCI_I2C_UCRXIFG2:     // RXIFG2
            break;
        case USCI_I2C_UCTXIFG2:     // TXIFG2
            break;
        case USCI_I2C_UCRXIFG1:     // RXIFG1
            break;
        case USCI_I2C_UCTXIFG1:     // TXIFG1
            break;
        case USCI_I2C_UCRXIFG0:     // RXIFG0^
            // read one byte
            RXData = UCB0RXBUF;
            break;
        case USCI_I2C_UCTXIFG0:     // TXIFG0
            if(byte_counter == 1)
            {
                // send the register to read
                //UCB0TXBUF = 0x75;
                EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
                UCB0TXBUF = 0x6B;
                byte_counter--;
            }
            else if(byte_counter == 0)
            {
                if(write_read)
                {
                    // go on writing
                    EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
                    UCB0TXBUF = 0xFF;
                    // add quickly a new counter 
                    byte_counter = 100;
                }
                else
                {
                // clear and disable interrupt
                EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
                EUSCI_B_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

                //Set in receive mode
                EUSCI_B_I2C_setMode(EUSCI_B0_BASE,
                     EUSCI_B_I2C_RECEIVE_MODE
                    );

                // enable receive interrupt
                EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);

                // start condition
                UCB0CTLW0 |= UCTXSTT;

                //Poll for start condition transmission
                while(UCB0CTLW0 & UCTXSTT);

                // send stop
                UCB0CTLW0 |= UCTXSTP;
                }
            }
            else if(byte_counter == 100)
            {
                // send stop
                UCB0CTLW0 |= UCTXSTP;

                // clear and disable interrupt
                EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
                EUSCI_B_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
            }
            else
            {
                // not aloud
                while(1){}
            }
            break;
        case USCI_I2C_UCBCNTIFG:    // Byte count limit reached (UCBxTBCNT)
            break;
        case USCI_I2C_UCCLTOIFG:    // Clock low timeout - clock held low too long
            break;
        case USCI_I2C_UCBIT9IFG:    // Generated on 9th bit of a transmit (for debugging)
            break;
        default:
            break;
    }
}

first i read and than i write. However i think that the writing process doesn't work. I don't read the value i wrote and after writing the data in the writing process the UCSTPIEG flag gets set. According to the Familiy users guide on pg. 829 this means data wasn't sent. (
"If UCTXSTP is
set during the transmission of the slave address or while the eUSCI_B module waits for data to be written
into UCBxTXBUF, a STOP condition is generated, even if no data was transmitted to the slave. In this
case, the UCSTPIFG is set. ")

What do i need to change to make my code work?

Thanks in advance and best regards

  • unfortunately i can't edit my post. However there are some things i'd like to change. first

    In the end i'd like to explain the code a little.

    i read and than i write. However i think that the writing process doesn't work. I don't read the value i wrote and after writing the data in the writing process the UCSTPIEG flag gets set. According to the Familiy users guide on pg. 829  this means data wasn't sent. ("If UCTXSTP isset during the transmission of the slave address or while the eUSCI_B module waits for data to be writteninto UCBxTXBUF, a STOP condition is generated, even if no data was transmitted to the slave. In thiscase, the UCSTPIFG is set. ")What do i need to change to make my code work?Thanks in advance and best regards

    second: i want to point out that the function my_EUSCI_B_I2C_masterSendSingleByte is NOT in use and can therefore be deleted.

  • Hi,

    Thanks for using MSP430 device.

    I would like to introduction the Peripherals Example for I2C with TI driverlib to you. You could take these codes as examples to check if your code miss anything. 

  • Thank you very much for your answer. I just the code from the drivers lib to dervive this code and i think my sending process is the same as in the sendmulitbyte function beside that i use the interrupt routines. I hope  somebody can give me a hint what the problem could be :) i don't expect you to write the code for me.

  • Hi,

    Did you set the UCTXSTP on your code? As the UG described, the UCSTPIFG is set when you set the bit.

    For your issue, it seems you can't write to the slave part. I would suggest you to scope the signal line to confirm whether the master didn't send out data or the data was sent but the slave didn't get.

    You may also check the guide of your slave part for data format of writing data from I2C and follow it on your master part.

**Attention** This is a public forum