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.

MSP430G2x33 VLO calibration without TI library

Other Parts Discussed in Thread: MSP430G2533, MSP430G2333

Hi,

I want to use VLO clock for my timer purpose but from datasheet I see there is huge VLO frequency drift between 4kHz to 20kHz . TI provides library function to calibrate VLO for timer accuracy. Is there any code which I can refer for calibrating VLO without TI library function?

  Thanks,

  • Hi Raj,

    The VLO library provides the assembly source for the calibration function. In case you don't know 430 assembly language, here's a brief description of how it works.

    It first activates the 1MHz calibrated DCO setting for MCLK and SMCLK, then configures ACLK to be sourced from VLO with a divider of 8. Next it configures TimerA to count DCO clock cycles and capture on the rising edges of ACLK. It then busy-waits for the timer to capture and calculates the difference between two consecutive measurements.

    The resulting value is the number of 1MHz cycles elapsed during eight cycles of the VLO. That's equivalent to the number of 8MHz cycles per VLO clock, which is the output value provided by the library code.

    Something to be wary of is the fact that MCLK frequency and CPU duty cycle affect the heat output of the CPU core. That in turn changes the VLO frequency. If the rest of your code spends most of its time in low power mode you may need to change the calibration method to account for this.

    Hope that helps,

    Rob

  • Hi Rob,

    I found this for F series controller , I configured my controller to work at 8 MHz (Clock Settings) at start up but I see in below mentioned code this clock settings are changed to 1 MHz while calculating VLO calibration frequency there after I am not able to use my serial port . 

    I tried to reset back my controller to 8MHz once I finish reading VLO calibration but now nothing is working . Any clue?

    #include <msp430x26x.h>

    unsigned int dco_delta;

    // Function Prototype
    unsigned int  measureVLO( void );

    void main(void)
    {
      WDTCTL = WDTPW +WDTHOLD;                  // Stop Watchdog Timer
      P1DIR |= 0x01;                            // P1.0 output
     
      dco_delta = measureVLO();                 // dco delta = number of
                                                // 1MHz cycles in 8 VLO cycles
      //Clock settings: DCO freq = 1MHz; ACLK = VLO/8
     
      // Timer A interval interrupt setup
      TACCTL0 = CCIE;                           // TACCR0 interrupt enabled
      TACCR0 = (1000000 / dco_delta);             
      TACTL = TASSEL_1 + MC_1;                  // ACLK, upmode
      P1OUT = 0x01;
     
      _BIS_SR(LPM3_bits + GIE);                 // Enter LPM3 w/ interrupt

    }

    // Timer_A0 Interrupt Vector
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A0(void)
    {
      P1OUT ^= 0x01;                            // Toggle P1.0
    }

    // This function measures the number of 1MHz clock pulses in 8 VLO cycles
    unsigned int  measureVLO( void )
    {
      static unsigned int start_count, stop_count;
      // Clock settings to achieve the good resolution for VLO freq measurement
      BCSCTL1 = CALBC1_1MHZ;                    // Set range
      DCOCTL = CALDCO_1MHZ;                     // Set DCO step + modulation
      TACCTL2 = CM_1+CCIS_1+CAP;                // CAP, ACLK
      TACTL = TASSEL_2+MC_2+TACLR;              // SMCLK, cont-mode, clear
      BCSCTL3 |= LFXT1S_2;                      // ACLK = VLO  
      BCSCTL2 = 0x0;
      BCSCTL1 |= DIVA_3;                        // ACLK = VLO/8
     
      TACCTL2 &= ~CCIFG;                        // Clear capture flag
      while (!(CCIFG & TACCTL2));               // Test capture flag to skip 1st cycle
      TACCTL2 &= ~CCIFG;                        // Clear capture flag
     
      while (!(CCIFG & TACCTL2));               // Test capture flag to skip 2nd cycle
      start_count = TACCR2;                     // save hardware captured value
      TACCTL2 &= ~CCIFG;                        // Clear capture flag
     
      while (!(CCIFG & TACCTL2));               // Test capture flag to capture a good clock
      TACTL &= ~MC_3;                           // Stop timer
      stop_count = TACCR2;
      return(stop_count - start_count);         // return
    }

  • Hi Raj,

    I can't see anything obvious in that code which would cause problems with serial output. It appears to just be a direct translation of TI's library code into C (except it lacks the clean-up steps which restore the original clock settings on function exit).

    Would you mind posting the rest of your code so we can see if anything might be affected by the calibration function?

    Rob

  • Hi Rob,

    I just verified , it is this piece of code which is not working and controller is getting hanged. I think this code doesn't work for MSP430G2xx3 based controllers.

    TACCTL2 = CM_1+CCIS_1+CAP;                // CAP, ACLK
      TACTL = TASSEL_2+MC_2+TACLR;              // SMCLK, cont-mode, clear
      BCSCTL3 |= LFXT1S_2;                      // ACLK = VLO  
      BCSCTL2 = 0x0;
      BCSCTL1 |= DIVA_3;                        // ACLK = VLO/8
     
      TACCTL2 &= ~CCIFG;                        // Clear capture flag
      while (!(CCIFG & TACCTL2));               // Test capture flag to skip 1st cycle
      TACCTL2 &= ~CCIFG;                        // Clear capture flag
     
      while (!(CCIFG & TACCTL2));               // Test capture flag to skip 2nd cycle
      start_count = TACCR2;                     // save hardware captured value
      TACCTL2 &= ~CCIFG;                        // Clear capture flag
     
      while (!(CCIFG & TACCTL2));               // Test capture flag to capture a good clock
      TACTL &= ~MC_3;                           // Stop timer
      stop_count = TACCR2;
      return(stop_count - start_count);         // return

  • Hi Rob,

    I debugged this issue and I see controller is not able to come out of while loop , it is stuck there without any response.

    I referred MSP430G2x33 datasheet and I don't see anything wrong in this code but I am not sure why it is hanging out there.

       TACCTL1 &= ~CCIFG;                        // Clear capture flag
        while (!(CCIFG & TACCTL1));               // Test capture flag to skip 1st cycle
        TACCTL1 &= ~CCIFG;                        // Clear capture flag

  • It seems that the correct CCTL/CCR registers to use for VLO calibration vary per chip. The sample code you found uses TA0CCTL2, but on the msp430g2x33 you need to use TA0CCTL0 instead. The TI library code is set up to handle this correctly.

    EDIT: To explain, the while loop is never exited because the capture is never triggered. That's because the capture input selected isn't the ACLK (as required for the code to work). Table 12 in the msp430g2533 datasheet lists the input/output connections for the Timer_A0 module, and shows that the only module block that takes ACLK as input is CCR0.

  • Hi Robert,

    You were right, TA0CCTL0 should be used for ACLK measurement, now code works but I am not getting 1 sec interrupt instead it is around 400 to 900ms which is not stable . Below is my code for your reference.

    #include <msp430g2333.h>

    unsigned int dco_delta;
    // Function Prototype
    unsigned int  measureVLO( void );

    void main()
    {

        /* Stop WDT */
        WDTCTL  =  WDTPW | WDTHOLD;
        /*
            8 MHz Clock settings for UART
        */
        
        BCSCTL1 |= DIVA0;                     // ACLK/1
        BCSCTL2 |= SELM_0 + DIVM_0;          // MCLK = DCOCLK , DIVISOR= /1 (8MHZ)
        BCSCTL3 |= LFXT1S_2;                  // Low frequency clock selector
        
        dco_delta = measureVLO();      
        CCTL0 = CCIE;                                // TACCR0 interrupt enabled
        CCR0  = (8000000 / dco_delta);            // Timer clock delta with VLO calibration
        TACTL = TASSEL_1 + MC_1;                  // ACLK, upmode
        
        _enable_interrupts();
        
        
         _BIS_SR(LPM3_bits + GIE);                 // Enter LPM3 w/ interrupt
    }


    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A (void)
    {
        P2OUT ^= LED;    
    }


    unsigned int measureVLO(void)
    {
      static unsigned int start_count, stop_count;
    //  Clock settings to achieve the good resolution for VLO freq measurement
      IFG1 &= ~OFIFG;                              // Clear OSCFault flag
      BCSCTL1 = CALBC1_1MHZ;                    // Set range
      DCOCTL  = CALDCO_1MHZ;                     // Set DCO step + modulation
      if (CALBC1_1MHZ == 0xFF)                    // If calibration constant erased
      {
             while(1);                           // do not load, trap CPU!!
      }
     
        P2OUT &= ~LED;
        P2DIR |= LED;

        TACCTL0 = CM_1+ CCIS_1+ CAP;              // CAP, ACLK
        TACTL = TASSEL_2+MC_2+TACLR;              // SMCLK, cont-mode, clear
        BCSCTL3 |= LFXT1S_2;                      // ACLK = VLO
        BCSCTL2 = 0x0;
        BCSCTL1 |= DIVA_3;                        // ACLK = VLO/8

        TACCTL0 &= ~CCIFG;                        // Clear capture flag
        while (!(CCIFG & TACCTL0));               // Test capture flag to skip 1st cycle
        TACCTL0 &= ~CCIFG;                        // Clear capture flag

        while (!(CCIFG & TACCTL0));               // Test capture flag to skip 2nd cycle
        start_count = TACCR2;                     // save hardware captured value
        TACCTL0 &= ~CCIFG;                        // Clear capture flag

        while (!(CCIFG & TACCTL0));               // Test capture flag to capture a good clock
        TACTL &= ~MC_3;                           // Stop timer
        stop_count = TACCR0;

        TACCTL0 = 0;                              // Stop TACCR0
        TACTL = 0;                                // Stop Timer_A
        
        /*
            RESTORE BACK DEFAULT CALIBRATION SETTINGS
        */
        BCSCTL1 =  CALBC1_8MHZ;            // Run at 8 MHz
        DCOCTL  =  CALDCO_8MHZ;            // Run at 8 MHz
        if (CALBC1_8MHZ==0xFF)                        // If calibration constant erased
          {
            while(1);                               // do not load, trap CPU!!
          }
        BCSCTL1 |= DIVA0;                     // ACLK/1
        BCSCTL2 |= SELM_0 + DIVM_0;          // MCLK = DCOCLK , DIVISOR= /1 (8MHZ)
        BCSCTL3 |= LFXT1S_2;                  // Low frequency clock selector


        return(stop_count - start_count);         // return

    }

  • Modified below code, VLO calibration is working . Thanks Rob for you help :)

    while (!(CCIFG & TACCTL0));               // Test capture flag to skip 2nd cycle
        start_count = TACCR2;                     // save hardware captured value
        TACCTL0 &= ~CCIFG;                        // Clear capture flag

    to

    while (!(CCIFG & TACCTL0));               // Test capture flag to skip 2nd cycle
        start_count = TACCR0;                     // save hardware captured value
        TACCTL0 &= ~CCIFG;                        // Clear capture flag

**Attention** This is a public forum