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/MSP430FR2355: Interfacing Servo motor and Opt3001

Part Number: MSP430FR2355
Other Parts Discussed in Thread: OPT3001

Tool/software: Code Composer Studio

I was trying to run two servo motors and one OPT3001 using MSP430, i m adding how it is supposed to work.

The servo motor rotation is controlled using ADC input and pin 2.2 is set using value from result register of OPT3001. During debugging my program is only performing ADC function, only ADC_Result variable is getting updated.

I tried adding breakpoints and debugging, but my program is getting stuck at this line from ADC_capture() function and that's why only ADC_Result is getting updated from ADC_ISR.

 __bis_SR_register(LPM0 | GIE);                       // Enter LPM3 w/ interrupts

I tried removing  ADC ISR and used If statement,

if(ADCIV_ADCIFG)
{
  ADC_Result = ADCMEM0;
}

but this did not work.

Can you tell my what is the problem with this.

Thank You

I m attaching my code here.

#include <msp430.h>                      // Generic MSP430 Device Include
#include <stdint.h>

#define OPT3001 0x44
#define Result 0x00
#define Configuration 0x01

#define ONE_BYTE 0x1
#define TWO_BYTES 0x2
#define THREE_BYTES 0x3

unsigned long lux;
unsigned int ADC_Result;

void GPIO_pin_configurations(void);
void Turning_MECH(void);
void Dipping_SYS(void);
void ADC_capture(void);
void ADC_CONFIG(void);

void I2C_transmission_setup(unsigned char num_of_bytes);
void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2);
void I2C_setup_write(unsigned char slave_address, unsigned char register_address);
void I2C_read(unsigned char slave_address);

unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa);

unsigned char TXData[3];
unsigned char RXData[2];
unsigned char ByteCtr;

void main(void)
{
    GPIO_pin_configurations();

    unsigned int exponent;
    unsigned int mantissa;
    //Write to Configuration Register (0x01) to set the operational mode of the OPT3001
    I2C_transmission_setup(THREE_BYTES);
    I2C_write(OPT3001, Configuration, 0xC6, 0x08);
    // Delay for 100 milliseconds to allow conversion process to complete
    __delay_cycles(100);

    while(1)
    {

        I2C_transmission_setup(ONE_BYTE);
        I2C_setup_write(OPT3001, Result);

        I2C_transmission_setup(TWO_BYTES);
        I2C_read(OPT3001);

        //Extract the upper four bits of exponent and the lower 12 bits of mantissa from the raw result value
        exponent = RXData[0] >> 4;
        mantissa = (RXData[0] << 8 | RXData[1]) & 0x0FFF;

        //Take the exponent and mantissa values and calculate the corresponding lux value
        lux = convert_to_lux(exponent, mantissa);

        ADC_CONFIG();

        Dipping_SYS();

        Turning_MECH();

        ADC_capture();

    } // End background loop
} // End main()


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCB0IV,USCI_I2C_UCBIT9IFG))
  {
        case USCI_NONE: break;                        // Vector 0: No interrupts break;
        case USCI_I2C_UCALIFG: break;
        case USCI_I2C_UCNACKIFG:
            UCB0CTL1 |= UCTXSTT;                      //resend start if NACK
          break;                                      // Vector 4: NACKIFG break;
        case USCI_I2C_UCSTTIFG: break;                // Vector 6: STTIFG break;
        case USCI_I2C_UCSTPIFG: break;                // Vector 8: STPIFG break;
        case USCI_I2C_UCRXIFG3: break;                // Vector 10: RXIFG3 break;
        case USCI_I2C_UCTXIFG3: break;                // Vector 14: TXIFG3 break;
        case USCI_I2C_UCRXIFG2: break;                // Vector 16: RXIFG2 break;
        case USCI_I2C_UCTXIFG2: break;                // Vector 18: TXIFG2 break;
        case USCI_I2C_UCRXIFG1: break;                // Vector 20: RXIFG1 break;
        case USCI_I2C_UCTXIFG1: break;                // Vector 22: TXIFG1 break;

        case USCI_I2C_UCRXIFG0:                       // Vector 24: RXIFG0 break;

            RXData[ByteCtr] = UCB0RXBUF;                // Load RX buffer
            ByteCtr++;                                  // Increment RX byte counter

            break;

        case USCI_I2C_UCTXIFG0:                       // Vector 26: TXIFG0 break;

            UCB0TXBUF = TXData[ByteCtr];            // Load TX buffer
            ByteCtr++;                              // Increment TX byte counter

          break;

        case USCI_I2C_UCBCNTIFG:                      // Vector 28: BCNTIFG

            __bic_SR_register_on_exit(LPM0_bits);     // Exit LPM0

            break;

        case USCI_I2C_UCCLTOIFG: break;               // Vector 30: clock low timeout
        case USCI_I2C_UCBIT9IFG: break;               // Vector 32: 9th bit
        default: break;
  }
}
  // ADC interrupt service routine
  #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
  #pragma vector=ADC_VECTOR
  __interrupt void ADC_ISR(void)
  #elif defined(__GNUC__)
  void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
  #else
  #error Compiler not supported!
  #endif
  {
      switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
      {
          case ADCIV_NONE:
              break;
          case ADCIV_ADCOVIFG:
              break;
          case ADCIV_ADCTOVIFG:
              break;
          case ADCIV_ADCHIIFG:
              break;
          case ADCIV_ADCLOIFG:
              break;
          case ADCIV_ADCINIFG:
              break;
          case ADCIV_ADCIFG:
              ADC_Result = ADCMEM0;
              __bic_SR_register_on_exit(LPM0_bits);            // Clear CPUOFF bit from LPM0
              break;
          default:
              break;
      }
  }

void I2C_transmission_setup(unsigned char num_of_bytes)
{
    //Configure USCI_B0 for I2C Mode and designate the number of bytes to be transmitted/received

    UCB0CTLW0 |= UCSWRST;                               // Software reset enabled
    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;    // I2C master mode, SMCLK
    UCB0CTLW1 |= UCASTP_2;                              // Automatic stop generated
                                                        // after UCB0TBCNT is reached
    UCB0BRW = 0x8;                                      // baudrate = SMCLK / 8
    UCB0TBCNT = num_of_bytes;                           // number of bytes to be received
    UCB0CTL1 &= ~UCSWRST;                               // clear reset register
    UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE | UCBCNTIE;   // transmit and NACK interrupt enable
}

void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2)
{
    UCB0I2CSA = slave_address;                      // Set the slave address
    TXData[0] = register_address;                   // Set the control register address
    TXData[1] = byte_1;                             // Set the Register Data LSB
    TXData[2] = byte_2;                             // Set the Register Data MSB
    ByteCtr = 0;                                    // Load byte counter
    while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
    UCB0CTLW0 |= UCTR;                              // I2C TX
    UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
    __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                    // Remain in LPM0 until all data
                                                    // is TX'd
}

