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.

MSP430FR5739 I2C Master problem, Missing bit7.

Other Parts Discussed in Thread: MSP-EXP430FR5739

Hi All,

When I use the I2C master demo "eusci_b_i2c_ex4_masterTxSingle", the demo failed at EUSCI_B_I2C_masterSendSingleByte.

When I set the slave address to 0x81, and check the wave from scope, I find that bit7 is lost.

 When I set the slave address to 0xAA, I find that bit7 is also lost.

Whatever I set to bit7 of slave address, it is lost.

And then, the UCNACKIFG is set.

So only bit6~bit0 is sent.

I'm using the "MSP-EXP430FR5739 FRAM Experimenter Board" from TI.

And I add 10K resistor to both SCL(Port1 Pin7) and SDA(Port1 Pin6).

Could anyone help me out with the case?

  • Lee Knight said:
    When I set the slave address to 0x81, and check the wave from scope, I find that bit7 is lost.

    0x81 is obviously an 8 bit value. But the slave address is a 7 bit value.

    Apparently you're trying to use the supposed I2C start byte as slave address. Which is wrong. Only use the 7 bit slave address. The USCI will add the LSB (R/W bit) automatically, based on the UCTR bit in USBxCTL1 when generating start condition und start byte.

  • Hi!

    I am having the same problem! My address is 0x1E and the 'EUSCI_B_I2C_masterSendSingleByte()' stucks at instruction 'while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG))' and I dont know why!

    Any thougths?

    Regards,

    AS

  • Hi!

    I am having the same problem! My address is 0x1E and the 'EUSCI_B_I2C_masterSendSingleByte()' stucks at instruction 'while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG))' and I dont know why!

    Any thougths?

    Regards,

    AS

  • The while is expecting that the slave has answered to the start condition. If it didn’t, the code will wait forever.
    When using this function, you should first test whether the slave has answered at all. And probably, you are not calling the library function to actually start a transfer. A bit more of your code would be required to analyze the problem. In most cases (not all, I must admit), problems with the library functions a based on wrong usage.

  • Here is the code!

    #define SLAVE_ADDRESS 0x1E
    //*****************************************************************************
    //
    //Specify Expected Receive data count.
    //
    //*****************************************************************************
    #define RXCOUNT 0x06
    
    //******************************************************************************
    //  MSP430FR57xx Demo - USCI_B0 I2C Master RX multiple bytes from MSP430 Slave
    //
    //  Description: This demo connects two MSP430's via the I2C bus. The master
    //  reads 5 bytes from the slave. This is the MASTER CODE. The data from the slave
    //  transmitter begins at 0 and increments with each transfer.
    //  The USCI_B0 RX interrupt is used to know when new data has been received.
    //  ACLK = n/a, MCLK = SMCLK = BRCLK =  DCO = 1MHz
    //
    //                                /|\  /|\
    //               MSP430FR5739      10k  10k     MSP430F5739
    //                   slave         |    |        master
    //             -----------------   |    |   -----------------
    //           -|XIN  P1.6/UCB0SDA|<-|----+->|P1.6/UCB0SDA  XIN|-
    //            |                 |  |       |                 | 32kHz
    //           -|XOUT             |  |       |             XOUT|-
    //            |     P1.7/UCB0SCL|<-+------>|P1.7/UCB0SCL     |
    //            |                 |          |             P1.0|--> LED
    //
    //******************************************************************************
    uint8_t RXData[6];
    uint8_t transmitData[3] = {0x02,0x00,0x03};
    uint8_t i=0;
    int byteCtr=0;
    void main(void)
    {
        WDT_A_hold(WDT_A_BASE);
    
        //Set DCO frequency to 8MHz
        CS_setDCOFreq(CS_DCORSEL_0,CS_DCOFSEL_3);
        //Set ACLK = DCO with frequency divider of 8
        CS_clockSignalInit(CS_ACLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_8);
        //Set SMCLK = DCO with frequency divider of 8
        CS_clockSignalInit(CS_SMCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_8);
        //Set MCLK = DCO with frequency divider of 8
        CS_clockSignalInit(CS_MCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_8);
    
        // Configure Pins for I2C
        //Set P1.6 and P1.7 as Secondary Module Function Input.
        /*
    
         * Select Port 1
         * Set Pin 6, 7 to input Secondary Module Function, (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).
         */
        GPIO_setAsPeripheralModuleFunctionInputPin(
            GPIO_PORT_P1,
            GPIO_PIN6 + GPIO_PIN7,
            GPIO_SECONDARY_MODULE_FUNCTION
            );
    
        //Init I2C 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 = RXCOUNT; //6Bytes for RX
        param.byteCounterThreshold = 3;
        //param.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD; //For RX
        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 TX 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);
    
    	EUSCI_B_I2C_clearInterruptFlag(EUSCI_B0_BASE,
    	                                   EUSCI_B_I2C_TRANSMIT_INTERRUPT0 +
    	                                   EUSCI_B_I2C_NAK_INTERRUPT
    	                                   );
    
    	    //Enable master Transmit interrupt
    	    EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE,
    	                                EUSCI_B_I2C_TRANSMIT_INTERRUPT0 +
    	                                EUSCI_B_I2C_NAK_INTERRUPT
    	                                );
    	    byteCtr = 3;
    	    while (byteCtr != 0 ){
    	    	EUSCI_B_I2C_masterSendSingleByte(EUSCI_B0_BASE, transmitData[byteCtr-1]);
    	    	byteCtr --;
    	    	__delay_cycles(2000);
    	    }
    
    
    
    	//Disable I2C Module to stop operations
    	EUSCI_B_I2C_disable(EUSCI_B0_BASE);
    
    	//Init I2C RX master
    	param.byteCounterThreshold = RXCOUNT; //6Bytes for RX
    	param.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD; //For RX
    	EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, &param);
    
        //Set Master in RX mode
        EUSCI_B_I2C_setMode(EUSCI_B0_BASE,
                            EUSCI_B_I2C_RECEIVE_MODE
                            );
    
    	//Enable I2C Module to start operations
    	EUSCI_B_I2C_enable(EUSCI_B0_BASE);
    
        EUSCI_B_I2C_clearInterruptFlag(EUSCI_B0_BASE,
                                       EUSCI_B_I2C_RECEIVE_INTERRUPT0 +
                                       EUSCI_B_I2C_BYTE_COUNTER_INTERRUPT +
                                       EUSCI_B_I2C_NAK_INTERRUPT
                                       );
    
        //Enable master Receive interrupt
        EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE,
                                    EUSCI_B_I2C_RECEIVE_INTERRUPT0 +
                                    EUSCI_B_I2C_BYTE_COUNTER_INTERRUPT +
                                    EUSCI_B_I2C_NAK_INTERRUPT
                                    );
    
        while(1)
        {
            __delay_cycles(2000);
    
            while(EUSCI_B_I2C_SENDING_STOP ==
                  EUSCI_B_I2C_masterIsSTOPSent(EUSCI_B0_BASE))
            {
                ;
            }
    
            EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
    
            __bis_SR_register(CPUOFF + GIE);    // Enter LPM0 w/ interrupt
        }
    }
    
    #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)
    {
        static uint8_t count = 0;
        switch(__even_in_range(UCB0IV,0x1E))
        {
        case 0x00: break;       // Vector 0: No interrupts break;
        case 0x02: break;       // Vector 2: ALIFG break;
        case 0x04:
            EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
            break;           // Vector 4: NACKIFG break;
        case 0x06: break;       // Vector 6: STT IFG break;
        case 0x08: 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:
            RXData[count] = EUSCI_B_I2C_masterSingleReceive(
                EUSCI_B0_BASE
                );        // Get RX data
            count++;
            if(count >= RXCOUNT)
            {
                count = 0;
                __bic_SR_register_on_exit(CPUOFF);               // Exit LPM0
            }
            break;           // Vector 24: RXIFG0 break;
        case 0x18:
    
        	break;       // Vector 26: TXIFG0 break;
        case 0x1a:
            GPIO_toggleOutputOnPin(
                GPIO_PORT_P1,
                GPIO_PIN0
                );
            break;           // Vector 28: BCNTIFG break;
        case 0x1c: break;       // Vector 30: clock low timeout break;
        case 0x1e: break;       // Vector 32: 9th bit break;
        default: break;
        }
    }
    

    Any thoughts?

    Thanks

  • Are you sure that 0x1E is the slave address? Or is it the start byte for a write transmission? Unfortunately, most manufacturers of I2C devices do not give the slave address, but separate start bytes for read and write. If so, the slave address would be 0x0f.

    Also, you have a while loop in which you send single bytes multiple times. I don’t know the library, but from other library, I remember that the single byte send means that the transmission ends after a single byte (while you want to send multiple bytes in one transmission).
    Moreover, you abruptly stop I2C operation without checking/ensuring that the last operation is done.

    This all is suspicious.

    Next it your ISR. In the NACKIFG case, you simply start a read operation - while the USCI was telling you that the slave didn’t answer on your last request (which likely was the write operation). Your main code continues to try to send bytes while the ISR has initiated a read - this can’t work. The main code is expecting the USCI to send while the USCI is not sending at all. Also, you enabled the TX interrupt, but you are not doing anything inside the TX ISR (except of clearing the TX flag). So the send function will never see TXIFG set (the ISR will clear it) and therefore never send anything (assuming TXBUF full, since TXIFG is not set).

    Please carefully re-read the library function descriptions. And draw a timeline of what happens when, based on the one found in the users guide. You’ll then see where the flaws in your workflow are.

**Attention** This is a public forum