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.

Frequency counter based on CC430 timer

Hi,

I am trying to develop a frequency counter based on TimerA's capture mode. I set up CCI with 1kHz for avoiding missing captures and timer with 26MHz radio clock, which I think is faster and provides a more accurate reference.

Till now I tried with some slower clocks, the accuracy looks great. But when I playing with 1kHz and 26MHz, the count value is having a larger range thus the frequency I measured is not accurate and stable enough. 

Is there any way to improve this situation? And if there is any algorithm I could put in to improve my frequency counter?

Below is my interrupt service code, if you have a better solution than my interrupt please let me know and give me some hints!

#define NCAPTURES 32 // Number of captures to accumulate
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMERA1_ISR ( void ) // ISR for CCIFGn and TAIFG
{
        static int Captures = 0; // Number of captures accumulated
        volatile unsigned   int StartTime ; // Time at start of sampling

        if ( TA0IV == TA0IV_TACCR2 ) { // CCIFG4 vector (4)
               switch ( Captures ) {
               case 0: // Starting new sequence of captures
                     StartTime = TA0CCR2 ; // Starting time
                     Captures = NCAPTURES ; // Initialize down counter
                      break ;
               case 1: // Final capture of sequence
                     printf("num=%u\r\n" ,TA0CCR2 - StartTime);
                     Captures = 0; // Finished
                     //TA0CCTL2=~CCIE; // Disable further interrupts
                      break ;
        default : // Sequence of captures continues
       --Captures ;
        break ;
              }
       }
}

