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.

MSP430F5529 Timer Input Capture problem

Other Parts Discussed in Thread: MSP430F5529, ENERGIA

Hello,

I have written some code to do timer input capture on the 5529, by reading an example written for 2553. (msp430g2xx3_ta_21.c was the starting point)

I have connected a function generator to P1.2 of MSP430F5529 LP, and I am able to change frequency and duty cycle of the incoming square wave input.

Here is my code:

#include <msp430.h>

volatile unsigned int counter;

int main(void)
{

  WDTCTL = WDTPW + WDTHOLD;   

  // P1.2/TA0.1
  P1DIR &= ~BIT2;                          
  P1SEL |= BIT2;

  // TA0CCR1 Capture mode; CCI1A; Both Rising and Falling Edge; interrupt enable
  TA0CCTL1 = CAP + CM_3 + CCIE + SCS + CCIS_0;
  
  // SMCLK, Cont Mode; start timer
  TA0CTL |= TASSEL_2 + MC_2 + TACLR; 
  
  while(1) {
      __bis_SR_register(LPM0_bits + GIE);
      __no_operation();
      // Check for Capture Overflow
      if(TA0CCTL1 & COV) { /* while(1); */ }
  }
}

#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR (void)
{
  switch(__even_in_range(TA0IV,0x0E))
  {
      case TA0IV_NONE: break;      
      case TA0IV_TACCR1: 
          // breakpoint here
          counter = TA0CCR1;
          TA0CTL |= TACLR; 
          __bic_SR_register_on_exit(LPM0_bits + GIE);
          break;
      case TA0IV_TACCR2: break; 
      case TA0IV_TACCR3: break;
      case TA0IV_TACCR4: break;
      case TA0IV_5: break;   
      case TA0IV_6: break; 
      case TA0IV_TAIFG: break; 
      default: break;
      
  }
}


So I have a breakpoint inside the ISR, and I debug using CCS, to get the value of the counter. However it will not work as expected. (unfortunately)

I am supposed to be using SMCLK. (I will be measuring pulses, that are 0.6 to 1ms on average) I setup TA0CCTL1 and TA0CTL accordingly, input capture mode, both edges rising and falling, and I am quite positive that P1.2 is connected and configured properly. (If I connect it to ground, the ISR will never run)

However, I am getting unexpected values for counter (TA0CCR1) - it will show a value between 15 and 32 at the most, no matter what is the frequency i supply it to. And although changing the frequency does not lead to a change in TA0CCR1 value, adding ID_2, ID_3 to TA0CTL during initialization will result an expected (divided according to) value.

Also, even though the timer is reset by TA0CTL |= TACLR; inside the ISR, for some reason the overflow bit is always on. In the code the while(1) is commented out so it will not freeze at that point, so I can continue debugging.

I have debugged for a while, so I am thinking that either the SMCLK is not configured properly, or there is another problem in the counter code. If the SMCLK was really slow, then it would not have caused the overflow bit to set.

I am new to CCS, and I had been an Energia user, but from this point I would like to do everything in CCS.

Any help/recomendations/ideas are greatly appreciated.

Best Regards,

C.A.

  • Setting TACLR in the interrupt handler is not a good idea because it is not synchronized with the capture. You would get more accurate results by just allowing the timer to continue to count, and subtracting the previous counter value to get the difference.
    (I don't know if the TACLR bit somehow interacts with the raising/falling edge detection.)

    You should clear the COV bit when you've detected it.

  • Hello,


    Based on your recomendations, I modified my code. It kind of works.(*) Problem is I can not observe it works, due to some debugger problem.

    Here is my new code:

    #include <msp430.h> 
    
    volatile unsigned int counter;
    volatile unsigned int prev_counter;
    unsigned int difference;
    
    int main(void)
    {
    
        WDTCTL = WDTPW | WDTHOLD;
    
        // P1.2/TA0.1
        P1DIR &= ~BIT2;
        P1SEL |= BIT2;
    
        // TA0CCR1 Capture mode; CCI1A; Both Rising and Falling Edge; interrupt enable
        TA0CCTL1 = CAP + CM_3 + CCIE + SCS + CCIS_0;
    
        // SMCLK, Cont Mode; start timer
        TA0CTL |= TASSEL_2 + MC_2 + TACLR;
    
        while(1) {
             __bis_SR_register(LPM0_bits + GIE);
            __no_operation();
            // break point here
            difference = counter - prev_counter;
    
            if(TA0CCTL1 & COV) {
              TA0CCTL1 &= ~COV;
            }
        }
    
    }
    
    #pragma vector = TIMER0_A1_VECTOR
    __interrupt void TIMER0_A1_ISR (void)
    {
      switch(__even_in_range(TA0IV,0x0E))
      {
          case TA0IV_NONE: break;
          case TA0IV_TACCR1:
              prev_counter = counter;
              counter = TA0CCR1;
              __bic_SR_register_on_exit(LPM0_bits + GIE);
              break;
          case TA0IV_TACCR2: break;
          case TA0IV_TACCR3: break;
          case TA0IV_TACCR4: break;
          case TA0IV_5: break;
          case TA0IV_6: break;
          case TA0IV_TAIFG: break;
          default: break;
    
      }
    }
    
    

    So the problem is if I set a breakpoint at the line I calculate the difference, and debug that way, it will always show ~50 for the difference expression.

    However if I remove breakpoint, and then start debug, and pause at a random point, it will show the correct values, as output by the frequency generator and as observed with the scope. So it does work, but why does it show not the correct value if I set a debug point?

    Best Regards,

    C.

**Attention** This is a public forum