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.

MSP430G2553 Launchpad 定时器不能用TACLR进行清零!



您好!我用的是IAR5.0版本的编译器,编写MSP430G2553控制程序时,发现无法用TACLR对定时器进行清零,我通过IAR里面自带的寄存器观察工具观察TACTL寄存器的值,发现用软件编写TACTL|=TASSEL_2+TACLR+MC_1+ID_3;时无法寄存器TACTL中TACLR位没有置位,依然是0,很困惑,不知道是什么问题!网上查到的其他同行编写的程序都是通过这种方式对定时器进行清零的,所以请教一下这个是什么问题????

  • 参考官方的一个例程看看是不是配置的问题

    //  MSP430G2xx3 Demo - Timer_A0, Normal Timer Mode Input Period and Dutycycle
    //                     measurement
    //  Description: This code example implements input capture in single capture
    //  mode using TimerA in normal timer mode. TA1.1 is configured to output PWM
    //  of 25% dutycycle, that is used as capture input at TA0.1. TA0.1 is
    //  configured as timer input capture that is triggered by both the rising and
    //  the falling edges. An external connection between TA1.1 and TA0.1 is
    //  required in this example. Rising and Falling edges are captured and the
    //  dutycycle is computed. If the measured dutycycle is != 25%, then LED on
    //  P1.0 is set.
    //
    //  ACLK = LFXT1 = 32kHz crystal ; SMCLK = MCLK = 8 MHz;
    //
    //                 MSP430F51x2
    //             -----------------
    //         /|\|              XIN|-
    //          | |                 | 32kHz
    //          --|RST          XOUT|-
    //            |                 |
    //            |       P1.2/TA0.1|<-- CCI1A <-|
    //            |       P2.1/TA1.1|--> CCR1 -->|
    //            |                 |
    //            |             P1.0|--> LED "ON" when dutycycle != 25%
    //            |                 |

    //
    //  W. Goh
    //  Texas Instruments Inc.
    //  March 2012
    //  Built with CCS v5.2 and IAR Embedded Workbench Version: 5.40.3
    //******************************************************************************
    #include <msp430.h>

    unsigned char Count, First_Time;
    unsigned int REdge1, REdge2, FEdge;

    int main(void)
    {
      unsigned int Period, ON_Period;
      unsigned char DutyCycle;

      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

    //  P1SEL |= BIT0;
      P1DIR |= BIT0;                            // P1.0/LED Output
      P1OUT &= ~BIT0;                           // LED off
      if (CALBC1_8MHZ==0xFF)     // If calibration constant erased
      {           
        while(1);                               // do not load, trap CPU!! 
      }
      DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      BCSCTL1 = CALBC1_8MHZ;                    // Set DCO to 8MHz
      DCOCTL = CALDCO_8MHZ;

      // Configure Port Pins
      P2DIR |= BIT1;                            // P2.1/TA1.1 Output
      P2SEL |= BIT1;                            // TA1.1 Option select
      P1DIR &= ~BIT2;                           // P1.1/TA0.1 Input Capture
      P1SEL |= BIT2;                            // TA0.1 option select

      // Configure TA1.1 to output PWM signal
      // Period = 82/32khz = 2.5ms ~ 400Hz Freq
      TA1CCR0 = 82-1;                          // Period Register
      TA1CCR1 = 21;                            // TA1.1 25% dutycycle
      TA1CCTL1 |= OUTMOD_7;                    // TA1CCR1, Reset/Set
      TA1CTL = TASSEL_1 + MC_1 + TACLR;        // ACLK, upmode, clear TAR

      // Configure the TA0CCR1 to do input capture
      TA0CCTL1 = CAP + CM_3 + CCIE + SCS + CCIS_0;
                                                // TA0CCR1 Capture mode; CCI1A; Both
                                                // Rising and Falling Edge; interrupt enable
      TA0CTL |= TASSEL_2 + MC_2 + TACLR;        // SMCLK, Cont Mode; start timer

      // Variable Initialization
      Count = 0x0;
      First_Time = 0x01;

      while(1)
      {
          __bis_SR_register(LPM0_bits + GIE);   // Enter LPM0
          __no_operation();                     // For debugger
          // On exiting LPM0
          if (TA0CCTL1 & COV)                   // Check for Capture Overflow
              while(1);                         // Loop Forever

          Period = REdge2 - REdge1;             // Calculate Period
          ON_Period = FEdge-REdge1;             // On period
          DutyCycle = ((unsigned long)ON_Period*100/Period);
          if(DutyCycle!= 25)
          {
              P1OUT |= BIT0;
          }
          else
          {
              P1OUT &= ~BIT0;
          }
      }
    }

    // TA0_A1 Interrupt vector
    #pragma vector = TIMER0_A1_VECTOR
    __interrupt void TIMER0_A1_ISR (void)
    {
      switch(__even_in_range(TA0IV,0x0A))
      {
          case  TA0IV_NONE: break;              // Vector  0:  No interrupt
          case  TA0IV_TACCR1:                   // Vector  2:  TACCR1 CCIFG
            if (TA0CCTL1 & CCI)                 // Capture Input Pin Status
            {
                // Rising Edge was captured
                if (!Count)
                {
                    REdge1 = TA0CCR1;
                    Count++;
                }
                else
                {
                    REdge2 = TA0CCR1;
                    Count=0x0;
                    __bic_SR_register_on_exit(LPM0_bits + GIE);  // Exit LPM0 on return to main
                }

                if (First_Time)
                    First_Time = 0x0;
            }
            else
            {
                // Falling Edge was captured
                if(!First_Time)
                {
                    FEdge = TA0CCR1;
                }
            }
            break;
          case TA0IV_TACCR2: break;             // Vector  4:  TACCR2 CCIFG
          case TA0IV_6: break;                  // Vector  6:  Reserved CCIFG
          case TA0IV_8: break;                  // Vector  8:  Reserved CCIFG
          case TA0IV_TAIFG: break;              // Vector 10:  TAIFG
          default:  break;
      }
    }

  • 在程序初始化的时候TACTL|=TASSEL_2+TACLR+MC_1+ID_3;  TACLR置1应该没有问题。如果定时器已经初始化完成,后面要改定时器设置,可是试试先用MC_0停止定时器,再重新配置。要清0TAR计数器,定时器不是用MCLK时,要停止定时器,直接写TAR也可以。

  • 你好!我想问下,用TACLR对定时器清零,可以在软件上通过查看寄存器来查看是否置位了吗?我在这个IAR环境下,无法观察TACLR是否置位,寄存器这一位的值一直是0,而且也没用清除TAR寄存器的值啊,TAR还是原来的值不变,运行这一条语句后值反而增加了!而当停止定时器后,通过TA0R = 0x0000这条语句可以清除定时器里面的值!

  • 您好

    在MSP430x2xx Family User-'s Guide里可以查到对TACLR位的解释里有这个:

    Timer_A clear. Setting this bit resets TAR, the clock divider, and the count
    direction. The TACLR bit is automatically reset and is always read as zero.

    意思是这个位被你置位后会被自动清零的 所以你读取它的值时总为零 

    至于你想用这种方式来对TAR进行清零操作  也是在这个手册里有这么一句话:

    It is recommended to stop the timer before modifying its operation (with
    exception of the interrupt enable, interrupt flag, and TACLR) to avoid errant
    operating conditions.

    意思是在修改定时器寄存器时最好先把定时器停下来  但是括号里说除了修改中断使能,中断标志位和TACLR

    所以直接置位TACLR来清零是可以实现的 

    我想您其实是已经清零成功了但是并没有发现自己成功了  

    建议您想一个办法来测试是否清零成功

    比如使用两个定时器 第一个的CCR0里的数值是第二个里的两倍 在第一个定时器的中断里设置让灯亮

    在第二个定时器的中断里对第一个的TACLR位进行置位操作 然后观察最终灯是否会亮

    这个我也没有测试 只是这么个想法

  • 你好,

    如果你单纯只是期望指令计数器清零请直接使用TACTL |= TACLR,不需要配置其他东西。

    你可以做一个实验来判断是否清零。

    利用CCRO产生中断,在CCR0中断里面清零计数器,设置断点,看TAR的值是否为零。

    注意CCR0中断计数器最好设置在40536左右,这样更容易看到效果。