Thanks in advance!

  • Perhaps you are getting count pulse slips - because you can't measure anything above 25MHz on this chip because that's max frequency of timer input clock. More about counting and measuring frequencies.

  • Ilmars said:

    Perhaps you are getting count pulse slips - because you can't measure anything above 25MHz on this chip because that's max frequency of timer input clock. More about counting and measuring frequencies.

    I measured 48 MHz (timer input clock) with 24 MHz MCLK (XT2).
  • >I measured 48 MHz (timer input clock) with 24 MHz MCLK (XT2).
    Yes, msp430 have async clock inputs for timer and yes, you were running msp430 out of spec, most probably at the room temperature. Anyway congrats! :)

    user4001754, perhaps by just following zrno's work you will have all your questions answered.
  • Thanks zrno, your code looks quite simple and does not use interrupt, right? I think the capture mode provides a similar counter feature and with its interrupts I can let the processors do some other tasks when I want to implement the frequency counter into other applications. How do you think?

  • user4001754 said:

    Thanks zrno, your code looks quite simple and does not use interrupt, right? I think the capture mode provides a similar counter feature and with its interrupts I can let the processors do some other tasks when I want to implement the frequency counter into other applications. How do you think?

    My implementation is based on 2 counters, one for counting input pulses (TA1) and another for time (TA0). Interrupts are used only for timers overflow (TAR value change from 0FFFFh to 00000h) so basically TAR is extended to one more word. This is used to cover complete measuring range from few kHz to 50 MHz.

    http://forum.43oh.com/topic/3317-msp430f550x-based-frequency-meter/?p=29031

  • What is the range of the frequency you are trying to measure?

    Using your method, the CPU may not have enough time to handle the interrupts in time if the input frequency is higher than say 1/100 of the MCLK frequency. On the other hand, if the input frequency is very slow, you have to face 16-bit timer counter overflow.
  • Thanks old cow. 

    I'm trying to use the 26MHz clock, which is theoretically fast enough, to measure all the other clocks on the board (from about several kHz to several MHz).

    For now I am focusing on using the 26MHz clock to measure a 32kHz clock. Then I set the 32kHz as the capture clock and the 26MHz as the timer input. Then for every interrupt on the rising edge of the capture clock I timestamp the value of TA0R, then the difference between the timestamp will be the count of 26MHz clock cycles in one period of the 32kHz clock. Do you think I am doing in the right way?

    Then in order to avoid missing the capture interrupt, I have to scale down the 32kHz clock to make sure it is much slower than the system clock for interrupts. Overflow is acceptable because we can take it into account.

    But I want to know if there is any other way to improve accuracy other than just scale the clocks down, perhaps dividing clocks will also bring in errors.

  • user4001754 said:
    I'm trying to use the 26MHz clock, which is theoretically fast enough, to measure all the other clocks on the board (from about several kHz to several MHz).

    Yes. For example use the method Zrno used. But not the method you described in your first post of this thread.

    user4001754 said:
    For now I am focusing on using the 26MHz clock to measure a 32kHz clock. Then I set the 32kHz as the capture clock and the 26MHz as the timer input. Then for every interrupt on the rising edge of the capture clock I timestamp the value of TA0R, then the difference between the timestamp will be the count of 26MHz clock cycles in one period of the 32kHz clock. Do you think I am doing in the right way?

    Yes, This can work. But do not use the CPU to read TA0R. Read the hardware captured value in TA0CCRx. The resolution will not be very good because the expected count will be ~800. You can use the method you described in your first post of this thread with NCAPTURES=40

    user4001754 said:
    Then in order to avoid missing the capture interrupt, I have to scale down the 32kHz clock to make sure it is much slower than the system clock for interrupts. Overflow is acceptable because we can take it into account.

    No, there is no need to do that for 32kHz input.

  • Thanks zrno,

    One thing that I am still curious about is that why you did not choose to use the capture mode. I prefer to use capture mode because it is said to use hardware to capture, which reduce the latency in software.

    I was trying to improve my method in my first post but I found that I cannot have an accurate count of the overflows, and because the overflow interrupt priority is lower than the capture interrupt, the captures always preempt  overflows. Is that the reason you use overflow interrupts but not capture?

  • No, I was not thinking about capture mode, and don't know if it can be better or not than my solution. In my algorithm result is the frequency number that don't need to be recalculated on any way. And there is no any latency. You can see on 43oh topic that (with MCLK form XT2) error between readings is really small. At the beginning I was thinking to use multiple ranges, but later gave up. Didn't see any reason for this.
  • Thanks zrno

    Oh... I didn't take the MCLK from XT2 into account. If you use XT2 as system main clock then it could be fast enough. But in my implementation I guess I have to stick with 32kHz as MCLK because I am not just making a frequency counter. There are other tasks like radio communication have to be done in my program and they will probably use my 26MHz crystal. That's why I am thinking about latency.
  • Sure you will get latency and huge errors if MCLK frequency of "counter designed by zrno" is low. It is always better idea to make frequency counter which is fully CPU independent. In your case you shall connect timebase counter compare output to measurement timer capture input. Then you just collect capture register contents in timer capture ISR, not worrying about CPU speed or latency.

    Perfect counter which is able to measure 0Hz .. max_supported_frequency would automatically select either gated mode or reciprocal mode depending on relation between reference and measured frequencies. More about that: in HP application note I mentioned before.

  • Ilmars said:
    Sure you will get latency and huge errors if MCLK frequency of "counter designed by zrno" is low.

    In algorithm on 43oh, there are two timer interrupts that will be executed in about 10 cycles.

    TimerA0  inc.w R10
             reti

    TimerA1  inc.w R11
             reti

    And there is looping in main, waiting for stopping timers...

    Wait     cmp.w #000400, R10
             jne Wait
             bic.w #MC0, &TA0CTL ; stop timer
             bic.w #MC1, &TA1CTL ; stop timer

    Main can be free if this part is moved inside interrupt. This will add few more cycles to interrupt.

    TimerA0    inc.w R10
               cmp.w #000400, R10
               jne TimerA0Ret
               bic.w #MC0, &TA0CTL ; stop timer
               bic.w #MC1, &TA1CTL ; stop timer
    TimerA0Ret reti

    Of course, lower MCLK will increase error, and if the CPU is busy with other interrupts in the moment when TimerA0 is triggered for the last time (stooping timers).

  • >In algorithm on 43oh, there are two timer interrupts that will be executed in about 10 cycles.
    Not when CPU is executing instruction which takes many cycles or what's worse - busy in other ISR. I see that in your assembly code actual source of error is not ISR latency but 1) fact that timers are not stopped synchronously and 2) "waiting for stopping timers" loop have inherent jitter. Maybe you shall think of new "ultimate" version which uses pure hardware capture? :)

**Attention** This is a public forum