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.

BOOSTXL-SENSORS: BOOSTXL-SENSORS and BOOSTXL-BASSENSORS on MSP430FR5994 and MSP430FR6989

Part Number: BOOSTXL-SENSORS
Other Parts Discussed in Thread: MSP430FR6989, MSP430FR5994, BOOSTXL-BASSENSORS, , OPT3001

Hello,

Currently, I am trying to run the BOOSTXL-BASSENSORS boosterpack on the MSP430FR6989 and was attempting to port some I2C driver code from the BOOSTXL-Sensors and MSP430FR5994 OOB code examples.  However, I kept running into an error on the driver where "while(!(UCB0IFG & UCTXIFG0));" during I2C communication, making me think the slave is not registering.  Then, when I tried the OOB code on the BOOSTXL-Sensors and the MSP430FR5994 combination, I received the same error, even though this is example code that is built for these devices.

Is there a reason I am running into this error?  If any more information is needed please let me know, thanks!

  • Hi Domenick,

    Attached is example code using FR6989 to acquire data from the OPT3001 on the BOOSTXL-BASSENSORS boosterpack.

    FR6989_demo.c
    //******************************************************************************
    //   MSP430FR6989 Demo - BOOSTXL- BASSENSORS BOOSTERPACK
    //
    //
    //******************************************************************************
    
    #include <msp430.h> 
    #include <stdint.h>
    #include <stdbool.h>
    
    
    //******************************************************************************
    // General I2C State Machine ***************************************************
    //******************************************************************************
    
    typedef enum I2C_ModeEnum{
        IDLE_MODE,
        NACK_MODE,
        TX_REG_ADDRESS_MODE,
        RX_REG_ADDRESS_MODE,
        TX_DATA_MODE,
        RX_DATA_MODE,
        SWITCH_TO_RX_MODE,
        SWITHC_TO_TX_MODE,
        TIMEOUT_MODE
    } I2C_Mode;
    
    
    /* Used to track the state of the software state machine*/
    I2C_Mode MasterMode = IDLE_MODE;
    
    /* The Register Address/Command to use*/
    uint8_t TransmitRegAddr = 0;
    
    /* ReceiveBuffer: Buffer used to receive data in the ISR
     * RXByteCtr: Number of bytes left to receive
     * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
     * TransmitBuffer: Buffer used to transmit data in the ISR
     * TXByteCtr: Number of bytes left to transfer
     * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer
     * */
    #define MAX_BUFFER_SIZE     20
    uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t RXByteCtr = 0;
    uint8_t ReceiveIndex = 0;
    uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
    uint8_t TXByteCtr = 0;
    uint8_t TransmitIndex = 0;
    
    
    
    /* I2C Write and Read Functions */
    
    /* For slave device with dev_addr, writes the data specified in *reg_data
     *
     * dev_addr: The slave device address.
     *           Example: SLAVE_ADDR
     * reg_addr: The register or command to send to the slave.
     *           Example: CMD_TYPE_0_MASTER
     * *reg_data: The buffer to write
     *           Example: MasterType0
     * count: The length of *reg_data
     *           Example: TYPE_0_LENGTH
     *  */
    I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count);
    
    /* For slave device with dev_addr, read the data specified in slaves reg_addr.
     * The received data is available in ReceiveBuffer
     *
     * dev_addr: The slave device address.
     *           Example: SLAVE_ADDR
     * reg_addr: The register or command to send to the slave.
     *           Example: CMD_TYPE_0_SLAVE
     * count: The length of data to read
     *           Example: TYPE_0_LENGTH
     *  */
    I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count);
    void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);
    
    
    I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
    {
        /* Initialize state machine */
        MasterMode = TX_REG_ADDRESS_MODE;
        TransmitRegAddr = reg_addr;
        RXByteCtr = count;
        TXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB1I2CSA = dev_addr;
        UCB1IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB1IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB1IE |= UCTXIE;                        // Enable TX interrupt
    
        UCB1CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
        __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts
    
        return 0;
    
    }
    
    
    I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
    {
        /* Initialize state machine */
        MasterMode = TX_REG_ADDRESS_MODE;
        TransmitRegAddr = reg_addr;
    
        //Copy register data to TransmitBuffer
        CopyArray(reg_data, TransmitBuffer, count);
    
        TXByteCtr = count;
        RXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB1I2CSA = dev_addr;
        UCB1IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB1IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB1IE |= UCTXIE;                        // Enable TX interrupt
    
        UCB1CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
        __bis_SR_register(LPM0_bits + GIE);      // Enter LPM0 w/ interrupts
    
        return MasterMode;
    }
    
    void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
    {
        uint8_t copyIndex = 0;
        for (copyIndex = 0; copyIndex < count; copyIndex++)
        {
            dest[copyIndex] = source[copyIndex];
        }
    }
    
    
    //******************************************************************************
    // Device Initialization *******************************************************
    //******************************************************************************
    void initGPIO()
    {
        P1OUT = 0;
        P1DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    
        P2OUT = 0;
        P2DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    
        P3OUT = 0;
        P3DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    
        P4OUT = 0;
        P4DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
        P4SEL0 = 0;
        P4SEL1 = (BIT0 | BIT1); // ENABLE I2C
    
        P5OUT = 0;
        P5DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    
        P6OUT = 0;
        P6DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    
        P7OUT = 0;
        P7DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    
        P8OUT = BIT6; // ENABLE PULLUP FOR INTERRUPT
        P8DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT7);  // BIT6 IS OPT3001 INTERRUPT
        P8REN = BIT6; // ENABLE PULLUP FOR INTERRUPT
    
        P9OUT = BIT0;  // APPLY OPT3001 POWER
        P9DIR = (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
    
        // Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;
    }
    
    void initClockTo16MHz()
    {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRCTL0 = FRCTLPW | NWAITS_1;
    
        // Clock System Setup
          CSCTL0_H = CSKEY >> 8;                    // Unlock CS registers
          CSCTL1 = DCOFSEL_4 | DCORSEL;             // Set DCO to 16MHz
          CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;  // Set SMCLK = MCLK = DCO
                                                    // ACLK = VLOCLK
          CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;     // Set all dividers to 1
          CSCTL0_H = 0;                             // Lock CS registers
    }
    
    
    void initI2C()
    {
    
        UCB1CTLW0 = UCSWRST;                      // Enable SW reset
        UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
        UCB1BRW = 40;                            // fSCL = SMCLK/40 = ~400kHz
        UCB1CTLW0 &= ~UCSWRST;                    // Clear SW reset, resume operation
        UCB1IE |= UCNACKIE;
    }
    
    
    //******************************************************************************
    // Main ************************************************************************
    // Send and receive three messages containing the example commands *************
    //******************************************************************************
    #include <math.h>
    #define HDC2010_ADDRS       0x40
    #define OPT3001_ADDRS       0x44
    #define OPT3001_RESULT_REG  0x00
    #define OPT3001_CONFIG_REG  0x01
    #define OPT3001_LLIMIT_REG  0x02
    #define TMP116_ADDRS        0x48
    #define LIGHT_SENSOR 2
    
    uint8_t LightSensorConfigWrite [2] = {0xCE , 0x10};  //AUTOMATIC FULLSCALE, 800MS CONVERSION, CONTINUOUS
    uint8_t LightSensorDataRead [2] = {0};              // DATA WILL ALWAYS BE 2 BYTES
    uint8_t LightSensorLLimitWrite [2] = {0xC0, 0x00};  //ENABLE INTERRUPT PIN AFTER EVERY CONVERSION
    uint8_t LightSensorConfigRead [2] = {0};              // CONFIG WILL ALWAYS BE 2 BYTES
    float lux;
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
        initClockTo16MHz();
        initGPIO();
        initI2C();
        _delay_cycles(100000);  // allow some time for OPT3001
    
        I2C_Master_WriteReg(OPT3001_ADDRS, OPT3001_CONFIG_REG, LightSensorConfigWrite, 2);
        I2C_Master_WriteReg(OPT3001_ADDRS, OPT3001_LLIMIT_REG, LightSensorLLimitWrite, 2);
    
        while(1)
        {
    
            while(P8IN & BIT6); // POLL THIS PIN (GOES LOW EVERY 800MS)
    
            I2C_Master_ReadReg(OPT3001_ADDRS, OPT3001_RESULT_REG, 2);
            CopyArray(ReceiveBuffer, LightSensorDataRead, 2);  // COPY RESULTS FROM RECEIVE BUFFER
    
            I2C_Master_ReadReg(OPT3001_ADDRS, OPT3001_CONFIG_REG, 2); // CLEAR THE INTERRUPT BIT
            CopyArray(ReceiveBuffer, LightSensorConfigRead, 2);  // COPY RESULTS FROM RECEIVE BUFFER
        }
    
    }
    
    
    //******************************************************************************
    // I2C Interrupt ***************************************************************
    //******************************************************************************
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B1_VECTOR
    __interrupt void USCI_B1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B1_VECTOR))) USCI_B1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      //Must read from UCB1RXBUF
      uint8_t rx_val = 0;
      switch(__even_in_range(UCB1IV, 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
          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:                 // Vector 22: RXIFG0
            rx_val = UCB1RXBUF;
            if (RXByteCtr)
            {
              ReceiveBuffer[ReceiveIndex++] = rx_val;
              RXByteCtr--;
            }
    
            if (RXByteCtr == 1)
            {
              UCB1CTLW0 |= UCTXSTP;
            }
            else if (RXByteCtr == 0)
            {
              UCB1IE &= ~UCRXIE;
              MasterMode = IDLE_MODE;
              __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
            }
            break;
        case USCI_I2C_UCTXIFG0:                 // Vector 24: TXIFG0
            switch (MasterMode)
            {
              case TX_REG_ADDRESS_MODE:
                  UCB1TXBUF = TransmitRegAddr;
                  if (RXByteCtr)
                      MasterMode = SWITCH_TO_RX_MODE;   // Need to start receiving now
                  else
                      MasterMode = TX_DATA_MODE;        // Continue to transmision with the data in Transmit Buffer
                  break;
    
              case SWITCH_TO_RX_MODE:
                  UCB1IE |= UCRXIE;              // Enable RX interrupt
                  UCB1IE &= ~UCTXIE;             // Disable TX interrupt
                  UCB1CTLW0 &= ~UCTR;            // Switch to receiver
                  MasterMode = RX_DATA_MODE;    // State state is to receive data
                  UCB1CTLW0 |= UCTXSTT;          // Send repeated start
                  if (RXByteCtr == 1)
                  {
                      //Must send stop since this is the N-1 byte
                      while((UCB1CTLW0 & UCTXSTT));
                      UCB1CTLW0 |= UCTXSTP;      // Send stop condition
                  }
                  break;
    
              case TX_DATA_MODE:
                  if (TXByteCtr)
                  {
                      UCB1TXBUF = TransmitBuffer[TransmitIndex++];
                      TXByteCtr--;
                  }
                  else
                  {
                      //Done with transmission
                      UCB1CTLW0 |= UCTXSTP;     // Send stop condition
                      MasterMode = IDLE_MODE;
                      UCB1IE &= ~UCTXIE;                       // disable TX interrupt
                      __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
                  }
                  break;
    
              default:
                  __no_operation();
                  break;
            }
            break;
        default: break;
      }
    }