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: MSP430F5325

Other Parts Discussed in Thread: MSP430F5325

Tool/software: Code Composer Studio

hello all, i am facing a problem to measure timer ticks of a given signal frequency 50Hz square wave on port P1.1, I am using MSP430F5325

i want to measure timer ticks in its ON time i.e. in 10 msec. can anyone tell me how to do it or anyone having sample code for this

also i have a one question, suppose i measure the timer ticks in 10ms then with the help of timer ticks value can i control the pulse width or frequency of that signal?

#include <msp430.h>

unsigned int rising_cap=0;
unsigned int falling_cap=0; volatile unsigned int rising_count = 0;
unsigned int i=0; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer for (i=0; i<20000; i++) // Delay for crystal stabilization { } P1DIR &=~ BIT1; P1SEL |= BIT1; // Set P1.1 to TA0 TA0CCTL0 |= CM_1 + SCS + CCIS_0 + CAP + CCIE; // Rising edge + CCI0A (P1.1) + Capture Mode + Interrupt TA0CCTL1 |= CM_2 + SCS + CCIS_0 + CAP + CCIE; //falling edge, capture mode, interrupt TA0CTL = TASSEL_2; // SMCLK _BIS_SR(GIE); // LPM0 + Enable global ints } #pragma vector = TIMER0_A0_VECTOR __interrupt void Timer0_A0_ISR (void) {
rising_count++;

