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.

MSP430F149 TimerA的捕获程序



我把MSP430的P1.2引脚作为方波的输入频率10Hz,但为什么一接到信号发生器上,就工作不正常,以下是程序:

#include <msp430x14x.h>

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;

BCSCTL1 &= ~XT2OFF;
do
{
IFG1 &= ~OFIFG;
for (unsigned int i = 0xFF; i > 0; i--);
}
while ((IFG1 & OFIFG));
BCSCTL2 |= SELM_2 + SELS + DIVS_3;


P1DIR &= ~BIT2;
P1SEL = BIT2;

P2DIR = BIT0; //控制LED灯,高电平灯灭
P2OUT = 0XFF; //灯灭


CCTL1 = CM_1 + SCS + CCIS_0 + CAP + CCIE;
TACTL = TASSEL_2 + MC_2 + ID_3;

_BIS_SR(GIE);
while(1);

}

#pragma vector = TIMERA1_VECTOR
__interrupt void Timer_A1 (void)
{
if(TAIV == 0X02)
P2OUT ^= BIT0;         //让灯交替亮灭
}

当程序下载到MCU时,灯在很快的闪,而且无论怎么调整输入的方波频率,灯都以那个频率在闪。当不接输入时,灯就不闪了。而且,在不接输入时,在P1.2口接一条杜邦线,杜邦线不连接其他设备,灯也会闪

  • 你这个是MSP430的帖子啊,貌似有这个版块,你怎么发的

  • 你先说明白,你想让程序干什么?这样我才能知道你要干嘛,你的程序干了嘛。你才知道为何没有干嘛。

  • 根据你最后一句和你的程序,你需要启动REN上拉电阻,然后就不干扰了,目前接个电线都不停的被外界干扰,那是天线效应,赶紧的,启动上拉电阻,记得REN。

  • 谢谢,加一个电阻可以了,但有时候还是会出现一些不稳定,就是灯闪着闪着就不闪了

  • 不好意思是我没把问题描述好,对不起。其实我是定时器A做一个频率计,输入频率的范围大概在100Hz到1500Hz之间,我现在用低于10Hz的输入频率,来控制LED灯的闪烁,主要是为了看现象是否正确。我下面还有一个程序用P1口的中断和定时器A的做一个频率计。我在P1口的输入上加了一个10K的下拉电阻,但是在输入为2KHz的方波时液晶不能正常显示,只显示00000,不知道是什么原因,帮忙看一下。

     

    #include  <msp430x14x.h>
    #include "Crystal1602.c"                 //液晶1602显示文件
    #include "Crystal1602.h"                 //液晶1602头文件

    #define uchar unsigned char          //宏定义

    uchar capture_end = 0;                    //捕获处理结束标志
    uchar capture_times = 0;                 //捕获次数
    uchar matrix[6] = {'0','0','0','0','0','\0'};//初始化显示的数组
    uchar a = 0;
    unsigned long int overflow_times = 0;                       //定时器;溢出的次数
    unsigned long int time_interval = 0 ;                          //一个周期的时间间隔
    unsigned long int time_interval_buffer = 0;               //时间间隔缓存,可以不用,仅用于调试

    void process(unsigned long int value,uchar *matrix)     //处理函数
    {
      matrix[0] = (uchar)(value / 10000) + '0';                            //得到万位数字
      matrix[1] = (uchar)(value %10000 / 1000) + '0';              //千位数字
      matrix[2] = (uchar)(value %1000 / 100) + '0';                   //百位数字
      matrix[3] = (uchar)(value %100 / 10) + '0';                        //十位数字
      matrix[4] = (uchar)(value %10) + '0';                                  //个位数字
      matrix[5] = '\0';
    }


    void desplay(unsigned long int des)                                    //显示函数
    {
      uchar mtrix[6];                                                                          //定义一个显示数组
      process(des,mtrix);                                                                //处理函数,获得个十百千万位
      write_string(0,0,mtrix);                                                            //在液晶1602的0行0列显示一个字符串mtrix
    }


    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
     
      BCSCTL1 &= ~XT2OFF;                      // XT2on
      do
      {
      IFG1 &= ~OFIFG;                                  // Clear OSCFault flag
      for (unsigned int i = 0xFF; i > 0; i--);  // Time for flag to set
      }
      while ((IFG1 & OFIFG));                       // OSCFault flag still set?
      BCSCTL2 |= SELM_2 + SELS + DIVS_3;        // MCLK = SMCLK = XT2 (safe)
     
      P1DIR = 0X00;                         //P1口设置为输入
      P1SEL = 0X00;                         //P1口选择为IO功能
      P1IES = 0X00;                          //选择P1口为上升沿中断
      P1IE  = 0XFF;                            //使能P1口中断功能
      P1IFG = 0X00;                           //清零P1口的的中断标志
      
      TACTL = TASSEL_2 + MC_2 + ID_3;                   // SMCLK, contmode
      CCTL0 &= ~CCIE;                             // CCR0 interrupt enabled
      CCR0 = 80;
      initialize_1602();
     

      _EINT();
      while(1)
      {  
        if(capture_end == 1)
        {
          time_interval = overflow_times*80;            //一个周期间隔的计算  时间间隔=定时器溢出的次数*定时器定时间隔
          overflow_times = 0;                                        //定时器溢出次数清零
          capture_end = 0;                                             //捕获完成标志清零
        }
        desplay(time_interval);                                     //显示时间间隔
      }
    }

     

    #pragma vector = PORT1_VECTOR      //P1口中断程序
    __interrupt void Port_1(void)
    {
      a = P1IFG;
      P1IFG = 0X00;
      if(capture_times == 0)           //如果是第一次捕获到上升沿
      {
        CCTL0 |= CCIE;                       //打开定时器CCR0的定时功能
        capture_times++;
      }
      if(capture_times == 1)         //如果是第二次捕获到上升沿
      {
        CCTL0 &= ~CCIE;               //关闭定时器CCR0的定时功能
        capture_times = 0;              //清除捕获次数
        capture_end = 1;                 //捕获完成标志置位
      }
    }


    // Timer A0 interrupt service routine
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A0 (void)
    {
       CCR0 += 80;
       overflow_times++;               //CCR0溢出次数
    }

  • 在这段程序中

    #pragma vector = PORT1_VECTOR      //P1口中断程序
    __interrupt void Port_1(void)
    {
      a = P1IFG;
      P1IFG = 0X00;
      if(capture_times == 0)           //如果是第一次捕获到上升沿
      {
        CCTL0 |= CCIE;                       //打开定时器CCR0的定时功能
        capture_times++;
      }
      if(capture_times == 1)         //如果是第二次捕获到上升沿
      {
        CCTL0 &= ~CCIE;               //关闭定时器CCR0的定时功能
        capture_times = 0;              //清除捕获次数
        capture_end = 1;                 //捕获完成标志置位
      }
    }

     

    用两个if是很大的BUG