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.

MSP430FG439,使用捕获功能测频率时中断冲突问题

Other Parts Discussed in Thread: MSP430FG439

       使用捕获功能对频率信号进行测量,捕获到第一个上升沿时对TBCCR1寄存器值进行读取,赋值给SMCLK_Count_Num_start变量,设置当TBR寄存器在连续模式下连续溢出11次时停止捕获,将此时TBCCR1寄存器的值赋予SMCLK_Count_Num_stop变量,按如下公式进行计算:

            SMCLK_Count_Num = 65535*overflow_Num + SMCLK_Count_Num_stop - SMCLK_Count_Num_start


            Frequency = ((CaptureNum-1)*SMCLK_Frequency)/SMCLK_Count_Num

      在调试过程中,出现现象为待测频率高于80kHz时 TIMERB1中断case14无法进入,溢出次数变量无法更新,导致程序卡死

      请各位帮忙分析解答问题所在。

      主程序如下:

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

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;    // stop watchdog timer
    SetupClock();
    Capture_Pos();
    __enable_interrupt();//中断使能
    while(1)
    {

        if (cap_finish_flag ==1)
        {
            cap_finish_flag = 0;
            SMCLK_Count_Num = 65535*overflow_Num + SMCLK_Count_Num_stop - SMCLK_Count_Num_start;
            Frequency = ((CaptureNum-1)*SMCLK_Frequency)/SMCLK_Count_Num;
            CaptureNum = 0;
            overflow_Num = 0;
            TB0CTL |= MC_2;
            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;           //选择MCLK,选择SMCLK //+DIVM_1
}

void Capture_Pos()//TIMER_B 捕获/比较寄存器 0
{
    P2SEL |= BIT2;            //TIMER B1通道
    P2DIR &= ~BIT2;
    //SMCLK做时钟源,16位计数器,不分频,连续计数模式,开中断
    TB0CTL |= TBSSEL_2 + CNTL_0 + ID_0 + MC_2 + TBCLR + TBIE;
    TBCCTL1 = CM_1+ CCIS_1 + SCS + CAP + CCIE;//上升沿触发,同步捕获,使能中断CCI1B
}

#pragma vector = TIMERB1_VECTOR
__interrupt void Timer_B1 (void)
{
    switch(TBIV)    
    {
        case 2:
            TBCCTL1 &= ~COV ;
            CaptureNum++;
            if(CaptureNum== 1)
            {
                  SMCLK_Count_Num_start = TBCCR1;
                  overflow_Num = 0;
            }
             if(overflow_Num== 11)
            {
                  SMCLK_Count_Num_stop = TBCCR1;
                  cap_finish_flag = 1;
                  TB0CTL |= MC_0;
                  TBCTL &= ~TBIE;
                  TBCCTL1 &=~CCIE;
            }
            break;
        case 4:
           break;
        case 14:
             overflow_Num ++ ;
            break;
        default:
           break;
    }
}







  • 待测频率80Khz是可以测量的,在数据手册内有相关的说明

    www.ti.com.cn/.../msp430fg439.pdf

    5.6 Inputs Px.y, TAx, TBx

    在G2553有相关的测试例程,您可以参考一下写法

    dev.ti.com/.../node

    抱歉,目前手边没有MSP430FG系列的板子,我回头找一下其他板子来测试一下

  • 已参考该例程进行测试,DEBUG时,程序会在如下程序不断循环:

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

    测试程序如下:

    #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;           //选择MCLK,选择SMCLK //+DIVM_1
    }


    void Capture_Pos()//TIMER_B 捕获/比较寄存器 0
    {
        P2SEL |= BIT2;            //TB1端口
        P2DIR &= ~BIT2;
        //SMCLK做时钟源,16位计数器,不分频,连续计数模式,开中断
        TB0CTL |= TBSSEL_2 + MC_2 + TBCLR ;
        TBCCTL1 = CM_1+ CCIS_1 + SCS + CAP + CCIE;//上升沿触发,同步捕获,使能中断CCI1B
    }

    #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;
        }
    }

  • 好的,谢谢反馈

    我手边没有这个板子,拿G2553的板子来测试一下后回复

  • 我用G2553的板子测试了一下例程是没有问题的,抱歉没有直接FG439的板子来测试

    您使用您自己之前的程序是可以测量频率的?只是当待测频率高于80kHz时会有问题?您现在SMCLK 是多少?可以适当增大一下频率

    Timer 用作Capture模式时,测量频率及精度取决于Timer的时钟源以及主频。

    需要有足够快的时钟源进行边沿捕获,同时还需要有足够快的响应时间进中断进行数据保存和计算。
  • 之前的程序目前还没有低功耗模式切换,没有对COV标志位进行判断,会出现高于80kHz无法测量频率。

    第二次测试程序是根据FG439芯片修改例程配置而来,程序会一直运行在检查捕获是否溢出的语句中,从我个人的理解4MHz时钟对80kHz频率捕获,应该不会有太大问题。

    测试时频率信号来源为信号发生器。

    目前测试用开发板为TI官方的MSP-FET430U80目标板搭配FG439芯片,使用32.768kHz和4MHz两个时钟晶振,是否与硬件有关?

    我这边会再次检查程序,希望发现问题。
  • 例程已经可以在开发板跑通,尝试在此程序运行基础上,将更大频率的信号接入开发板,程序会停在while(1)循环内

  • MCLK = 4MHz去捕获80kHz是可行的但不容易实现。程序中4MHz / 80kHz = 50个CPU时钟来处理每个捕获,其中大约一半用于ISR开销。

    另外

    1 __bic_SR_register_on_exit(LPM0_bits + GIE);

    这将禁用main中的中断,在该除法运算运行时,会导致COV超限。请尝试:

    __ bic_SR_register_on_exit(LPM0_bits);

    2 建议在在ISR中执行(Redge2-Redge1)减法

    3 请将Redge1,Redge2以及SMCLK_Count_Num声明为“ volatile”试试