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.

MSP430F2122: PWM Startup Initial Pulse Overlap with Second PWM Pulse in UP/Down Configuration

Part Number: MSP430F2122


When the device is initially powered up the first pulse is always considerably longer than the desired set point. Once the device is running and inputs direct it back to the start of the main code the pulse width is always correct. I'm only seeing the issue on startup of the very first pulse.  

//Setup Timer for PWM
	TACCR0 = 360 - 1;                       // Pulse Frequency
	TACCR1 = 0;                             // Pulse Width - 0 is OFF ?
	TACCTL1 = OUTMOD_2;                     // TA0CCR2 toggle mode
	TACCTL2 = OUTMOD_6;                     // TA0CCR2 toggle mode
	TA0CTL = TASSEL_2 + MC_0;               // SMCLK, up/down mode
	TACCR2 = (TACCR0 - TACCR1);             // Set Hi/Lo Pulse Equal

//function called to start PWM output

volatile int Test_Volt(volatile int m)
{
    volatile int i = 0;
    TACCR1 = 25;                        // Set width value
    TA0CTL = TASSEL_2 + MC_3;           // Start 
    TACCR2 = (TACCR0 - TACCR1);
    for (i=0;i<10;)                     // Code to loop
    {
    while ((TACTL & CCIFG) == 1)
    {i++;
    break;
    }
    }

    TACCR1 = 0;
    TACCR2 = (TACCR0 - TACCR1);
    TA0CTL = TASSEL_2 + MC_0;           // Stop pulses for test
    TA0CTL = TASSEL_2 + MC_3;
    for (i=0;i<60;)                     // Code to loop
        {
        while ((TACTL & CCIFG) == 1)
        {i++;
        break;
        }
        }


    ADC10CTL1 |= INCH_1;                //Select Analog Input
    ADC10CTL0 |= ENC + ADC10SC;         // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);
           if (ADC10MEM < 512)
           {
           P1OUT &= ~BIT0;              // Turn off 1 LED
           P1OUT |=BIT1;                // Turn on 2 LED
           ADC10CTL0 &= ~ENC;           // Stop ADC
           ADC10CTL1 &= ~ INCH_15;      // Clear ADC Pin Select
           m = 1;
           return m;
           }
           else{
           P1OUT |= BIT0;               // Turn on 1 LED
           ADC10CTL0 &= ~ENC;           // Stop ADC
           ADC10CTL1 &= ~ INCH_15;}     // Clear ADC Pin Select
           m = 0;
           return m;
}
	

  • Hi Josh,

    I'm not sure what "inputs direct it back to the start of the main code" means. Is there a chance that the initial timer code is different than what gets repeated later?

  • I'm assuming the yellow trace is TACCR2 output and the blue trace is TACCR1 output in your scope shot. I tried to draw this out with the help of Figure 12-9 in the MSP430x2xx Family User's Guide. I can see how the blue pulse and second yellow pulse would continue opposite from each other, enabling dead zones.

    Let's assume the setup code gets executed first, then the code in Test_Volt(). By setting TACCR1 equal to zero, that makes TACCR2 equal to TACCR0 in the setup code. That may be an undefined state that's causing what you're seeing, since you're using Up/Down mode which centers the TACCR1 and TACCR2 outputs around TACCR0. I'm not sure what would happen if TACCR2 equals TACCR0, since TACCR2 is intended to be less than TACCR0 to provide a pulse centered around TACCR0. If it's equal, it may be trying to go high and low at the same time!

    Try increasing TACCR1 from 0 to 1 in your setup code. I suspect that you won't see this strange behavior, since TACCR2 would be less than TACCR0.

  • volatile int Test_Rail(volatile int m)
    {
        volatile int i = 0;
        TA0CTL = TASSEL_2 + MC_3;
        TACCR1 = 1;
        TACCR2 = (TACCR0 - TACCR1);
        TA0CTL = TASSEL_2 + MC_3;
        TACCR1 = 20;
        TACCR2 = (TACCR0 - TACCR1);
        for (i=0;i<5;)                     // Code to loop and count 5 pwm periods
        {
        while ((TACTL & TAIFG) == 1)
        {i++;
        TACTL &= ~TAIFG;
        break;
        }
        }
        TA0CTL = TASSEL_2 + MC_0 + TACLR;
        TACCR1 = 0;
        TACCR2 = (TACCR0 - TACCR1);
        TA0CTL = TASSEL_2 + MC_3;
        for (i=0;i<3;)                     // Code to loop and count 3 pwm periods
            {
            while ((TACTL & TAIFG) == 1)
            {i++;
            TACTL &= ~TAIFG;
            break;
            }
            }
    
    
        ADC10CTL1 |= INCH_1;                //Select Analog Input
        ADC10CTL0 |= ENC + ADC10SC;         // Sampling and conversion start
        __bis_SR_register(CPUOFF + GIE);
               if (ADC10MEM < 512)
               {
               P1OUT &= ~BIT0;              // Turn off 1 LED
               P1OUT |=BIT1;                // Turn on 2 LED
               ADC10CTL0 &= ~ENC;           // Stop ADC
               ADC10CTL1 &= ~ INCH_15;      // Clear ADC Pin Select
               m = 1;
               return m;
               }
               else{
               P1OUT |= BIT0;               // Turn on 1 LED
               ADC10CTL0 &= ~ENC;           // Stop ADC
               ADC10CTL1 &= ~ INCH_15;}     // Clear ADC Pin Select
               m = 0;
               return m;
    }

    I was playing around with this yesterday before I saw your response and it does seem that setting TACCR1 = 1 might be helping. I've also changed the code not to loop back through the test section if it fails the test. When it is set to loop back through it seems half the time the first pulse will be how it should, and half the time it will be a long pulse as pictured. 

    On a side note, I've noticed that setting the DCO to 1mhz or up to 16mhz appears to have no effect on my switching frequency. I thought the clock was linked?

    I'm using  the following code at the start to set the clock. Perhaps i'm doing something wrong here.

    //Setup Clock
    DCOCTL = 0; // Select lowest DCOx and MODx settings
    BCSCTL1 = CALBC1_16MHZ; // Set DCO to 16MHz
    DCOCTL = CALDCO_16MHZ;

  • Keep in mind that TAIFG gets set in the middle of the TACCR1 output pulse, so it won't be a full cycle like TACCR2. I would simply set up the timer once with TACCR1 and TACCR2 < TACCR0, start the timer and measure the outputs.

    There are several PWM examples in TI Resource Explorer that may be helpful. You can also find clock examples. If you're changing the DCO frequency and you're not seeing the timer period change, then I suspect SMCLK is not equal to MCLK. TASSEL_2 selects SMCLK, not MCLK.

  • I managed to clear the calibration memory which in turn caused the second lines of my code of calling the values to load clock settings useless. 

**Attention** This is a public forum