void I2C_setup_write(unsigned char slave_address, unsigned char register_address)
{
    UCB0I2CSA = slave_address;                      // Set the slave address
    TXData[0] = register_address;                   // Set the control register address
    ByteCtr = 0;                                    // Load byte counter
    while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
    UCB0CTLW0 |= UCTR;                              // I2C TX
    UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
    __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                    // Remain in LPM0 until all data
                                                    // is TX'd
}

void I2C_read(unsigned char slave_address)
{
    UCB0I2CSA = slave_address;                      // Set the slave address
    ByteCtr = 0;                                    // Load byte counter
    while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
    UCB0CTLW0 &= ~UCTR;                             // I2C RX
    UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
    __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                    // Remain in LPM0 until all data
                                                    // is RX'd
}

unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa)
{
    // Convert the Result Register into a lux measurement based on formula below:
    // lux = 0.01 * (2^E[3:0]) * R[11:0]

    unsigned int result;
    unsigned int count;
    unsigned long converted_lux;

    result = 1;
    for(count = exponent; count > 0; count--)
    {
        result = result * 2;
    }
    converted_lux = mantissa / 100;
    converted_lux *= result;

    return converted_lux;
}

void GPIO_pin_configurations(void)
{
   WDTCTL = WDTPW | WDTHOLD;                                  // Stop WDT

   // Disable the GPIO power-on default high-impedance mode to activate
   // previously configured port settings
   PM5CTL0 &= ~LOCKLPM5;

   // Configure ADC A1 pin
   P1SEL0 |= BIT1 | BIT2 | BIT3;                              //Configure ADC A1 pin, I2C pins and Timer_B 0 pins
   P1SEL1 |= BIT1 | BIT6 | BIT7;                                     // P1.1, 1.2, 1.3 , 1.6 and 1.7 options select
   P1DIR |= BIT6;                                             // P1.6 output

   // Configure XT1 oscillator
   P2SEL1 |= BIT6 | BIT7;                                     // P2.6~P2.7: crystal pins

   CSCTL4 = SELA__XT1CLK;                                     // Set ACLK = XT1; MCLK = SMCLK = DCO
   /*Configuring Unused pins to avoid floating voltage
    and extra current consumption*/
    P1OUT = 0x00;
    P3DIR = 0xFF;
    P3OUT = 0x00;
    P4DIR = 0xFF;
    P4OUT = 0x00;
    P5DIR = 0xFF;
    P5OUT = 0x00;
    P6DIR = 0xFF;
    P6OUT = 0x00;
    P7DIR = 0xFF;
    P7OUT = 0x00;
    P8DIR = 0xFF;
    P8OUT = 0x00;
    P9DIR = 0xFF;
    P9OUT = 0x00;
    P10DIR = 0xFF;
    P10OUT = 0x00;
    PADIR = 0xFF;
    PAOUT = 0x00;
    PBDIR = 0xFF;
    PBOUT = 0x00;
    PCDIR = 0xFF;
    PCOUT = 0x00;
    PDDIR = 0xFF;
    PDOUT = 0x00;
    PEDIR = 0xFF;
    PEOUT = 0x00;
}

void Turning_MECH(void)
{

   //Servo motor for rotation minimum value of TB0CCR1 is 500 and maximum value of TB0CCR1 is 3500
   TB0CCTL1 = OUTMOD_7;                                       // CCR1 reset/set P1.6
   TB0CCTL2 = OUTMOD_7;                                       // CCR2 reset/set
   TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR;                   // SMCLK, up mode, clear TBR
   if(ADC_Result == 0)
   {
     TB0CCR0 = 20000-1;                                       // PWM Period
     TB0CCR1 = 500;                                           // CCR1 PWM duty cycle
     TB0CCR2 = 500;                                           // CCR2 PWN duty cycle
   }
   else if(ADC_Result == 100)
   {
     TB0CCR0 = 20000-1;                                       // PWM Period
     TB0CCR1 = 1700;                                          // CCR1 PWM duty cycle
     TB0CCR2 = 1700;                                           // CCR2 PWN duty cycle
   }
   else if(ADC_Result >= 250)
   {
     TB0CCR0 = 20000-1;                                       // PWM Period
     TB0CCR1 = 3500;                                          // CCR1 PWM duty cycle
     TB0CCR2 = 3500;                                           // CCR2 PWN duty cycle
   }
}
void Dipping_SYS(void)
{
    /*
     * Pin2.2 is connected to main headlight and control its auto dip mechanism
     */
   if(lux > 2000)
   {
     P2DIR |= BIT2;
     P2OUT |= BIT2;
   }
   else
   {
     P2OUT = 0X00;
   }
}

