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/MSP430FR5959: Timer In Capture mode.

Part Number: MSP430FR5959

Tool/software: Code Composer Studio

hello sir,

 we are using timer B (as capture mode CCR5 & CCR6 pin no 28 and 29).. in that every thing works fine when capture frequency is less but when frequency is more (around 50kHz ) is not coming out of the timer B ISR.. we also have ADC, WDOG , UART0 and  Timer A interrupts. UART having modbus RTU protocol so it is continuously polling other devices..

so when high frequancy given in the pin(28 and 29) it will affect the UART interrupt and instrument gets hang.. so guide us how to deal with it 

is this a interrupt priority problem? .. if it is then how to set the interrupt priority in MSP ?

  

  • At 50kHz you have 1/50kHz=20usec to process each interrupt. If you haven't changed the clock, that's 20 CPU clocks, which is not enough to get into/out of the ISR (even if you did nothing there). Options:

    1) Speed up the CPU clock. At 16MHz you would have 16*20=320 clocks which should be enough.
    2) Do less work in your ISR.
    3) Invert the problem and count pulses (TBCLK) instead of using capture.

    It's not really a priority problem: If the other interrupts were getting in you'd (still) be losing data.
  • thank you sir
    we used 8 MHz CPU clock and i got your point i think as u said your 3rd option .. actually we need to count max 100KHz freq (in both channels pin 28 and pin 29 ) in our application.so counting pulse would be best solution so can u please give sample code for timer used as counting pulse..

    thank you for your time
  • To do pulse counting you would feed your pulse source into TB0CLK (P2.0) and use TBSSEL=0. (Also configure P2.0 according to Data Sheet (SLAS704F) Table 6-52.) TB0R then counts pulses from your signal rather than from SMCLK.

    To do frequency, measure real time with another timer and either (a) trigger an interrupt after some fixed number of pulses and measure how long that took or (b) read TB0R at some fixed period and compute how many pulses happened in the meantime.

    Unfortunately, you can only do one input signal per timer. However, there is an analogous mechanism for TA0 and TA1.

    [Edit: Fixed typo in DS doc number.]

  • I had this idea that there was a standard Example program that illustrates this, but I couldn't find it, so I spent a few minutes constructing one that runs on an FR5969 Launchpad.

    You actually only need about 6 lines of this, but I packaged it as a demo (jumper P1.2 to P2.0) so you (and I) could be convinced that it worked.

    No warranty, no support, and all that.

    ///
    //  main.c
    //  Demonstrate TB0CLK input. Patching P1.2 to P2.0 blinks an LED.
    //
    //  Disclaimer: No warranty, no support. I may not even exist.
    //
    #include <msp430.h>
    #define HZ          1000000UL           // SMCLK ~1MHz after Reset
    #define TRIGGER_HZ  50000UL             // 50 kHz out from TA1.1 into TB0CLK
    #define TRIGGER_PERIOD (HZ/TRIGGER_HZ)  // TA1.1 output period 20 ticks
    #define LED_HZ      1UL                 // 1Hz (two toggles) on the LED
    #define LED_PERIOD  (TRIGGER_HZ/LED_HZ/2) // 25000 pulses per LED toggle
    
    ///
    //  main()
    //
    int
    main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    
        //  Launchpad P1.0 LED
        P1OUT &= ~BIT0;             // Initially off
        P1DIR |= BIT0;              // Output
    
        //  Here's the timer clock input part:
        //  Clock TB0 from TB0CLK (P2.0), inconveniently located on J13 (TXD).
        //  Pulses are counted in TB0R. An interrupt occurs after a given number
        //  of pulses (LED_PERIOD).
        P2DIR &= ~BIT0;             // P2.0 input
        P2SEL1 |= BIT0;             // P2.0 assigned TB0CLK
        P2SEL0 |= BIT0;             //  per SLAS704F Table 6-52
        TB0CCTL6 = CCIE;            // Interrupt after
        TB0CCR6 = LED_PERIOD;       //    25000 input pulses (1Hz blink)
        TB0CTL |= TBSSEL_0 | ID_0 | MC_2 | TBCLR; // TBCLK/1, Continuous [,Clear]
    
        //  Here's the demo part: Generate a 50% duty cycle at apx 50kHz on TA1.1.
        //  To see it, jumper P1.2 (TA1.1) to P2.0 (TB0CLK) so TB0 sees some clock pulses.
        P1SEL0 |= BIT2;             // P1.2 as TA1.1
        P1SEL1 &= ~BIT2;            //  per SLAS704F Table 6-49
        P1DIR |= BIT2;
        TA1CCR0 = TRIGGER_PERIOD-1; // Cycle 20 clocks (50kHz)
        TA1CCR1 = TRIGGER_PERIOD/2; // Halfway for 50% duty cycle
        TA1CCTL1 = OUTMOD_7;        // Reset/Set
        TA1CTL = TASSEL_2 |ID_0 | MC_1 | TACLR; // SMCLK/1, Up [,Clear]
    
        PM5CTL0 &= ~LOCKLPM5;       // Engage GPIOs
        __enable_interrupt();
    
        //  Not much to do now
        while (1)
        {
            LPM0;
        }
    	/*NOTREACHED*/
    	return 0;
    }
    
    ///
    //  ISR for TB0CCR6 (every LED_PERIOD pulses)
    //
    #pragma vector=TIMER0_B1_VECTOR
    __interrupt void
    timerB1_ISR(void)
    {
        TB0CCTL6 &= ~CCIFG;         // Clear IFG
        TB0CCR6 += LED_PERIOD;      // Move forward for next time
        P1OUT ^= BIT0;              // Blink (well, half a blink anyway)
        return;
    }
    

  • ya sir i got it.. we change frequency input to timer A0 and A1 (p1.1 and 1.2) because at timer B input we need UART0 also so we cant used timer B for input(both are on same pin)

    and it works fine upto 65535( 16bit timer) but we need up to 100k ..how can we handle OFL flag without timer OFL interrupt to be ON..just like we can do in 8051


    unsigned long u32_timercount = 0;

    TR2 = 0;//stop timer
    u32_timercount = TH2; // freq value high byte
    u32_timercount = (u32_timercount << 8) | TL2; // freq value low byte

    if(TF2)//if OFL bit set
    {
    u32_timercount += 65535; //add 65535 to 16 bit timer val
    TF2 = 0; // clear OFL for next read
    }

    is MSP430 have TF(timer ofl )bit and that is to be read with out interrupt to be ON..???
  • You can stop the timer by setting the TA0CTL:MC field to 0. However, reading from TA0R (all 16 bits) is atomic, so the timer doesn't need to be stopped.

    There is an overflow flag: TA0CTL:TAIFG. But there is a race between reading TA0R and reading the TAIFG bit. I would be tempted to accumulate counts by differencing (analogous to what one does with pulse-width measurement), something like:

    now = TA0R; diff = now - prev; total += diff; prev = now;

    which uses (a) the atomicity of reading TA0R and (b) the "magic" of 16-bit unsigned underflow to avoid stopping the timer.

    You may also want to consider dividing down the pulse count using TA0CTL:ID and TA0EX0. You'll give up some resolution in exchange for more manageable numbers.

    I probably should have asked what it is you're actually trying to measure -- I've assumed it was frequency counting since (as you noticed) capture per se, i.e. measuring individual pulse widths, is impractical at those frequencies.

**Attention** This is a public forum