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.

MSP430F249-EP: Is this MCU enough to measure 40kHZ frequency?

Part Number: MSP430F249-EP
Other Parts Discussed in Thread: MSP430F249, GRACE, MSP430F2619, MSP430F169

Hello

I'm wondering if this MCU can measure 40kHz frequency accurately.

Also I have one more question.

To measure a frequency, I should use Timer capture mode?

Thanks for your attention to my question!

Have a wonderful day

  • Hello Jaeseo,

    many thanks for your interest in our product. Yes, you can measure frequencies with an MSP430 and specifically MSP430F249-EP. But the question is whta your accuracy requirements are? If you give us more details on this, we can be also more specific in our answer.

    And, yes, one method is using a Capture input of the timer.

    Best regards

    Peter

  • Measuring 40kHz using Capture is possible, but not trivial. Plan to (a) run the CPU (MCLK) >= 8MHz (b) not do much else on the MCU. The accuracy depends on the accuracy of your reference clock (SMCLK).

    Measuring 40kHz using frequency-counting (TACLK/TBCLK) has much lower CPU requirements, but the lower sampling rate means slower step (change) response. The accuracy will be dominated by your measurement period (quantization error).

  • Hello Jaeseo,

    please let me know, whether you still need support on this. Many thanks in advance.

    Best regards

    Peter

  • Thanks for your support.

    Sorry to late reply.

    I was working on other tasks.

    I have some questions for measuring a frequency.

    1.Could I ask why you refered to MSP430F249-EP? Is there any specific difference from other F249?

    My measurement goal is 40000hz+-130hz. Could I be satisfied with my goal by this MCU?

    2. I wrote a pseudo code. It worked in another company's MCU. 

    I will be trying to integrate in MSP430F249 with Grace.

    Could I possible? Especially I would like to know how can I get a clock frequency. Which register has this value?

    if (Is_First_Captured==0)
    {
    	IC_Value1 = ReadCapturedValue();
    	Is_First_Captured =1;
    }
    else if (Is_First_Captured)
    {
    	IC_Value2 = ReadCapturedValue();
    	if (IC_Value2 > IC_Value1)
    	{
    		Difference = IC_Value2-IC_Value1;
    	}
    	else if (IC_Value2 < IC_Value1)
    	{
    		Difference = ((0xffff-IC_Value1)+IC_Value2) +1;
    	}
    	else
    	{
    		Error_Handler();
    	}
    
    	Frequency = Get_Using_CLK_Freq()/Difference;
    
    	Is_First_Captured = 0;
    }

    3. I did some input capture test as following Grace's input capture instruction.

    How do I start a input capture mode?

    Just enabling a interrupt or 

    I should be initialized by code.

    I read MSP430F249 user's guide and found 12.2.4.1 Capture initiated by Software

    I read this section. but I could not get it. Could you explain more or show me example? 

     Thanks for your support

  • I suppose that Peter mentioned the MSP430F249-EP since that's what you asked about. As far as I know the F249 and the F249-EP are functionally equivalent.

    1) My calculator says that +/-130Hz in 40kHz is 0.3% -- fairly tight for the DCO, which is good for  about 1%. Glancing at the data sheet (SLAS547I) I don't see mention of a high-speed crystal oscillator.

    2) When computing the delta between edges, use Continuous mode and store the captured time values as "unsigned" (16-bit). Then just subtract each value from the previous one; 16-bit subtraction underflow will do the correct thing.

    There are 4x calibrated DCO settings (CALDCO/CALBC1). These are described in User Guide (SLAU144J) Sec 5.2.5.2.

    3) I don't see a capture example in the F249 Examples in Resource Explorer. In the examples for the G2553, I see msp430g2xx3_ta_21.c, which will give you the general idea (the G2 series is really part of the F2 series).

    http://dev.ti.com/tirex/explore/node?node=AFB5DJx-bgFTI4ERhplnuw__IOGqZri__LATEST

  • Hi Jaesseo,

    have your questions been sufficiently addressed by Bruce's correct recommendations?

    One point to add from my side, yes, there is no capture example in the MSP430F249 examples, but in the MSP430F2619 examples you can find a more complex example for VLO driven captures. The name of the code example is MSP430x261x_vlo_capture.c

    Please let us know, whether there's still something we can do for you on this. Many thanks in advance.

    Best regards

    Peter

  • Thanks for your support.

    I also had written a code for MSP430F169. last week. 

    Because we didn't had MSP430249 yet. 

    So I used this example for measuring a frequency. and It worked well

    //For MSP430F169, It is working well
    
    #include <msp430.h>
    
    volatile unsigned int CounterValue = 0;
    volatile unsigned int StoredCount = 0;
    unsigned int Result = 0;
    
    
    int main(void)
    {
      volatile unsigned int i;
      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
      for (i=0; i<20000; i++)                   // Delay for crystal stabilization
      {
      }
      P1DIR = 0x01;                             // Set P1.0 out,1.1 input dir
      P1OUT &= ~0x01;                           // LED off
      P1SEL = 0x02;                             // Set P1.1 to TA0
    
    
      CCTL0 = CM_1 + SCS + CCIS_0 + CAP + CCIE; // Rising edge + CCI0A (P1.1)
                                                // + Capture Mode + Interrupt
    
      TBCCTL0 = CCIE;                           // CCR0 interrupt enabled
      TBCCR0 = 2000;
    
    
      __bis_SR_register(GIE);       // LPM0 + Enable global ints
    
      while(1)
      	{
    		TACTL = TASSEL_2 + MC_2;  				// Start timer
    		TBCTL = TBSSEL_2 + MC_1;                  // SMCLK, contmode
    		while(CounterValue != 400);	// Wait while CounterValue is not equal to 400
    		TA0CTL &= ~(MC1+MC0);				// Stop timer
    		TB0CTL &= ~(MC1+MC0);				// Stop timer
    		Result = StoredCount;		// Store frequency in Result
    		CounterValue = 0;			// Zero CounterValue
    		StoredCount = 0;			// Zero StoredCount
    		TA0R = 0;					// Zero Timer_A0 register
    		TB0R = 0;					// Zero Timer_A1 register
      	}
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMERA0_VECTOR
    __interrupt void TimerA0(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMERA0_VECTOR))) TimerA0 (void)
    #else
    #error Compiler not supported!
    #endif
    {
    	StoredCount++;
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMERB0_VECTOR
    __interrupt void TimerB0(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMERB0_VECTOR))) TimerB0 (void)
    #else
    #error Compiler not supported!
    #endif
    {
    	CounterValue++;
    }

    Now I get a MSP430F249.

    So I did a test this code with MSP430F249

    Code which is below was not working well. Only TimerB was working well (counting for 1s).

    Input capture did not work.

    I don't know what is wrong.

    Also I tried an input capture with Grace.It was failed.

    How do I solve this problem?

    thanks in advance

    //MSP430F249, It is not working
    #include <msp430.h> 
    
    /*
     * main.c
     */
    
    volatile unsigned int CounterValue = 0;
    volatile unsigned int StoredCount = 0;
    unsigned int Result = 0;
    
    
    int main(void) {
        volatile unsigned int i;
        WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
    
        DCOCTL = 0x00;
        BCSCTL1 = CALBC1_1MHZ;      /* Set DCO to 1MHz */
        DCOCTL = CALDCO_1MHZ;
    
        P1DIR = 0x01;                             // Set P1.0 out,1.1 input dir
        P1OUT &= ~0x01;                           // LED off
        P1SEL = 0x02;                             // Set P1.1 to TA0
    
        CCTL0 = CM_1 + SCS + CCIS_0 + CAP + CCIE; 
    // Rising edge + CCI0A (P1.1) // + Capture Mode + Interrupt TBCCTL0 = CCIE; // CCR0 interrupt enabled TBCCR0 = 2000; __bis_SR_register(GIE); // LPM0 + Enable global ints while(1) { TACTL = TASSEL_2 + MC_2; // Start timer TBCTL = TBSSEL_2 + MC_1; // SMCLK, contmode while(CounterValue != 50); // Wait while CounterValue is not equal to 400 TA0CTL &= ~(MC1+MC0); // Stop timer TB0CTL &= ~(MC1+MC0); // Stop timer Result = StoredCount; // Store frequency in Result CounterValue = 0; // Zero CounterValue StoredCount = 0; // Zero StoredCount TA0R = 0; // Zero Timer_A0 register TB0R = 0; // Zero Timer_A1 register } } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=TIMERA0_VECTOR __interrupt void TimerA0(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(TIMERA0_VECTOR))) TimerA0 (void) #else #error Compiler not supported! #endif { /* switch(__even_in_range(TAIV,10)) { case TAIV_NONE: break; // Vector 0: No interrupt case TAIV_TACCR1: // Vector 2: TACCR1 CCIFG if (TACCTL0 & CCI) // Capture Input Pin Status { StoredCount++; } break; case TAIV_TACCR2: break; // Vector 4: TACCR2 CCIFG case TAIV_TAIFG: break; // Vector 10: TAIFG default: break; } */ StoredCount++; } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=TIMERB0_VECTOR __interrupt void TimerB0(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(TIMERB0_VECTOR))) TimerB0 (void) #else #error Compiler not supported! #endif { CounterValue++; }
  • Hi Jaeseo,

    many thanks for the update, but could you please be more specific on what did not work as expected? And what is your expectation, how the code / measurement method should work?

    Best regards

    Peter

  • Hello Peter

    I used TimerA and TimerB.

    For measuring frequency, TimerA was used as input captuer and TimerB was used as counter of 1 sec.

    During TimerB is increasing, Timer A should counter rising edge of input capture.

    To work well, Both timer interrupt have to work. However, It is only Timer B was working.

    TImer A input captuer interrupt was not working.

    Thanks in advance.

  • I tested again. I think that it works well.

    Thanks for your supporting!

  • Another way to do frequency counting is by bringing your signal into TACLK (P1.0) rather than TA0 (P1.1), setting TASSEL=0 (TACLK) rather than TASSEL=2 (SMCLK), and not using CAPture.

    With this method, the timer keeps count for you in TA0R (rather than StoredCount) and you don't have to take an interrupt for each edge.

    You can then e.g. use TACCR1 to interrupt when the count reaches, say, 400.

  • Hello Jaeseo,

    if I understood your response, you have been able to resolve the last issues.

    Please consider Bruce's suggestion, feeding the 40kHz as clock source into one of the Timers, and using CCR timing for a deterministic measurement period. This definitely makes sense.

    Best regards

    Peter