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/MSP430FG439: External timer input capture maximum frequency

Part Number: MSP430FG439

Tool/software: Code Composer Studio

Dear team,

My customer want to measure the frequency of ext signal with timer capture mode.

Hardware: MSP-FET430U80 with FG439

XT1=32.768kHz    XT2=4MHz

Code: 

#include <msp430fg439.h>
#include "main.h"


unsigned long SMCLK_Count_Num = 0;
unsigned long Frequency = 0;
unsigned char Count = 0x0;
unsigned int REdge1, REdge2;


void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;    // stop watchdog timer
    SetupClock();
    Capture_Pos();
//    __enable_interrupt(); 
    while(1)
    {
//        __enable_interrupt(); 
        __bis_SR_register(LPM0_bits + GIE);   // Enter LPM0
        __no_operation();                     // For debugger
        if (TB0CCTL1 & COV)                   // Check for Capture Overflow
            while(1);

            SMCLK_Count_Num = REdge2 - REdge1;
            Frequency = (Count*SMCLK_Frequency)/SMCLK_Count_Num;
//            TBCTL |= TBCLR + TBIE;
//            TBCCTL1 |= CCIE;
    }
}


void SetupClock()
{
    uint16_t tmpv;
    FLL_CTL1 &= ~XT2OFF;         
    do
    {
        IFG1 &= ~OFIFG;            
        for (tmpv = 0xff; tmpv > 0; tmpv--);
    }
    while((IFG1 & OFIFG)!=0);    
    IFG1 &= ~OFIFG;
    FLL_CTL1 |= SELM_XT2+SELS;           
}


void Capture_Pos() 
{
    P2SEL |= BIT2;           
    P2DIR &= ~BIT2;
 
    TB0CTL |= TBSSEL_2 + MC_2 + TBCLR ;
    TBCCTL1 = CM_1+ CCIS_1 + SCS + CAP + CCIE; 
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMERB1_VECTOR
__interrupt void TIMER0_B1_ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_B1_VECTOR))) TIMER0_B1_ISR (void)
#else
#error Compiler not supported!
#endif
//__interrupt void Timer_B1 (void)
{
    switch(__even_in_range(TB0IV,0x0A))     
    {
        case TB0IV_NONE:
            break;
        case TB0IV_TBCCR1:
            if (!Count)
            {
                REdge1 = TB0CCR1;
                Count++;
            }
            else
            {
                REdge2 = TB0CCR1;
                Count=0x0;
//                TBCTL &= ~TBIE;
//                TBCCTL1 &=~CCIE;
                __bic_SR_register_on_exit(LPM0_bits + GIE);  // Exit LPM0 on return to main
            }
            break;
        case TB0IV_TBCCR2:
            break;
        case TBIV_3:
            break;
        case TBIV_4:
            break;
        case TBIV_5:
            break;
        case TBIV_6:
            break;
        case TB0IV_TBIFG:
            break;
        default:
           break;
    }
}

It hangs in 

        if (TB0CCTL1 & COV)                   // Check for Capture Overflow
            while(1);

They want to measure 80KHz ext singal.

  • 80kHz with MCLK=4MHz is in that grey area: Feasible but not easy. The program has 4MHz/80kHz=50 CPU clocks to process each capture, and roughly half of that goes to ISR overhead. Even turning on compiler optimization might improve things. That division operation by itself could cause some number (10, maybe?) of misses, but one of the benefits of using capture is that each cycle (pair) gives you an answer (if you can avoid COV overruns).

    Unsolicited:

    1) 

    > __bic_SR_register_on_exit(LPM0_bits + GIE); 

    This disables interrupts in main, which will predictably cause COV overruns while that division operation is running. Try:

    >__bic_SR_register_on_exit(LPM0_bits); 

    2) Do the (Redge2-Redge1) subtraction in the ISR, to avoid races.

    3) 

    >            Frequency = (Count*SMCLK_Frequency)/SMCLK_Count_Num;

    I don't quite understand why Count figures in here. Count is either 0 or 1, which doesn't bear on the time delta.

    4) Redge1, Redge2, and maybe SMCLK_Count_Num need to be declared "volatile".