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.

MSP430FR2355 frequency counter

Other Parts Discussed in Thread: MSP430FR2355

Hello everybody

I am using with MSP430FR2355, I need to measure frequency from the frequency divider in 4Mhz and capture it.

I tested 2 sample code ( MSP4302235X_tb0_capture.c  and  MSP4302235X_tb0_22.c) , now I have question's: 

1- I am using MSP430Fr2355 Launchpad and I don't have access to Pin 2.7 for as a input, what should I do now? 

2- I should use TB0CLK for timer  and TB0TRG for trigger? could you please explain it what should I do.

3- Do I need to connect pins together for timer and trigger?? Because in this link connected 2 pins for timer and trigger together.

Best

  • Hi Hadi, you want to measure the frequencies of various dividers from a 4MHz clock, correct? The 4MHz clock is an external clock source, not from the MSP430, correct? What resolution or how accurate does the measurements need to be?

  • Hi Dennis

    Thanks for your reply.

    I have external device which I connected to one pin of MSP430FR2355 and I want measure the frequency of it, and I think for measure the frequency I should count number of period(I am not sure).
    I want to measure frequency of the frequency divider (3-4 MHz) coming one pin of MSP430FR2355. I used P2.2.

    Best Regards

    Hadi

  • Ok, there are actually several timerB modules on this device, some with 2 capture/compare  inputs and one with 5 capture/compare inputs that connect to available pins.

     Looking at the datasheet, section 6.10.9, there are tables that show the timers and their input capture pins. The MSP430FR2355 Launchpad user guide schematics shows the following timer input fan-out to the boosterpack header pins: TB0.1 (P1.6), TB0.2 (P1.7), TB1.1 (P2.0), TB1.2(P2.1), TB2.0(P5.0), TB2.1(P5.1), TB3.1(P6.0), TB3.2(P6.2), TB3.3(P6.2), TP3.4(P6.3), and TB3.5(P6.4).  Note that P2.2 is not a timer input, so choose one of the other inputs.

    Now, to be able to measure up to 4MHz you will need to run the timers at a minimum of twice the input you are measuring, so 8MHz.  Since the timerB can be clocked at a maximum of 24MHz, I would suggest you configure your clock system to provide the 24MHz input clock to the timer.

    You will want to setup the timer in CAPTURE mode.  There are examples of how to do this for the MSP430FR2355 in the TI resource explorer, TIREX.

  • I hesitate to disagree with Dennis, but you will not succeed in measuring a 4MHz  signal using capture, rather you should use TB1CLK as you proposed. Choose TBSSEL=0 and MC=2 and fetch TB1R periodically — probably measured by a separate timer.

    I usually estimate around 20 kHz as the break even point — a slower signal works better with capture, faster requires a TBnCLK counter.

    TB1TRG is something separate, related to TBOUTH. In most applications you want to avoid triggering TB1TRG.

  • Hi Dennis

    Thanks for your reply. I will check with your suggestion and come to you.

    Best Regards 

    Hadi

  • Dear Bruce

    Thanks for your reply.

    I have problem in this method, Do I need to connect pins together for timer and trigger (TB1CLK and TB1TRG)?? Because in this link connected 2 pins for timer and trigger together.

    https://dev.ti.com/tirex/explore/node?node=AE1YXfIwoIIOovncrRHB2A__IOGqZri__LATEST

    Best Regards

    Hadi

  • Connect TB1CLK to your signal. Don’t connect TB1TRG at all.

    The example creates its own input signal, which is handy but I thought you had a signal (?). Unfortunately it uses capture rather than an external clock.

    Here’s an example using an external clock. It’s for a different device but the principle is the same.

    https://e2e.ti.com/support/microcontrollers/msp-low-opower-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/714284/ccs-msp430fr5959-timer-in-capture-mode

  • Dear Bruce
    Thanks for your reply.

    I have one external signal and I want to measure frequency from it.
    I connected it to P2.2 (TB1CLK), and I test several time but I couldn't find the number of period.

    TB1CCTL0 |= CM_1 | CCIS_1 | CCIE | CAP | SCS;
    TB1CTL |= TBSSEL_0 | MC_2 | TBCLR;

    TB1CCTL0 &= ~CCIFG;
    CountMeasureFreq = TB1CCR0;

    I don't have Idea for solve it, could you please help me. 

    Thanks a lot.

    Best

    Hadi

  • This code uses capture for the measurement. I don’t recommend capture for your stated application but to do that you would need to use the TB1.0 pin, which apparently doesn’t exist.

    Your external signal will cause TB1R to increment (+1) for each cycle (pulse) in the signal. To use this, read TB1R periodically, e.g. every millisecond, subtract the value you read last time, then divide that difference by the period to get (pulses/time).

    The simplest way to do the “periodically” part is to use another timer (maybe TB0) and set it to interrupt (CCIE) every (e.g.) millisecond. I’m pretty sure one of the TI examples shows how to do this part.

  • Dear Bruce
    I hope you are doing well.

    Please find my attached code.

    in this code I wanted to find measure frequency from the frequency divider (external) from P2.2 (TB1CLK).

    But may value is 0.

    #include <msp430.h>
    
    
    unsigned long VAL; // Previous value of the capture register
    unsigned long counter;
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;                       // Stop watchdog timer
    
        // Configure GPIO
    
        P2SEL1 |= BIT2;                                 // Set as ACLK pin, second function
        P2DIR |= BIT2;
    
        PM5CTL0 &= ~LOCKLPM5;
    
    
        TB1CTL = TBSSEL_0 | MC_2 | TBCLR | TBIE;
        TB1CCTL0 |= CM_1 | CCIS_1 | CCIE | CAP | SCS;
    
    
        __bis_SR_register(LPM0_bits | GIE);
        __no_operation();
    }
    
    // Timer0_B3 CCR0, TB Interrupt Handler
    #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
    
    
    {
        unsigned long freq;
        freq = counter;
        counter = 0;
        TB1CCTL0 &= ~CCIFG;
    
        unsigned long SAM;
        SAM = TB1CCR0;
    
    
        freq += SAM - VAL;
        VAL = SAM;
    }
    
    #pragma vector=TIMER0_B1_VECTOR
    __interrupt void TB0IV_ISR(void)
    {
        if(TBIV == 10)
        {
            counter += 0x10000;
        }
    }
    
    

  • This code looks pretty much like the previous code -- in particular, it still uses Capture for the computation, but there will be no Capture events since the TB1.0 pin doesn't exist. You need to decide whether you want to use Capture (slow signal) or External Clock (fast signal), since the procedures are rather different.

    I suggest you run this code in the debugger, and use the Registers view to watch TB1R as your input signal runs. But first, you need to:

    >P2SEL1 |= BIT2; // Set as ACLK pin, second function
    >P2DIR |= BIT2;

    Replace these two lines with:

    >P2SEL0 |= BIT2; // P2.2 as TB1CLK per
    >P2DIR &= ~BIT2; // data sheet (SLASEC4C) Table 6-64

    Also, here's a TI example of using an external clock (though not a full frequency-counter implementation) on the FR2355:

    https://dev.ti.com/tirex/explore/node?node=ANcmdW6geYSVsxVVNMB9rA__IOGqZri__LATEST

  • Dear Bruce
    Thanks for your reply.

    Could you please provide me clear solution, because I couldn't find solution and solve my problem.

    Please find my attached code.

    #include <msp430.h>
    
    
     unsigned long CounterValue = 0;
     unsigned long StoredCount = 0;
     unsigned long Result = 0;
    
    
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;                       // Stop watchdog timer
    
        // Configure GPIO
    
        P2SEL0 |= BIT2;                                 // Set as ACLK pin, second function
        P2DIR &= ~BIT2;
    
        PM5CTL0 &= ~LOCKLPM5;
    
    
        TB1CTL = TBSSEL_0 | MC_2 | TBCLR | TBIE;
        TB0CCTL0 |= CM_1 | CCIS_1 | CCIE | CAP | SCS;
    
        while(1)
        {
    
        TB0CTL |= MC0;              // Start timer
        TB1CTL |= MC_2;              // Start timer
        while(CounterValue != 400); // Wait while CounterValue is not equal to 400
        TB0CTL &= ~MC0;             // Stop timer
        TB1CTL &= ~MC_2;             // Stop timer
        Result = StoredCount;       // Store frequency in Result
        CounterValue = 0;           // Zero CounterValue
        StoredCount = 0;            // Zero StoredCount
        TB0R = 0;                   // Zero Timer_B0 register
        TB1R = 0;                   // Zero Timer_B1 register
        }
    
    
        __bis_SR_register(LPM0_bits | GIE);
        __no_operation();
    }
    
    // Timer0_B3 CCR0, TB Interrupt Handler
    #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
    
    {
        CounterValue++;
    }
    
    #pragma vector=TIMER0_B1_VECTOR
    __interrupt void TB0IV_ISR(void)
    
    {
        StoredCount++;
    }

  • I patched together examples tb0_02 and tb0_22, and added a small bit of arithmetic. 

    Disclaimer: I don't have my equipment here, so this is untested. I think it's approximately correct, though.

    //
    //  Frequency-counter example, assuming fast (>1kHz) input signal.
    //  Started life as example msp430fr235x_tb0_02, with a patch from tb0_22.
    //  No support. No warranty. I may not even exist.
    //
    #include <msp430.h>
    
    unsigned curr, prev;                             // Must be 16-bit unsigned for arithmetic
    unsigned freq_in_kHz;                            // Instantaneous frequency result
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;                    // Stop WDT
        PM5CTL0 &= ~LOCKLPM5;                        // Engage GPIOs
    
        //  Adapted from example tb0_22:
        P2SEL0 |= BIT2;                              // P2.2 selected as TB1CLK
        TB1CTL = TBSSEL_0 | MC_2 | TBCLR;            // TB1CLK, continuous mode, clear TBR, no interrupt
    
        //  Adapted from example tb0_02:
        TB0CCTL0 |= CCIE;                            // TBCCR0 interrupt enabled
        TB0CCR0 = 1000-1;                            // 1ms at 1MHz SMCLK
        TB0CTL = TBSSEL__SMCLK | MC__UP;             // SMCLK, UP mode
    
        //  The ISR does all the work
        __bis_SR_register(LPM0_bits | GIE);          // Enter LPM0 w/ interrupt
        __no_operation();                            // For debug
    }
    
    // Timer0_B0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = TIMER0_B0_VECTOR
    __interrupt void Timer0_B0_ISR (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_B0_VECTOR))) Timer0_B0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        //  Called every 1ms.
        //  Compute delta-ticks based on successive TB1R values.
        unsigned diff;              // Must be 16-bit unsigned
        curr = TB1R;                // Number of ticks from external clock
        diff = curr - prev;         // Difference from last time (1ms ago)
        prev = curr;                // For next time
        // Based on 1ms poll cycle, delta-count is frequency in kHz
        // You'll probably want some better arithmetic here.
        freq_in_kHz = diff;
    }

    [Edit: Tested using a self-generated signal from TB2. Comment updated accordingly.]

  • Dear Bruce
    Thanks for your reply. I will check with your suggestion and come to you.

    Best Regards 

    Hadi

  • Dear Bruce

    BRILLIANT!!! ABSOLUTELY BRILLIANT SUGGESTION! 

    I could have never figured out this solution. I Hope your answer will help others too!!

    Thank you once again. keep up the good work!

  • Dear Bruce

    I hope you are doing well.!

    is there any opportunity to increase the accuracy of frequency measurement?

    Best

    Hadi

  • You can get more resolution by extending the TB0 poll cycle from (e.g.) 1ms to 10ms. You would then (conceptually) multiply the result by 100 rather than 1000 to get Hz, i.e. 1 more decimal digit of resolution. The signal needs to be stable for the full poll cycle, else you'll get an averaging effect.

    With a 4MHz signal, doing this would give a result of 40000, which is pretty close to the 16-bit limit (65535) for this method. How many digits do you need?

  • Dear Bruce
    Thanks for your reply.

    I would like to have at least 5 digit. Could you please kindly let me know what should be my value  for TB0 ?

    In TB0CCR0 = 1000-1; my frequency is near of 2800; but when I changed TB0CCR0 = 10000-1; my  frequency is near 27000.

    Best Regards

    Hadi

  • How near is "near"? With some rounding error, (2800*1000) isn't too far from (27000*100). Possible sources of error:

    1) Since you're polling TB1R, this is sensitive to interrupt latency. (What else is your program doing?) I expect this would show up as jitter since it wouldn't affect your signal. Averaging is a fairly simple remedy for jitter.

    2) Your signal is running faster than your instruction rate (estimated at MCLK/5) which would also produce jitter of perhaps as much as 5-10 counts (depending on your MCLK).

    3) How steady is your signal? Does it vary during your polling period? Is it jittering?

    Each of these can be improved by averaging. Start with maybe 8-10 consecutive readings.

**Attention** This is a public forum