void ADC_CONFIG(void)
{
    // Configure ADC
    ADCCTL0 |= ADCON | ADCMSC;                                // ADCON
    ADCCTL1 |= ADCSHS_2 | ADCCONSEQ_2;                        // repeat single channel; TB1.1 trig sample start
    ADCCTL2 &= ~ADCRES;                                       // clear ADCRES in ADCCTL
    ADCCTL2 |= ADCRES_2;                                      // 12-bit conversion results
    ADCMCTL0 |= ADCINCH_1 | ADCSREF_1;                        // A1 ADC input select; Vref=1.5V
    ADCIE |= ADCIE0;                                          // Enable ADC conv complete interrupt
    // Configure reference
    PMMCTL0_H = PMMPW_H;                                      // Unlock the PMM registers
    PMMCTL2 |= INTREFEN | REFVSEL_0;                          // Enable internal 1.5V reference
    __delay_cycles(400);                                      // Delay for reference settling
    do{
        CSCTL7 &= ~(XT1OFFG | DCOFFG);                        // Clear XT1 and DCO fault flag
        SFRIFG1 &= ~OFIFG;
       }while (SFRIFG1 & OFIFG);                              // Test oscillator fault flag

}
void ADC_capture(void)
{
    ADCCTL0 |= ADCENC;                                        // ADC Enable
    // ADC conversion trigger signal - TimerB1.1 (32ms ON-period)
    TB1CCR0 = 1024-1;                                         // PWM Period
    TB1CCR1 = 512-1;                                          // TB1.1 ADC trigger
    TB1CCTL1 = OUTMOD_4;                                      // TB1CCR0 toggle
    TB1CTL = TBSSEL__ACLK | MC_1 | TBCLR;                     // ACLK, up mode
    __bis_SR_register(LPM0 | GIE);                       // Enter LPM3 w/ interrupts
}

  • P4DIR = 0xFF;
    P4OUT = 0x00;

    I removed the initialization statement for Port 4 and now its working. I m still failing to understand how port 4 is affecting OPT3001. 

  • >    __bis_SR_register(LPM0 | GIE);                       // Enter LPM3 w/ interrupts

    If this works, it's purely accidental. Try:

    >    __bis_SR_register(LPM0_bits | GIE);                       // Enter LPM3 w/ interrupts

    ----------------

    Are you using the Launchpad? If so, P4.2-3 are connected to the backchannel UART and P4.2 (RXD) in particular is being driven high by the USB side. Try removing the RXD/TXD jumpers from J101.

    ----------------

    With CONSEQ=2 and MSC=1, your ADC is converting as fast as it can (ignoring your timer trigger). This is probably eating up many CPU cycles. I think you'll get the effect you want if you set MSC=0.

    More generally: You probably want to use ADC_CONFIG once, outside the main loop. And the TimerB initialization should go there, not every time through the loop.

  • I have used LPM0_bits in my program maybe by mistake I edited it after copying the program in the thread, sorry about that.

    I m using MSPEXP430FR2355.

    I tried removing jumpers of RXD and TXD from J101 and added initialization of port 4, its still the same.

    I did some changes according to your suggestions.

    I wanted to ask about OPT3001, it's unpredictable at first during debugging it will work for few times and then stop abruptly, I m sure that no lose connections are there. 

    I m attaching updated code and also I was adding delay using timer module which is yet to be completed.

     

    #include <msp430.h>                      // Generic MSP430 Device Include
    #include <stdint.h>
    
    #define OPT3001 0x44
    #define Result 0x00
    #define Configuration 0x01
    
    #define ONE_BYTE 0x1
    #define TWO_BYTES 0x2
    #define THREE_BYTES 0x3
    
    unsigned long lux;
    unsigned int ADC_Result;
    
    void GPIO_pin_configurations(void);
    void Turning_MECH(void);
    void Dipping_SYS(void);
    void ADC_capture(void);
    void ADC_CONFIG(void);
    void Delay(unsigned long int Value);
    
    void I2C_transmission_setup(unsigned char num_of_bytes);
    void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2);
    void I2C_setup_write(unsigned char slave_address, unsigned char register_address);
    void I2C_read(unsigned char slave_address);
    
    unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa);
    
    unsigned char TXData[3];
    unsigned char RXData[2];
    unsigned int ByteCtr;
    
    void main(void)
    {
        GPIO_pin_configurations();
    
        unsigned int exponent;
        unsigned int mantissa;
        //Write to Configuration Register (0x01) to set the operational mode of the OPT3001
        I2C_transmission_setup(THREE_BYTES);
        I2C_write(OPT3001, Configuration, 0xC6, 0x08);
        // Delay for 100 milliseconds to allow conversion process to complete
        //Delay(1000000);
        __delay_cycles(100);
    
        ADC_CONFIG();
    
        while(1)
        {
               do
               {
                   CSCTL7 &= ~(XT1OFFG | DCOFFG);                        // Clear XT1 and DCO fault flag
                   SFRIFG1 &= ~OFIFG;
               }while (SFRIFG1 & OFIFG);                                 // Test oscillator fault flag
    
            Dipping_SYS();
    
            Turning_MECH();
    
            ADC_capture();
    
            I2C_transmission_setup(ONE_BYTE);
            I2C_setup_write(OPT3001, Result);
    
            I2C_transmission_setup(TWO_BYTES);
            I2C_read(OPT3001);
    
            //Extract the upper four bits of exponent and the lower 12 bits of mantissa from the raw result value
            exponent = RXData[0] >> 4;
            mantissa = (RXData[0] << 8 | RXData[1]) & 0x0FFF;
    
            //Take the exponent and mantissa values and calculate the corresponding lux value
            lux = convert_to_lux(exponent, mantissa);
        } // End background loop
    } // End main()
    
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB0IV,USCI_I2C_UCBIT9IFG))
      {
            case USCI_NONE: break;                        // Vector 0: No interrupts break;
            case USCI_I2C_UCALIFG: break;
            case USCI_I2C_UCNACKIFG:
                UCB0CTL1 |= UCTXSTT;                      //resend start if NACK
              break;                                      // Vector 4: NACKIFG break;
            case USCI_I2C_UCSTTIFG: break;                // Vector 6: STTIFG break;
            case USCI_I2C_UCSTPIFG: break;                // Vector 8: STPIFG break;
            case USCI_I2C_UCRXIFG3: break;                // Vector 10: RXIFG3 break;
            case USCI_I2C_UCTXIFG3: break;                // Vector 14: TXIFG3 break;
            case USCI_I2C_UCRXIFG2: break;                // Vector 16: RXIFG2 break;
            case USCI_I2C_UCTXIFG2: break;                // Vector 18: TXIFG2 break;
            case USCI_I2C_UCRXIFG1: break;                // Vector 20: RXIFG1 break;
            case USCI_I2C_UCTXIFG1: break;                // Vector 22: TXIFG1 break;
    
            case USCI_I2C_UCRXIFG0:                       // Vector 24: RXIFG0 break;
    
                RXData[ByteCtr] = UCB0RXBUF;                // Load RX buffer
                ByteCtr++;                                  // Increment RX byte counter
    
                break;
    
            case USCI_I2C_UCTXIFG0:                       // Vector 26: TXIFG0 break;
    
                UCB0TXBUF = TXData[ByteCtr];            // Load TX buffer
                ByteCtr++;                              // Increment TX byte counter
    
              break;
    
            case USCI_I2C_UCBCNTIFG:                      // Vector 28: BCNTIFG
    
                __bic_SR_register_on_exit(LPM0_bits);     // Exit LPM0
    
                break;
    
            case USCI_I2C_UCCLTOIFG: break;               // Vector 30: clock low timeout
            case USCI_I2C_UCBIT9IFG: break;               // Vector 32: 9th bit
            default: break;
      }
    }
      // ADC interrupt service routine
      #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
      #pragma vector=ADC_VECTOR
      __interrupt void ADC_ISR(void)
      #elif defined(__GNUC__)
      void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
      #else
      #error Compiler not supported!
      #endif
      {
          switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
          {
              case ADCIV_NONE:
                  break;
              case ADCIV_ADCOVIFG:
                  break;
              case ADCIV_ADCTOVIFG:
                  break;
              case ADCIV_ADCHIIFG:
                  break;
              case ADCIV_ADCLOIFG:
                  break;
              case ADCIV_ADCINIFG:
                  break;
              case ADCIV_ADCIFG:
                  ADC_Result = ADCMEM0;
                  __bic_SR_register_on_exit(LPM0_bits);            // Clear CPUOFF bit from LPM0
                  break;
              default:
                  break;
          }
      }
    
      // Timer B1 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = TIMER1_B0_VECTOR
    __interrupt void Timer1_B0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER1_B0_VECTOR))) Timer1_B0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
      {
         __bic_SR_register_on_exit(LPM0_bits);            // Clear CPUOFF bit from LPM0
      }
    
    void I2C_transmission_setup(unsigned char num_of_bytes)
    {
        //Configure USCI_B0 for I2C Mode and designate the number of bytes to be transmitted/received
    
        UCB0CTLW0 |= UCSWRST;                               // Software reset enabled
        UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;    // I2C master mode, SMCLK
        UCB0CTLW1 |= UCASTP_2;                              // Automatic stop generated
                                                            // after UCB0TBCNT is reached
        UCB0BRW = 0x8;                                      // baudrate = SMCLK / 8
        UCB0TBCNT = num_of_bytes;                           // number of bytes to be received
        UCB0CTL1 &= ~UCSWRST;                               // clear reset register
        UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE | UCBCNTIE;   // transmit and NACK interrupt enable
    }
    
    void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        TXData[0] = register_address;                   // Set the control register address
        TXData[1] = byte_1;                             // Set the Register Data LSB
        TXData[2] = byte_2;                             // Set the Register Data MSB
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 |= UCTR;                              // I2C TX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is TX'd
    }
    
    void I2C_setup_write(unsigned char slave_address, unsigned char register_address)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        TXData[0] = register_address;                   // Set the control register address
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 |= UCTR;                              // I2C TX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is TX'd
    }
    
    void I2C_read(unsigned char slave_address)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 &= ~UCTR;                             // I2C RX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is RX'd
    }
    
    unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa)
    {
        // Convert the Result Register into a lux measurement based on formula below:
        // lux = 0.01 * (2^E[3:0]) * R[11:0]
    
        unsigned int result;
        unsigned int count;
        unsigned long converted_lux;
    
        result = 1;
        for(count = exponent; count > 0; count--)
        {
            result = result * 2;
        }
        converted_lux = mantissa / 100;
        converted_lux *= result;
    
        return converted_lux;
    }
    
    void GPIO_pin_configurations(void)
    {
         WDTCTL = WDTPW | WDTHOLD;                                 // Stop WDT
    
        P1SEL0 = BIT2|BIT3;
        // Configure ADC A1 pin
        P1SEL0 |= BIT1;
        P1SEL1 |= BIT1;
        P1DIR |= BIT6 | BIT7;                     // P1.6 and P1.7 output
        P1SEL1 |= BIT6 | BIT7;                    // P1.6 and P1.7 options select
    
        // Configure XT1 oscillator
        P2SEL1 |= BIT6 | BIT7;                                    // P2.6~P2.7: crystal pins
    
        // Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;
        CSCTL4 = SELA__XT1CLK;                                    // Set ACLK = XT1; MCLK = SMCLK = DCO
        P1OUT = 0x00;
        /*Configuring Unused pins to avoid floating voltage
             and extra current consumption*/
        P3DIR = 0xFF;
        P3OUT = 0x00;
      //  P4DIR = 0xFF;
      //  P4OUT = 0x00;
        P5DIR = 0xFF;
        P5OUT = 0x00;
        P6DIR = 0xFF;
        P6OUT = 0x00;
        P7DIR = 0xFF;
        P7OUT = 0x00;
        P8DIR = 0xFF;
        P8OUT = 0x00;
        P9DIR = 0xFF;
        P9OUT = 0x00;
        P10DIR = 0xFF;
        P10OUT = 0x00;
        PADIR = 0xFF;
        PAOUT = 0x00;
        PBDIR = 0xFF;
        PBOUT = 0x00;
        PCDIR = 0xFF;
        PCOUT = 0x00;
        PDDIR = 0xFF;
        PDOUT = 0x00;
        PEDIR = 0xFF;
        PEOUT = 0x00;
    }
    
    void Turning_MECH(void)
    {
        //servo motor min 500 and max 3500
        TB0CCR0 = 20000-1;                         // PWM Period
        TB0CCTL1 = OUTMOD_7;                      // CCR1 reset/set p1.6
        TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR;  // SMCLK, up mode, clear TBR
    if(ADC_Result > 250)
    {
        TB0CCR1 = 3500;                            // CCR1 PWM duty cycle
    }
    else
    {
        TB0CCR1 = 500;                            // CCR1 PWM duty cycle
    }
    }
    void Dipping_SYS(void)
    {
        /*
         * Pin2.2 is connected to main headlight and control its auto dip mechanism
         */
        if(lux > 2000)
         {
             P2DIR |= BIT2;
             P2OUT |= BIT2;
         }
         else
        {
           P2OUT = 0X00;
        }
    }
    
    void ADC_CONFIG(void)
    {
        // Configure ADC
        ADCCTL0 |= ADCON ;                                // ADCON
        ADCCTL1 |= ADCSHS_2 | ADCCONSEQ_2;                        // repeat single channel; TB1.1 trig sample start
        ADCCTL2 &= ~ADCRES;                                       // clear ADCRES in ADCCTL
        ADCCTL2 |= ADCRES_2;                                      // 12-bit conversion results
        ADCMCTL0 |= ADCINCH_1 | ADCSREF_1;                        // A1 ADC input select; Vref=1.5V
        ADCIE |= ADCIE0;                                          // Enable ADC conv complete interrupt
        // Configure reference
        PMMCTL0_H = PMMPW_H;                                      // Unlock the PMM registers
        PMMCTL2 |= INTREFEN | REFVSEL_0;                          // Enable internal 1.5V reference
        __delay_cycles(400);
       // Delay(400000);                                            // Delay for reference settling
    }
    void ADC_capture(void)
    {
         ADCCTL0 |= ADCENC;                                        // ADC Enable
        // ADC conversion trigger signal - TimerB1.1 (32ms ON-period)
        TB1CCR0 = 1024-1;                                         // PWM Period
        TB1CCR1 = 512-1;                                          // TB1.1 ADC trigger
        TB1CCTL1 = OUTMOD_4;                                      // TB1CCR0 toggle
        TB1CTL = TBSSEL__ACLK | MC_1 | TBCLR;                     // ACLK, up mode
    
        __bis_SR_register(LPM0_bits | GIE);                       // Enter LPM3 w/ interrupts
    }
    
    void Delay(unsigned long int Value)
    {
        TB1CCTL0 |= CCIE;                             // TBCCR0 interrupt enabled
        TB1CCR0 = Value;
        TB1CTL |= TBSSEL__SMCLK | MC__CONTINUOUS;     // SMCLK, continuous mode
        __bis_SR_register(LPM0_bits | GIE);           // Enter LPM3 w/ interrupts
    }
  • Looking at your program flow, I see a hazard in having the ADC running (timer-triggered) in the background: If it happens to trigger in the middle of an I2C transaction, that transaction will see a false wakeup.

    Dealing with multiple wakeup sources can be done, but it requires a holistic design and certain number of state variables. In this application, I'm not sure that's worth the trouble.

    I'm a fan of timer-triggered ADC, but in this case a better strategy might be to run the ADC one-shot -- SHS=0 (ADCSC), CONSEQ=0 -- when you need it. The ADC is pretty quick, so it won't slow you down much.

    Also, you should be careful in using Delay() since its wakeup could also generate interference.

    Unsolicited: PA and P1/P2 are the same things. E.g. setting PADIR sets P1DIR and P2DIR and vice versa. You should either work with PA-PE or P1-P10, but not both.

  • What if i do not use ADC ISR and instead use ADCBUSY bit to check if my conversion is completed or not, without changing my previous setting except for disabling interrupts.

    Will this help?

    Edit 1:

    I tried this but my result in  ADC_Result is always 4095 and it is not changing.

    This is what i added in the program.

    void ADC_capture(void)
    {
        ADCCTL0 |= ADCENC;                                        // ADC Enable
            // ADC conversion trigger signal - TimerB1.1 (32ms ON-period)
            TB1CCR0 = 1024-1;                                         // PWM Period
            TB1CCR1 = 512-1;                                          // TB1.1 ADC trigger
            TB1CCTL1 = OUTMOD_4;                                      // TB1CCR0 toggle
            TB1CTL = TBSSEL__ACLK | MC_1 | TBCLR;                     // ACLK, up mode
         while ((ADCCTL1 & ADCBUSY) == 0x01);
         ADC_Result = ADCMEM0;
      //  __bis_SR_register(LPM0_bits | GIE);                       // Enter LPM3 w/ interrupts
    }

    rest everything is working fine. 

    I changed OPT3001 output pin from P2.2 to P4.7 as 2.2 was related to TB1ClK which i was using and it is working fine except the ADC.

  • void ADC_CONFIG(void)
    {
        ADCCTL0 |= ADCSHT_2 | ADCON;                             // ADCON, S&H=16 ADC clks
            ADCCTL1 |= ADCSHP;                                       // ADCCLK = MODOSC; sampling timer
            ADCCTL2 &= ~ADCRES;                                      // clear ADCRES in ADCCTL
            ADCCTL2 |= ADCRES_2;                                     // 12-bit conversion results
            ADCMCTL0 |= ADCINCH_1;                                   // A1 ADC input select; Vref=AVCC
            ADCIE |= ADCIE0;                                         // Enable ADC conv complete interrupt
    }
    void ADC_capture(void)
    {
        ADCCTL0 |= ADCENC | ADCSC;                           // Sampling and conversion start
    __bis_SR_register(LPM0_bits | GIE);                  // LPM0, ADC_ISR will force exit
    }

    This is what I did for single shot setting but still the result is same, my program is getting stuck in I2C_write() function 

    __bis_SR_register(LPM0_bits | GIE);                

    this line. 

  • I don't have an OPT3001 to work with, so I connected a simple software-based I2C slave which allows reading and writing from a "register" set but doesn't do much else.

    When I run this code (including your later changes) I don't see any hang, either in the ADC or the I2C, and the data (such as it is) looks as expected. That suggests that you're following the proper I2C sequences.

    A few observations:

    1) How do you know the program is hanging at that LPM statement? That statement is executed fairly frequently, and takes a little while, so maybe it's just probable to Pause there. It might be useful to add a progress indicator (LED e.g.) to the main loop.

    2) The OPT3001 has a bus timeout tTIMEO=28ms [Ref data sheet (SBOS681C) Sec 6.6]. If you hit a breakpoint in the middle of a transaction, it's highly probable that the device will reset its side, leaviing the master hanging.

    3) This looks a bit odd:

    >        case USCI_I2C_UCNACKIFG:
    >            UCB0CTL1 |= UCTXSTT;                      //resend start if NACK
    since if you get a NACK it seems unlikely that just restarting the transaction will do anything useful. Most likely it will just get another NACK and you'll loop forever. I suggest you treat this condition as fatal: set an Error variable, maybe issue a Stop, and wake up main.
    --------------------------------
    As a practical matter I can't really debug this further without your device. A scope would be useful. In the absence of a scope I get pretty good use out of a little circular trace that logs the UCB0IV contents each time through the ISR.
  • Thanks a lot for your help, there is one last thing(hopefully) in which i need your help.

    I did few changes and now both of my variables are changing accordingly but the servo motor is not updating with ADC_Result. I have to stop debugging to rotate my motor and then again start and I obviously do not want this to happen.

    Brief explanation of problem: ADC_Result is getting updated according to input on P1.1 but my motor is not rotating with it. If I pause debugging then it rotates according to last ADC_Result value.

    I have used ADC in Single-channel single-conversion, trigger conversion using ADCSC and TimerB0 is used to control servo motor.

    I m attaching the latest code here. 

    #include <msp430.h>                      // Generic MSP430 Device Include
    #include <stdint.h>
    
    #define OPT3001 0x44
    #define Result 0x00
    #define Configuration 0x01
    
    #define ONE_BYTE 0x1
    #define TWO_BYTES 0x2
    #define THREE_BYTES 0x3
    
    unsigned long lux;
    unsigned int ADC_Result;
    
    void GPIO_pin_configurations(void);
    void Turning_MECH(void);
    void Dipping_SYS(void);
    void ADC_capture(void);
    void ADC_CONFIG(void);
    
    void I2C_transmission_setup(unsigned char num_of_bytes);
    void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2);
    void I2C_setup_write(unsigned char slave_address, unsigned char register_address);
    void I2C_read(unsigned char slave_address);
    
    unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa);
    
    unsigned char TXData[3];
    unsigned char RXData[2];
    unsigned char ByteCtr;
    
    void main(void)
    {
        GPIO_pin_configurations();
    
        unsigned int exponent;
        unsigned int mantissa;
    
        //Write to Configuration Register (0x01) to set the operational mode of the OPT3001
        I2C_transmission_setup(THREE_BYTES);
        I2C_write(OPT3001, Configuration, 0xC6, 0x08);
         //Delay for 100 milliseconds to allow conversion process to complete
        __delay_cycles(100);
    
        ADC_CONFIG();
    
        while(1)
        {
              do
               {
                   CSCTL7 &= ~(XT1OFFG | DCOFFG);                        // Clear XT1 and DCO fault flag
                   SFRIFG1 &= ~OFIFG;
               }while (SFRIFG1 & OFIFG);                                 // Test oscillator fault flag
    
            Dipping_SYS();
    
            Turning_MECH();
    
            ADC_capture();
            I2C_transmission_setup(ONE_BYTE);
            I2C_setup_write(OPT3001, Result);
    
            I2C_transmission_setup(TWO_BYTES);
            I2C_read(OPT3001);
    
            //Extract the upper four bits of exponent and the lower 12 bits of mantissa from the raw result value
            exponent = RXData[0] >> 4;
            mantissa = (RXData[0] << 8 | RXData[1]) & 0x0FFF;
    
            //Take the exponent and mantissa values and calculate the corresponding lux value
            lux = convert_to_lux(exponent, mantissa);
        } // End background loop
    } // End main()
    
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB0IV,USCI_I2C_UCBIT9IFG))
      {
            case USCI_NONE: break;                        // Vector 0: No interrupts break;
            case USCI_I2C_UCALIFG: break;
            case USCI_I2C_UCNACKIFG:
                UCB0IFG = USCI_I2C_UCSTPIFG;
                __bic_SR_register_on_exit(LPM0_bits);     // Exit LPM0
              break;                                      // Vector 4: NACKIFG break;
            case USCI_I2C_UCSTTIFG: break;                // Vector 6: STTIFG break;
            case USCI_I2C_UCSTPIFG: break;                // Vector 8: STPIFG break;
            case USCI_I2C_UCRXIFG3: break;                // Vector 10: RXIFG3 break;
            case USCI_I2C_UCTXIFG3: break;                // Vector 14: TXIFG3 break;
            case USCI_I2C_UCRXIFG2: break;                // Vector 16: RXIFG2 break;
            case USCI_I2C_UCTXIFG2: break;                // Vector 18: TXIFG2 break;
            case USCI_I2C_UCRXIFG1: break;                // Vector 20: RXIFG1 break;
            case USCI_I2C_UCTXIFG1: break;                // Vector 22: TXIFG1 break;
    
            case USCI_I2C_UCRXIFG0:                       // Vector 24: RXIFG0 break;
    
                RXData[ByteCtr] = UCB0RXBUF;                // Load RX buffer
                ByteCtr++;                                  // Increment RX byte counter
    
                break;
    
            case USCI_I2C_UCTXIFG0:                       // Vector 26: TXIFG0 break;
    
                UCB0TXBUF = TXData[ByteCtr];            // Load TX buffer
                ByteCtr++;                              // Increment TX byte counter
    
              break;
    
            case USCI_I2C_UCBCNTIFG:                      // Vector 28: BCNTIFG
    
                __bic_SR_register_on_exit(LPM0_bits);     // Exit LPM0
    
                break;
    
            case USCI_I2C_UCCLTOIFG: break;               // Vector 30: clock low timeout
            case USCI_I2C_UCBIT9IFG: break;               // Vector 32: 9th bit
            default: break;
      }
    }
    // ADC interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC_VECTOR
    __interrupt void ADC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
        {
            case ADCIV_NONE:
                break;
            case ADCIV_ADCOVIFG:
                break;
            case ADCIV_ADCTOVIFG:
                break;
            case ADCIV_ADCHIIFG:
                break;
            case ADCIV_ADCLOIFG:
                break;
            case ADCIV_ADCINIFG:
                break;
            case ADCIV_ADCIFG:
                ADC_Result = ADCMEM0;
                __bic_SR_register_on_exit(LPM0_bits);            // Clear CPUOFF bit from LPM0
                break;
            default:
                break;
        }
    }
    
    void I2C_transmission_setup(unsigned char num_of_bytes)
    {
        //Configure USCI_B0 for I2C Mode and designate the number of bytes to be transmitted/received
    
        UCB0CTLW0 |= UCSWRST;                               // Software reset enabled
        UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;    // I2C master mode, SMCLK
        UCB0CTLW1 |= UCASTP_2;                              // Automatic stop generated
                                                            // after UCB0TBCNT is reached
        UCB0BRW = 0x8;                                      // baudrate = SMCLK / 8
        UCB0TBCNT = num_of_bytes;                           // number of bytes to be received
        UCB0CTL1 &= ~UCSWRST;                               // clear reset register
        UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE | UCBCNTIE;   // transmit and NACK interrupt enable
    }
    
    void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        TXData[0] = register_address;                   // Set the control register address
        TXData[1] = byte_1;                             // Set the Register Data LSB
        TXData[2] = byte_2;                             // Set the Register Data MSB
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 |= UCTR;                              // I2C TX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is TX'd
    }
    
    void I2C_setup_write(unsigned char slave_address, unsigned char register_address)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        TXData[0] = register_address;                   // Set the control register address
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 |= UCTR;                              // I2C TX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is TX'd
    }
    
    void I2C_read(unsigned char slave_address)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 &= ~UCTR;                             // I2C RX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is RX'd
    }
    
    unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa)
    {
        // Convert the Result Register into a lux measurement based on formula below:
        // lux = 0.01 * (2^E[3:0]) * R[11:0]
    
        unsigned int result;
        unsigned int count;
        unsigned long converted_lux;
    
        result = 1;
        for(count = exponent; count > 0; count--)
        {
            result = result * 2;
        }
        converted_lux = mantissa / 100;
        converted_lux *= result;
    
        return converted_lux;
    }
    
    void GPIO_pin_configurations(void)
    {
         WDTCTL = WDTPW | WDTHOLD;                                 // Stop WDT
         PM5CTL0 &= ~LOCKLPM5;
        // Configure ADC A1 pin
        P1SEL0 |= BIT1|BIT2|BIT3;
        P1SEL1 |= BIT1 | BIT6 | BIT7;
        P1DIR |= BIT6 | BIT7;                     // P1.6 and P1.7 output
    
        // Configure XT1 oscillator
        P2SEL1 |= BIT6 | BIT7;                                    // P2.6~P2.7: crystal pins
    
        // Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
        CSCTL4 = SELA__XT1CLK;                                    // Set ACLK = XT1; MCLK = SMCLK = DCO
        P1OUT = 0x00;
        /*Configuring Unused pins to avoid floating voltage
             and extra current consumption*/
        P3DIR = 0xFF;
        P3OUT = 0x00;
        P5DIR = 0xFF;
        P5OUT = 0x00;
        P6DIR = 0xFF;
        P6OUT = 0x00;
        P7DIR = 0xFF;
        P7OUT = 0x00;
        P8DIR = 0xFF;
        P8OUT = 0x00;
        P9DIR = 0xFF;
        P9OUT = 0x00;
        P10DIR = 0xFF;
        P10OUT = 0x00;
    }
    
    void Turning_MECH(void)
    {
        //servo motor min 500 and max 3500
        TB0CCR0 = 20000-1;                         // PWM Period
        TB0CCTL1 = OUTMOD_7;                      // CCR1 reset/set p1.6
        TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR;  // SMCLK, up mode, clear TBR
    
    if(ADC_Result > 500)
    {
        TB0CCR1 = 3500;                            // CCR1 PWM duty cycle
    }
    else
    {
        TB0CCR1 = 500;                            // CCR1 PWM duty cycle
    }
    }
    void Dipping_SYS(void)
    {
        /*
         * Pin4.7 is connected to main headlight and control its auto dip mechanism
         */
        if(lux > 2000)
         {
             P4DIR |= BIT7;
             P4OUT |= BIT7;
         }
         else
        {
           P4DIR |= BIT7;
           P4OUT = 0X00;
        }
    }
    
    void ADC_CONFIG(void)
    {
        // Configure ADC10
           ADCCTL0 |= ADCSHT_2 | ADCON;                              // ADCON, S&H=16 ADC clks
           ADCCTL1 |= ADCSHP;                                        // ADCCLK = MODOSC; sampling timer
           ADCCTL2 &= ~ADCRES;                                       // clear ADCRES in ADCCTL
           ADCCTL2 |= ADCRES_2;                                      // 12-bit conversion results
           ADCIE |= ADCIE0;                                          // Enable ADC conv complete interrupt
           ADCMCTL0 |= ADCINCH_1 | ADCSREF_1;                        // A1 ADC input select; Vref=1.5V
    
           // Configure reference module
           PMMCTL0_H = PMMPW_H;                                      // Unlock the PMM registers
           PMMCTL2 = INTREFEN | REFVSEL_0;                           // Enable internal 1.5V reference
           while(!(PMMCTL2 & REFGENRDY));                            // Poll till internal reference settles
    }
    
    void ADC_capture(void)
    {
        ADCCTL0 |= ADCENC | ADCSC;                            // Sampling and conversion start
            __bis_SR_register(LPM0_bits | GIE);                       // Enter LPM3 w/ interrupts
    }
    
    

  • Turning_MECH restarts the PWM timer every time it's called. My guess is that your while loop takes much less than 20ms to run, so the PWM never gets a chance to run.

    I suggest you initialize the PWM once, up at the beginning of the program, using some "idle" duty cycle (0? 500?) and only update CCR1 in the while loop. This will mostly do what you want, but with your while loop running as fast as it can you'll still tend to thrash the duty cycle. A physical thing like a motor is probably fine with an update 10-50 (rather than maybe 1000) times per second, so it's probably useful to introduce a delay into the while loop.

    Unsolicited:

    >            UCB0IFG = USCI_I2C_UCSTPIFG;.

    This doesn't send a Stop Condition. Try:

    >    UCB0CTLW0 |= UCTXSTP;

  • Thank you for your help, everything is working fine now.

    Changes done: Added delay in Turning_MECH() function and removed timer configuration from while loop.

    Adding latest program for reference.

    #include <msp430.h>                      // Generic MSP430 Device Include
    #include <stdint.h>
    
    #define OPT3001 0x44
    #define Result 0x00
    #define Configuration 0x01
    
    #define ONE_BYTE 0x1
    #define TWO_BYTES 0x2
    #define THREE_BYTES 0x3
    
    unsigned long lux;
    unsigned int ADC_Result;
    
    void GPIO_pin_configurations(void);
    void Turning_MECH(void);
    void PWM_Config(void);
    void Dipping_SYS(void);
    void ADC_capture(void);
    void ADC_CONFIG(void);
    
    void I2C_transmission_setup(unsigned char num_of_bytes);
    void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2);
    void I2C_setup_write(unsigned char slave_address, unsigned char register_address);
    void I2C_read(unsigned char slave_address);
    
    unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa);
    
    unsigned char TXData[3];
    unsigned char RXData[2];
    unsigned char ByteCtr;
    
    void main(void)
    {
        GPIO_pin_configurations();
    
        unsigned int exponent;
        unsigned int mantissa;
    
        //Write to Configuration Register (0x01) to set the operational mode of the OPT3001
        I2C_transmission_setup(THREE_BYTES);
        I2C_write(OPT3001, Configuration, 0xC6, 0x08);
         //Delay for 100 milliseconds to allow conversion process to complete
        __delay_cycles(100);
    
        PWM_Config();
        ADC_CONFIG();
    
        while(1)
        {
              do
               {
                   CSCTL7 &= ~(XT1OFFG | DCOFFG);                        // Clear XT1 and DCO fault flag
                   SFRIFG1 &= ~OFIFG;
               }while (SFRIFG1 & OFIFG);                                            // Test oscillator fault flag
    
            Dipping_SYS();
    
            Turning_MECH();
    
            ADC_capture();
            I2C_transmission_setup(ONE_BYTE);
            I2C_setup_write(OPT3001, Result);
    
            I2C_transmission_setup(TWO_BYTES);
            I2C_read(OPT3001);
    
            //Extract the upper four bits of exponent and the lower 12 bits of mantissa from the raw result value
            exponent = RXData[0] >> 4;
            mantissa = (RXData[0] << 8 | RXData[1]) & 0x0FFF;
    
            //Take the exponent and mantissa values and calculate the corresponding lux value
            lux = convert_to_lux(exponent, mantissa);
        } // End background loop
    } // End main()
    
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB0IV,USCI_I2C_UCBIT9IFG))
      {
            case USCI_NONE: break;                           // Vector 0: No interrupts break;
            case USCI_I2C_UCALIFG: break;
            case USCI_I2C_UCNACKIFG:
                UCB0CTLW0 |= UCTXSTP;
                __bic_SR_register_on_exit(LPM0_bits);        // Exit LPM0
              break;                                         // Vector 4: NACKIFG break;
            case USCI_I2C_UCSTTIFG: break;                   // Vector 6: STTIFG break;
            case USCI_I2C_UCSTPIFG: break;                   // Vector 8: STPIFG break;
            case USCI_I2C_UCRXIFG3: break;                   // Vector 10: RXIFG3 break;
            case USCI_I2C_UCTXIFG3: break;                   // Vector 14: TXIFG3 break;
            case USCI_I2C_UCRXIFG2: break;                   // Vector 16: RXIFG2 break;
            case USCI_I2C_UCTXIFG2: break;                   // Vector 18: TXIFG2 break;
            case USCI_I2C_UCRXIFG1: break;                   // Vector 20: RXIFG1 break;
            case USCI_I2C_UCTXIFG1: break;                   // Vector 22: TXIFG1 break;
    
            case USCI_I2C_UCRXIFG0:                          // Vector 24: RXIFG0 break;
    
                RXData[ByteCtr] = UCB0RXBUF;                 // Load RX buffer
                ByteCtr++;                                   // Increment RX byte counter
    
                break;
    
            case USCI_I2C_UCTXIFG0:                          // Vector 26: TXIFG0 break;
    
                UCB0TXBUF = TXData[ByteCtr];                 // Load TX buffer
                ByteCtr++;                                   // Increment TX byte counter
    
              break;
    
            case USCI_I2C_UCBCNTIFG:                         // Vector 28: BCNTIFG
    
                __bic_SR_register_on_exit(LPM0_bits);        // Exit LPM0
    
                break;
    
            case USCI_I2C_UCCLTOIFG: break;                  // Vector 30: clock low timeout
            case USCI_I2C_UCBIT9IFG: break;                  // Vector 32: 9th bit
            default: break;
      }
    }
    // ADC interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC_VECTOR
    __interrupt void ADC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
        {
            case ADCIV_NONE:
                break;
            case ADCIV_ADCOVIFG:
                break;
            case ADCIV_ADCTOVIFG:
                break;
            case ADCIV_ADCHIIFG:
                break;
            case ADCIV_ADCLOIFG:
                break;
            case ADCIV_ADCINIFG:
                break;
            case ADCIV_ADCIFG:
                ADC_Result = ADCMEM0;
                __bic_SR_register_on_exit(LPM0_bits);        // Clear CPUOFF bit from LPM0
                break;
            default:
                break;
        }
    }
    
    void I2C_transmission_setup(unsigned char num_of_bytes)
    {
        //Configure USCI_B0 for I2C Mode and designate the number of bytes to be transmitted/received
    
        UCB0CTLW0 |= UCSWRST;                               // Software reset enabled
        UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;             // I2C master mode, SMCLK
        UCB0CTLW1 |= UCASTP_2;                              // Automatic stop generated
                                                            // after UCB0TBCNT is reached
        UCB0BRW = 0x8;                                      // baudrate = SMCLK / 8
        UCB0TBCNT = num_of_bytes;                           // number of bytes to be received
        UCB0CTL1 &= ~UCSWRST;                               // clear reset register
        UCB0IE |= UCTXIE0 | UCRXIE0 | UCNACKIE | UCBCNTIE;   // transmit and NACK interrupt enable
    }
    
    void I2C_write(unsigned char slave_address, unsigned char register_address, unsigned char byte_1, unsigned char byte_2)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        TXData[0] = register_address;                   // Set the control register address
        TXData[1] = byte_1;                             // Set the Register Data LSB
        TXData[2] = byte_2;                             // Set the Register Data MSB
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 |= UCTR;                              // I2C TX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is TX'd
    }
    
    void I2C_setup_write(unsigned char slave_address, unsigned char register_address)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        TXData[0] = register_address;                   // Set the control register address
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 |= UCTR;                              // I2C TX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is TX'd
    }
    
    void I2C_read(unsigned char slave_address)
    {
        UCB0I2CSA = slave_address;                      // Set the slave address
        ByteCtr = 0;                                    // Load byte counter
        while (UCB0CTLW0 & UCTXSTP);                    // Ensure stop condition got sent
        UCB0CTLW0 &= ~UCTR;                             // I2C RX
        UCB0CTLW0 |= UCTXSTT;                           // I2C start condition
        __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts
                                                        // Remain in LPM0 until all data
                                                        // is RX'd
    }
    
    unsigned long convert_to_lux(unsigned int exponent, unsigned int mantissa)
    {
        // Convert the Result Register into a lux measurement based on formula below:
        // lux = 0.01 * (2^E[3:0]) * R[11:0]
    
        unsigned int result;
        unsigned int count;
        unsigned long converted_lux;
    
        result = 1;
        for(count = exponent; count > 0; count--)
        {
            result = result * 2;
        }
        converted_lux = mantissa / 100;
        converted_lux *= result;
    
        return converted_lux;
    }
    
    void GPIO_pin_configurations(void)
    {
         WDTCTL = WDTPW | WDTHOLD;                                    // Stop WDT
         PM5CTL0 &= ~LOCKLPM5;
        // Configure ADC A1 pin
        P1SEL0 |= BIT1|BIT2|BIT3;
        P1SEL1 |= BIT1 | BIT6 | BIT7;
        P1DIR |= BIT6 | BIT7;                                         // P1.6 and P1.7 output
    
        // Configure XT1 oscillator
        P2SEL1 |= BIT6 | BIT7;                                        // P2.6~P2.7: crystal pins
    
        // Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
        CSCTL4 = SELA__XT1CLK;                                        // Set ACLK = XT1; MCLK = SMCLK = DCO
        P1OUT = 0x00;
        /*Configuring Unused pins to avoid floating voltage
             and extra current consumption*/
        P3DIR = 0xFF;
        P3OUT = 0x00;
        P5DIR = 0xFF;
        P5OUT = 0x00;
        P6DIR = 0xFF;
        P6OUT = 0x00;
        P7DIR = 0xFF;
        P7OUT = 0x00;
        P8DIR = 0xFF;
        P8OUT = 0x00;
        P9DIR = 0xFF;
        P9OUT = 0x00;
        P10DIR = 0xFF;
        P10OUT = 0x00;
    }
    void PWM_Config(void)
    {       //Interfacing two servo motors using TB0CCR1 and TB0CCR2  
            TB0CCR0 = 20000-1;                                                                // PWM Period
            TB0CCTL1 = OUTMOD_7;                                                        // CCR1 reset/set P1.6
            TB0CCTL2 = OUTMOD_7;                                                        // CCR2 reset/set P1.7
            TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR;                  // SMCLK, up mode, clear TBR
    }
    void Turning_MECH(void)
    {
        //servo motor min 500 and max 3500
    if((3000 < ADC_Result) && (ADC_Result < 4095))
    {
        TB0CCR1 = 3300;                                               // CCR1 PWM duty cycle
        TB0CCR2 = 3300;                                               // CCR2 PWM duty cycle
    }
    else if((2000 < ADC_Result) && (ADC_Result < 2999))
    {
        TB0CCR1 = 2300;
        TB0CCR2 = 2300;
    }else if((1000 <= ADC_Result) && (ADC_Result <1999))
    {
        TB0CCR1 = 1500;
        TB0CCR2 = 1500;
    }else if(ADC_Result <= 500)
    {
        TB0CCR1 = 500;
        TB0CCR2 = 500;
    }
    __delay_cycles(10);                                              //10 ms delay for servo motor
    }
    void Dipping_SYS(void)
    {
        /*
         * Pin4.7 is connected to main headlight and control its auto dip mechanism
         */
        if(lux > 2000)
         {
             P4DIR |= BIT7;
             P4OUT |= BIT7;
         }
         else
        {
           P4DIR |= BIT7;
           P4OUT = 0X00;
        }
    }
    
    void ADC_CONFIG(void)
    {
        // Configure ADC10
           ADCCTL0 |= ADCSHT_2 | ADCON;                              // ADCON, S&H=16 ADC clks
           ADCCTL1 |= ADCSHP;                                        // ADCCLK = MODOSC; sampling timer
           ADCCTL2 &= ~ADCRES;                                       // clear ADCRES in ADCCTL
           ADCCTL2 |= ADCRES_2;                                      // 12-bit conversion results
           ADCIE |= ADCIE0;                                          // Enable ADC conv complete interrupt
           ADCMCTL0 |= ADCINCH_1 | ADCSREF_1;                        // A1 ADC input select; Vref=1.5V
    
           // Configure reference module
           PMMCTL0_H = PMMPW_H;                                      // Unlock the PMM registers
           PMMCTL2 = INTREFEN | REFVSEL_0;                           // Enable internal 1.5V reference
           while(!(PMMCTL2 & REFGENRDY));                            // Poll till internal reference settles
    }
    
    void ADC_capture(void)
    {
        ADCCTL0 |= ADCENC | ADCSC;                                   // Sampling and conversion start
        __bis_SR_register(LPM0_bits | GIE);                          // Enter LPM3 w/ interrupts
    }
    
    

**Attention** This is a public forum