if (rising_count==2)
{
rising_cap = TA0CCR0;
falling_cap = TA0CCR1;

          }

  • Hello Mohit,

    If you just need to count how many pulses your input signal is doing, then you can just have it tied to the Timer Clock input and it will advance on every pulse.

    If you need to count time between the rising and falling edge and thusly figure out pulse width, then you should use only one CCR in capture mode and have it capture on both falling and rising edge. you can subtract the current capture from the previous one every time the capture updates to figure out how many timer clock cycles have passed between the instances.

    In your code above, you would to need either a separate signal or tie the same signal to whichever pin CCR1 is associated with along with the pin CCR0 is associated with.
  • #include <msp430.h>
    
    unsigned long int current_cap=0,timer_ticks=0;
    unsigned int previous_cap=0;
    volatile unsigned long int capture_count = 0;
    unsigned int i=0;
    
    int main(void)
    {
    
      WDTCTL = WDTPW + WDTHOLD;  // Stop watchdog timer
    
      for (i=0; i<20000; i++)   // Delay for crystal stabilization
      {
      }
    
      P1DIR &=~ BIT1;
      P1SEL |= BIT1;                                    //Set P1.1 to TA0
    
      TA0CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE;     //capture mode, capture on both rising and falling edge,sync, capture interrupt enable
    
      TA0CTL = TASSEL_2;                                //SMCLK, continious mode
    
      _BIS_SR(GIE);                                     // LPM0 + Enable global ints
    
      while(1)
      {
    
      TA0CTL |= MC_2;                             // timer start
      while(capture_count != 2);
      if(capture_count==2)
         {
          TA0CTL &=~ MC_2;                            // timer stop
          TA0CCTL0 &=~ CCIE;                          // use breakpoint here and measure timer_ticks
          TA0CCR0 = 0;
          }
      }
    
    }
    
        #pragma vector = TIMER0_A0_VECTOR
        __interrupt void Timer0_A0_ISR (void)
        {
         capture_count++;
         timer_ticks = TA0CCR0;
        }
    

    Thanks for your precious reply, i have made changes in my code as suggest you.now i m getting timer ticks but the problem is that its vary widely i.e. (12042, 17482, 16782, 17151, 18834, 12465, 12447,15831,10674)

  • Hello Mohit,

    what's your SMCLK speed? You more than likely need to divide this down as your are possibly clocking too fast and getting rollover of the timer. If your SMLCK is default, then 1MHz is way too fast for a 50Hz signal. Think about what resolution is acceptable for your pulse width measurement and back calculate how fast you need to run the timer to achieve that many steps. In most cases, less (speed) is more.
  • The variability comes from the fact that you don't know where in the first period your program starts listening. Since you wait for two edges, you always see more than half of a period, but since you stop after two edges you won't see an entire period.

    Try saving both of the first two captures, then subtract them. I suspect the difference will be consistent.
  • #include <msp430.h>
    
    unsigned long int first_edge=0, second_edge=0;
    volatile unsigned int capture_count = 0, period=0;
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;  // Stop watchdog timer
    
      P1DIR &=~ BIT1;
      P1SEL |= BIT1;                                    //Set P1.1 to TA0
    
      TA0CCTL0 |= CM_1 + SCS + CCIS_0 + CAP + COV + CCIE;     //capture mode, capture on both rising and falling edge,sync, capture interrupt enable
    
      TA0CTL = TASSEL_1 + MC_2;                                //ACLK, continuous mode
    
          _BIS_SR(GIE);
          while(1)
          {
              if(second_edge>first_edge)
              {
              period = (second_edge - first_edge);
              }
              else if(second_edge<first_edge)
              {
              period = (first_edge - second_edge);
              }
          }
    }
        #pragma vector = TIMER0_A0_VECTOR
        __interrupt void Timer0_A0_ISR (void)
        {
          capture_count++;
    
             if (capture_count==1)
                {
                    first_edge = TA0CCR0;
                }
            else if (capture_count==2)
                {
                    second_edge = TA0CCR0;
                    capture_count=0;
                    TA0CCR0=0;
                }
        }
    

    Hello Jace H,

    My controller speed is default 1MHz, and this means i get approx 20,000 clock pulses in one period of 50hz , i mean 20,000 clock pulses in 20ms.

    now i change my controller speed to ACLK (32768 Hz). but this not resolved my issue. same thing happens i get a wide variation, so i have done more changes in my code. please see it.

    in my new code now im facing another problem, the variation is less between two consecutive rising edge, hence calculating period. according to ACLK i got ~ 655 or 656 clocks in 20ms period if 50Hz frequency.

    my question is when the timer overflow i got unwanted results, to overcome this i reset TA0CCR0 value to ZERO but unfortunately it doesnt work and still get unwanted results(variation).

  • #include <msp430.h>
    
    unsigned long int first_edge=0, second_edge=0;
    volatile unsigned int capture_count = 0, period=0;
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;  // Stop watchdog timer
    
      P1DIR &=~ BIT1;
      P1SEL |= BIT1;                                    //Set P1.1 to TA0
    
      TA0CCTL0 |= CM_1 + SCS + CCIS_0 + CAP + COV + CCIE;     //capture mode, capture on both rising and falling edge,sync, capture interrupt enable
    
      TA0CTL = TASSEL_1 + MC_2;                                //ACLK, continuous mode
    
          _BIS_SR(GIE);
          while(1)
          {
              if(second_edge>first_edge)
              {
              period = (second_edge - first_edge);
              }
              else if(second_edge<first_edge)
              {
              period = (first_edge - second_edge);
              }
          }
    }
        #pragma vector = TIMER0_A0_VECTOR
        __interrupt void Timer0_A0_ISR (void)
        {
          capture_count++;
    
             if (capture_count==1)
                {
                    first_edge = TA0CCR0;
                }
            else if (capture_count==2)
                {
                    second_edge = TA0CCR0;
                    capture_count=0;
                    TA0CCR0=0;
                }
        }
    

    Hello, Thanks for your suggestions. i have done implement your ideas in my code. but in my new code now im facing another problem, the variation is less between two consecutive rising edge, hence calculating period. according to ACLK i got ~ 655 or 656 clocks in 20ms period if 50Hz frequency.

    my question is when the timer overflow i got unwanted results, to overcome this i reset TA0CCR0 value to ZERO but unfortunately it doesnt work and still get unwanted results(variation). Please help me as im new in embedded. can you put some line of code to overcome this.

  • > unsigned long int first_edge=0, second_edge=0;
    Make these 16-bit, so the arithmetic works (by definition the difference can't be larger than 16 bits):
    > unsigned int first_edge=0, second_edge=0;
    ---------------
    > if(second_edge>first_edge){
    > period = (second_edge - first_edge);
    > }
    > else if(second_edge<first_edge){
    > period = (first_edge - second_edge);
    > }
    The second_edge is by definition "greater" than the first_edge, so just subtract them. The "magic" of 16-bit unsigned underflow will take care of wraparound. All you need here is:
    > period = (second_edge - first_edge);
    ---------------
    True, it is important to make sure your timer pacing is in a reasonable range for your input signal. For 50Hz, either SMCLK (1MHz) or ACLK (32kHz) is fine, though SMCLK will give you a few more bits of accuracy.
    ---------------
    I notice you've switched from CM_3 (both edges) to CM_1 (rising edge). This is fine, just keep in mind that you're now measuring pulse period (1/frequency), when (I think?) you mentioned pulse width some time back. For purposes of this exercise, either is fine.

    [Edit: Fixed some ambiguous wording.]

  • Also: I just noticed that your loop in main is grabbing the results as fast as (actually faster than) they arrive, so it's likely to see partial results. I suggest an interlock between that loop and the ISR.

    There are various ways to do this. Perhaps the simplest would be to put:
    > LPM0; // Sleep until the ISR says to wake up
    as the first line of the while(1) loop, and add
    > LPM0_EXIT; // Wake up main()
    to the "capture_count == 2" block in the ISR.
  • #include <msp430.h>
    
    unsigned int first_edge=0, second_edge=0, i=0, first_diff=0,secnd_diff=0,third_edge=0,fourth_edge=0,third_diff=0;
    volatile unsigned int capture_count=0;
    
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;  // Stop watchdog timer
    
      for (i=0; i<40000; i++)    // Delay for crystal stabilization
      {
      }
    
      P1DIR &=~ BIT1;
      P1SEL |= BIT1;                                          //Set P1.1 to TA0
    
      TA0CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE + SCCI;    //capture mode, capture on both rising and falling edge,sync, capture interrupt enable
    
      TA0CTL |= TASSEL_1 + MC_2 + TACLR;                      //ACLK, continuous mode,clear timer
    
      _BIS_SR(GIE);
          while(1)
          {
              first_diff = (second_edge-first_edge);
    
              secnd_diff = (third_edge-second_edge);
    
              third_diff = (fourth_edge-third_edge);
          }
    }
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer0_A0_ISR (void)
    {
      capture_count++;
         if (capture_count==1)
            {
                first_edge = TA0CCR0;
            }
        else if (capture_count==2)
            {
                second_edge = TA0CCR0;
            }
        else if (capture_count==3)
            {
                third_edge = TA0CCR0;
            }
        else if (capture_count==4)
            {
                fourth_edge = TA0CCR0;
                TA0R = 0;
                capture_count=0;
            }
    }
    

    Hello,

    when i start timer in capture mode, it will give interrupt on either falling or rising or both edges (right) depending upon CAP mode ?

    my first question is that, the timer clocks i measured is in which part of the sq. wave i.e.  In its ON time or OFF time ?

    second question how can i find out the timer ticks in its ON time ? i have 50% duty cycle.

    third question if i wanted to find out timer ticks on its OFF time then what should i do?

    fourth question that i asked u before is that with the help of timer ticks in its(OFF or ON) time can i control the pulse width and do PWM ?? (yes or no) ??

  • You're still fetching your readings constantly, so at any moment (at least) one of your differences is nonsense. I suggested an interlock scheme above.

    I don't recommend resetting TA0R back to 0, since that will skew your results. This probably doesn't matter much in this limited-function program, but it will later.

    > when i start timer in capture mode, it will give interrupt on either falling or rising or both edges (right) depending upon CAP mode ?
    Depending on the CM setting, yes.

    > my first question is that, the timer clocks i measured is in which part of the sq. wave i.e. In its ON time or OFF time ?
    The ON time is the difference between a rising and falling edge. The timer doesn't tell you which edge it detected, so you have to look, e.g. by (P1IN&BIT1). There is a race here, but with a 50Hz signal you'll pretty much always win.

    > second question how can i find out the timer ticks in its ON time ? i have 50% duty cycle.
    The ON time is the difference between a rising and falling edge. If you have a 50% duty cycle the ON time is (total_period/2) where total_period is the difference between two rising (or two falling) edges.

    > third question if i wanted to find out timer ticks on its OFF time then what should i do?
    The OFF time is the difference between a falling and rising edge. Alternatively, it's (total_period-ON_time).

    > fourth question that i asked u before is that with the help of timer ticks in its(OFF or ON) time can i control the pulse width and do PWM ?? (yes or no) ?
    I didn't answer since the question was incomplete. What signal are you trying to control? Reading your input signal does not implicitly give you control over it. If you have another timer, generating an output, and using the same clock (TASSEL/ID), the units in your capture difference are suitable for putting into a CCR for that other timer.
  • Last I looked (some time ago), TI didn't have an app note covering this topic. However, I am familiar with appnote AVR135 from [Other Guys] which discusses it. It's for a different device, but the principles are common.
  • i did what you say, i implement those things in my code, but my problem didn't solve and did not getting timer ticks("period reads to 0"), so i just remove it and clear the timer counter by setting TA0R =0, then i check the results i got clear results as my timer CCR0 not getting overflow.

    > The ON time is the difference between a rising and falling edge. If you have a 50% duty cycle the ON time is (total_period/2) where total_period is the difference between two rising (or two falling) edges.

    yes ON time is difference between a rising and falling edge but the timer doesn't know which edge is capture first (rising or falling), so (total_period/2)  give ON time value or OFF time value? (total_period/2) lies in which part of a period (ON or OFF)?

    according to the user guide of msp430 CM_3 is capture both falling and rising. means it interrupt on both edges weather the condition of first occur is falling or rising.

    from code i want to pretty much sure that i measure timer ticks in its ON time the value is got is between rising and falling

  • >The ON time is the difference between a rising and falling edge. The timer doesn't tell you which edge it detected, so you have to look, e.g. by (P1IN&BIT1). There is a race here, but with a 50Hz signal you'll pretty much always win.

    I do this (P1IN & BIT1) thing in my code but unfortunately we can only read on LOW sides not on HIGH, as i try both things
    first i read to LOW by setting (P1IN & BIT1)==0.... I got results and do lots of iteration but some are good and most of the results are useless

    now second time i used to read my P1.1 on high (P1IN & BIT1)==1 .this time i didnt get ant time of result coz it didnt read my pin on HIGH condition.

    i crosscheck this thing on a new program only just by setting the condition of HIGH and LOW on a LED, finally i found that i can only read my PIN on LOW condition irrespective of pullup high or pullup low.
  • > (P1IN & BIT1)==1
    This condition is never true -- the result of the & is either 0 or BIT1 (=2). Try:
    > (P1IN & BIT1)!=0

**Attention** This is a public forum