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.

CCS/MSP430FR6989: I2C sample code using MSP430Ware MSP430FR5xx_6xx Driverlib

Part Number: MSP430FR6989
Other Parts Discussed in Thread: MSP430WARE, , ENERGIA

Tool/software: Code Composer Studio

Hello

Can somebody help me with sample code using MSP430FR5xx_6xx Driverlib for I2C communication. I am trying to connect to a I2C slave with 0x48 address and read a register 0x10. I have searched extensively but could not find any sample code that can get me started.

Regards

Vijay

  • Hello Vijay,

    MSP430WARE -> Libraries -> Driver Library -> MSP430FR5xx_6xx -> Example Projects -> EUSCI_B_I2C has several examples to get you started.

    Regards,
    Ryan
  • Sorry to bother you. My problem is that the slave does not send any data by itself. We have to retrieve data from the register in the slave. All the examples in the libraries wait for an interrupt to be generated from the slave. It is not the case with the sensor I am using. For example I have to read the chip address 0xd0 on a slave with address 0x77. I will be very thankful if you share some code.
  • What you've said simply isn't true, albeit no I2C slave devices send data without the master providing the clock. What is the slave device you are using? I would use example eusci_b_i2c_ex4_masterTxSingle (to send register address) followed by eusci_b_i2c_ex4_masterRxMultiple (to read data from register). Start -> slave address + write -> register address -> stop/start or re-start -> slave address + read -> read data -> stop.

    Regards,
    Ryan
  • The following code worked for me just once. I am not using interrupts as I will only need to set the register values once.
    I was able to read the Chip ID from BME280 module. However, it is now returning 0x00. Can you please suggest what could be wrong?


    ---------------------------------------------------------------------------------------------------
    #include <stdio.h>
    #include <msp430fr6989.h>
    #define SLAVE_ADDRESS 0x77
    #define CHIP_ADDRESS 0xd0

    unsigned int RX_Data;
    volatile unsigned char Com_Flag = 0;

    int main(void)
    {
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

    printf("Setting I2C Pins\n");

    P1SEL0 |= BIT6 | BIT7; // Configure GPIO 1.6 SDA 1.7 SCL to I2C pins

    PM5CTL0 &= ~LOCKLPM5;

    // Configure USCI_B0 for I2C mode
    UCB0CTLW0 = UCSWRST; // put eUSCI_B in reset state
    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK; // I2C master mode, SMCLK
    UCB0BRW = 0x8; // baudrate = SMCLK / 8
    //UCB0CTLW0 = UCASTP_2; // automatic STOP assertion
    UCB0CTLW0 &= ~UCSWRST; // clear reset register
    UCB0IE |= UCTXIE0 | UCNACKIE; // transmit and NACK interrupt enable
    UCB0I2CSA = SLAVE_ADDRESS; // configure slave address

    printf("I2C initialised!\n");

    while(UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTLW0 |= UCTR | UCTXSTT; // I2C TX, start condition
    printf("Sent start!\n");
    __delay_cycles(1000);
    UCB0TXBUF = CHIP_ADDRESS;
    __delay_cycles(1000);
    //UCB0CTLW0 |= UCTXSTP; // I2C stop condition
    //while(UCB0CTLW0 & UCTXSTP);
    UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
    UCB0CTLW0 &= ~UCTR;
    UCB0CTLW0 |= UCTXSTT; // repeated start
    __delay_cycles(1000);
    RX_Data = UCB0RXBUF; // Get RX data
    printf("Chip ID is: 0x%02x\n",RX_Data);
    }
    -------------------------------------------------------------------------------------------

    OUTPUT

    Setting I2C Pins
    I2C initialised!
    Sent start!
    Chip ID is: 0x00
  • If the BME280 device's SDO pin is connected to GND then the slave address should be 0x76, only 0x77 if connected to VDDIO instead. You should use a logic analyzer or oscilloscope screenshot to confirm that the slave address is acknowledging the I2C communication and responding correctly. The code you've provided could use improvement by checking the UCBUSY or TX/RX IFGs bits instead of relying on delays.

    Regards,
    Ryan
  • Dear Ryan

    The BME280 is working perfectly fine with the same launchpad with energia code. I am have trouble with this code in CCS. The energia code is working even when I import to CCS. After running many times, the code worked only once. Presently I am using 10K pullup resisters and I tried 4.7K resistors also. Both were working with energia but not with this code. I also tried below code with interrupts from the examples you mentioned but it getting stuck at __bic_SR_register_on_exit(LPM0_bits); I am not able get the TXIFG0 interrupt.

    Sorry I do not have an oscilloscope I also dont know how to use it. I am a medical science doctor working on a pollution sensing project.

    Please see the code below and let me know what I am doing wrong here. I has taken me 2 weeks to get to this level : )

    I have not added any restart for Receive. This code itself is getting stuck at the GIE.

    ______________________________________________________________________

    #include <msp430fr6989.h>
    
    #define BME280_ADDRESS 0x77
    #define CHIP_ADDRESS 0xd0
    
    volatile unsigned char TXByteCtr;
    unsigned char RX_Data;
    
    int main(void)
    {
      WDTCTL = WDTPW | WDTHOLD;
      P1SEL0 |= BIT6 | BIT7;
      PM5CTL0 &= ~LOCKLPM5;
      UCB0CTLW0 = UCSWRST;                                // Enable SW reset
      UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK;      // I2C Master, synchronous mode
      UCB0BRW = 0x8;                                     // fSCL = SMCLK/12 = ~100kHz
      UCB0CTLW0 &= ~UCSWRST;                             // Clear SW reset, resume operation
      UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE;             //Enable RX and TX interrupt
    
      while(1)
      {
          __delay_cycles(1000);                   // Delay between transmissions
          UCB0I2CSA = BME280_ADDRESS;    // configure slave address
          TXByteCtr = 1;                          // Load TX byte counter
          while (UCB0CTLW0 & UCTXSTP);            // Ensure stop condition got sent
    
          UCB0CTLW0 |= UCTR | UCTXSTT;            // I2C TX, start condition
    
          __bis_SR_register(LPM0_bits | GIE);
      }
    }
    
    #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, USCI_I2C_UCBIT9IFG))
        {
          case USCI_NONE:          break;         // Vector 0: No interrupts
          case USCI_I2C_UCALIFG:   break;         // Vector 2: ALIFG
          case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG
            UCB0CTLW0 |= UCTXSTT;                 // resend start if NACK
            break;
          case USCI_I2C_UCSTTIFG:  break;         // Vector 6: STTIFG
          case USCI_I2C_UCSTPIFG:  break;         // Vector 8: STPIFG
          case USCI_I2C_UCRXIFG3:  break;         // Vector 10: RXIFG3
          case USCI_I2C_UCTXIFG3:  break;         // Vector 12: TXIFG3
          case USCI_I2C_UCRXIFG2:  break;         // Vector 14: RXIFG2
          case USCI_I2C_UCTXIFG2:  break;         // Vector 16: TXIFG2
          case USCI_I2C_UCRXIFG1:  break;         // Vector 18: RXIFG1
          case USCI_I2C_UCTXIFG1:  break;         // Vector 20: TXIFG1
          case USCI_I2C_UCRXIFG0:  break;         // Vector 22: RXIFG0
          case USCI_I2C_UCTXIFG0:                 // Vector 24: TXIFG0
            if (TXByteCtr)                        // Check TX byte counter
            {
              UCB0TXBUF = CHIP_ADDRESS;      // Load TX buffer
              TXByteCtr--;                        // Decrement TX byte counter
            }
            else
            {
              UCB0CTLW0 |= UCTXSTP;               // I2C stop condition
              UCB0IFG &= ~UCTXIFG;                // Clear USCI_B0 TX int flag
              __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
            }
            break;
          default: break;
        }
      }
    

  • Vijay,

    I debugged your code as-is and entered the USCI_I2C_UCTXIFG0 case of the USCI_B0_VECTOR ISR without any issues. Note that this will only occur with pull-up resistors connected.

    Regards,
    Ryan
  • Ryan

    What perplexes me is the fact that it Launchpad with 10K pullups is working in energia while it is not in CCS? Is there any additional project/build configuration the I need to do in CCS?

    Regards
    Dr. Vijay

  • The 10k resistors on my LaunchPad do work in CCS. What are your IDE and compiler versions?  You can try sending me your CCS project files to review if you think it will be of any use.

    Regards,
    Ryan

  • Ryan

    Below code solved my problem. I still wonder why the earlier code was getting stuck. Please let me if you find the bug.

    unsigned char i2c_read(unsigned char slv_addr, unsigned char reg_addr){
    
        unsigned char data = 0;
    
        while(UCB0STAT & UCBBUSY);
        UCB0I2CSA = slv_addr;
        UCB0CTLW0 |= UCTR | UCTXSTT;
        
        while(UCB0CTLW0 & UCTXSTT);
        UCB0TXBUF = reg_addr;
        while(!(UCB0IFG & UCTXIFG0));
    
        UCB0CTLW0 &= ~UCTR;
        UCB0CTLW0 |= UCTXSTT;
    
        while(UCB0CTLW0 & UCTXSTT);
        UCB0CTLW0 |= UCTXSTP;
        while(!(UCB0IFG & UCRXIFG0));
        data = UCB0RXBUF;
    
        while(UCB0CTLW0 & UCTXSTP);
    
        return data;
    }

**Attention** This is a public forum