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: Timer A0 issue in MSP430

Part Number: MSP430G2553


Hi Forum experts,

We are trying to run two pheripherls on Timer A0 (Module name is MSP430G2553). One is PWM which is on p3.0 and other we are using as one shot timer.

One shot timer uses TA0CCR0 and our PWM uses TA0CCR2. But when I run the code I'm seeing that PWM duty cycle is not changing why I'm seeing this trouble?

MSP430g2553 has two timers for three capture/compare register, So, why I'm having trouble to configure both at same time?

Please let me know your suggestions if you have faced this kind of difficulty.

  • There's no reason you can't get "double-duty" out of a single timer (TA0 in this case), supposing that the numbers work out right. I wonder why you mentioned the second timer (TA1) since from your description you aren't using it.

    Can you be more specific? Sometimes all it takes is a typo.

  • Hello Bruce,

    We are using Timer0_A3 (TA0) in our application for generating a single shot time (General purpose timer). Our main application also uses capacitive touch sense and using RO_PINOSC_TA0_WDTp touch sense method. As the capacitive touch sense is using TA1 we are using TA0 for single shot time. What we want to achieve is we need PWM to be generated for controlling the LED and single shot time for processing the other events. The PWM frequency can be from 100Hz to 1KHz or ~40KHz.

    For the single shot timer we were using TACCR0, but the PWM module is also using TACCR0 (period) and TACCR2 (Duty cycle). We tried to configure the TACCR0 to generate a specific time (Single shot timer as well as for PWM) and loading a value to TACCR2 for changing the duty cycle, but the duty cycle is not getting changed.

    As the timer module has 3 CCR registers can we achieve what we are expecting?

  • I take one-shot to mean that you count some number of timer (CCR0) periods then declare the one-shot done -- in particular, that you aren't starting and stopping the timer for each use.

    How often are you updating CCR2? One easy mistake is to update it faster than the timer is cycling, so it never has a chance to reach the EQU2 event.

    If you can post some relevant code, e.g. the sequence that updates CCR2, maybe someone will see something.

  • Hi Bruce,

    In the One-shot timer each and every time the CCR0 value is set after 50ms is elapsed so in this timer is started only once during startup intialization of board and it is never halted.

    CCR2 is updated based on external events like in our case we are updating only on capacitive buttons are pressed otherwise CCR2 is not updated.

  • I'm not very familiar with CapSense, but based on the Programmer's Guide (SLAA490D) Table 8, RO_PINOSC_TA0_WDTp uses TA0, not TA1. I'm not sure how you're getting TA0.2 to generate PWM at all.

  • Hi Bruce,

    We are using TA1 for a external event based on GPIO and these are loaded with some predefined values based on events. If RO_PINOSC_TA0_WDTp uses TA0 then in that case our timer shouldn't work for 50msec but it is working perfectly.

  • SLAA490D Sec 4.4.1 claims that it saves and restores the timer settings on each touch poll operation. I can imagine that this could interfere with something like PWM that is expected to run for a long time.

    As I understand your symptom You set some value A into CCR2, and the PWM operates according to that value, but if you then put a different value B into CCR2, the PWM continues to operate (indefinitely) as though CCR2 still had A in it. What does CCR2 actually contain if you read it? I'm wondering whether  CapSense is doing something that restores A back into CCR2. 

  • Hello Bruce,

    We have made a seperate test code where we are using two timers one is one shot timer of 50ms. And other is General purpose timer with SMCLK as a clock source and it is continous mode.We are using P3.0 to generate PWM. CCR1 value is loaded with 4000 and GPIO is set and for off period CCR1 is kept for 1000. It is able to genetate the PWM but for a certain duration is generating then it is set for high again for 300msec. We are unable to identify why we are seeing this GPIO is high for 300mes and it is stopping the PWM generation.

  • If you can attach your test code I may be able to understand your symptom a little better.

  • Hi Bruce,

    Please find the attached code

    #include <msp430.h>
    #include <stdint.h>
    
    
    int timer_count,Duty_cycle_Max[4]={1900,1450,1000,550};
    int Duty_Cycle_Min[4] = {100, 550, 1000, 1450},index;
    static inline void init_sysClock(void)
    {
    	BCSCTL1 = CALBC1_1MHZ;                // Set DCO to 1MHz
    	DCOCTL = CALDCO_1MHZ;
    	BCSCTL3 = LFXT1S_0;                  // LFXT1 = 32KHz
    	BCSCTL2 = SELM_0;						// select SMCLK = MCLK = DCOCLK
    }
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      init_sysClock();
      //P1SEL |= 0x06;                            // P1.1 - P1.2 option select
      P3DIR |= (BIT0 + BIT1);                            // P3.0 - P3.1 outputs
      //P3SEL |= (BIT0 + BIT1);                              // P3.0 - P3.1 outputs
     // P3SEL2 &= ~(BIT0 + BIT1); 
      CCR0 = 10000;
      //CCR2 = 600;
      CCTL0 = CCIE;                  // CCR0 toggle, interrupt enabled
      TA1CCR1 = 500;
      CCTL1 = CCIE;                  // CCR1 toggle, interrupt enabled
      TACTL = TASSEL_2 +  MC_2 + TAIE;          // SMCLK, Contmode, int enabled
      //TACCTL2 = CCIE;
    
      __bis_SR_register(GIE);       // Enter LPM0 w/ interrupt
      while(1)
      {
        uint32_t wait = 0xffff;
        while(wait)
        {
          wait--;
        }
        index++;
        if(index == 4)
        {
                index = 0;
              //  CCTL1 &= ~CCIE;
        }
      }
    }
    
    // Timer A0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A0 (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A0 (void)
    #else
    #error Compiler not supported!
    #endif
    {
        CCR0 += 50000;                              // Add Offset to CCR0
        P3OUT ^= BIT1;
        //CCTL0 &= ~CCIE;
    }
    
    // Timer_A2 Interrupt Vector (TA0IV) handler
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void Timer_A1(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_A1_VECTOR))) Timer_A1 (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch( TA0IV )
      {
      case  2: //CCR1 = 1000;                    // Add Offset to CCR1
               timer_count++;
               if(timer_count == 1)
               {
                 CCR1 += 4500;
                 P3OUT |= BIT0;
                 break;
               }
               CCR1 += 1500;
               P3OUT &= ~BIT0;
               timer_count = 0;
               
               break;
      case 10: 
               //P3OUT ^= BIT1;
               break;
     }
    }

  • > CCR0 += 50000; // Add Offset to CCR0

    > CCR1 += 4500;

    This program uses a "rolling CCR0" approach to timing, which is fine but you need to keep in mind that CCR1 (duty) is relative to its effective PWM cycle, which is defined by CCR0 (which is moving). Conceptually, you want to do something like "CCR1 = CCR0 + 4500", but you can't since it should be set relative to the Next cycle (which won't start until later, when CCR0 is updated).

    By incrementing CCR1 slower than CCR0, you end up with meta-cycles which sometimes work and sometimes don't.

    One simple fix is to use

    > CCR1 = CCR0 + 50000 + 4500;  // duty relative to next cycle

    where 50000 is the (well-known) cycle time.

  • Hi Bruce,

    Even after going as per your suggestion, we are getting blink status in between.

  • Maybe I misunderstood your description. I thought your concern was that the CCR1 signal was drifting with respect to the CCR0 signal, but maybe that was intentional?

    Just watching the raw signals on my scope, I haven't seen any 300ms pulses in 15 minutes. How often does this symptom occur?

    I should also mention that I don't have a 28-pin G2553, so I'm using P1.0/.6 on a 20-pin G2553. Judging from the test code, I don't see how it would differ from P3.0/.1.

  • Hi Bruce,

    Thanks for your support, but we have resolved this issue.

**Attention** This is a public forum