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.

Pulse Width Modulation and MSP430

Other Parts Discussed in Thread: MSP430F5438, MSP430F5438A, MSP430F5529

Hi, 

I am new to MSP430 series microcontroller. I am trying to do pulse width modulation. My code is as follows 
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD;                 
TA1CCTL0 = 0x0040;                       
TA1CTL = 0x0110;
TA1CCR0 = 655;
TA1CCR1 = 327;
P2DIR |= 0x02;                            
P2SEL |= 0x02;                            
//TA1CTL = TASSEL_1 + MC_1 + TACLR;       
 __bis_SR_register(LPM3_bits);           
// __no_operation();                        
}
MSP430F5438 counts up to 655 with no problem. I get 50Hz time period. The clock is 32KHz. The problem is that MSP is not taking the "TA1CCR1" value "327" into account. "327" suppose to give me 50% duty cycle. I am not able to control the Duty Cycle. The time period is correct 20msec but I have no control over Duty Cycle. Please advise!
jess
  • Jessica:

    Here is one of the TI examples - it looks like you are close. (msp430x54xA_ta3_16.c)

    //*******************************************************************************
    //  MSP430F543xA Demo - Timer_A3, PWM TA1.1-2, Up Mode, DCO SMCLK
    //
    //  Description: This program generates two PWM outputs on P2.2,P2.3 using
    //  Timer1_A configured for up mode. The value in CCR0, 512-1, defines the PWM
    //  period and the values in CCR1 and CCR2 the PWM duty cycles. Using ~1.045MHz
    //  SMCLK as TACLK, the timer period is ~500us with a 75% duty cycle on P2.2
    //  and 25% on P2.3.
    //  ACLK = n/a, SMCLK = MCLK = TACLK = default DCO ~1.045MHz.
    //
    //                MSP430F5438A
    //            -------------------
    //        /|\|                   |
    //         | |                   |
    //         --|RST                |
    //           |                   |
    //           |         P2.2/TA1.1|--> CCR1 - 75% PWM
    //           |         P2.3/TA1.2|--> CCR2 - 25% PWM
    //
    //   M. Morales
    //   Texas Instruments Inc.
    //   June 2009
    //   Built with CCE Version: 3.2.2 and IAR Embedded Workbench Version: 4.11B
    //******************************************************************************

    #include <msp430.h>

    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      P2DIR |= 0x0C;                            // P2.2 and P2.3 output
      P2SEL |= 0x0C;                            // P2.2 and P2.3 options select
      TA1CCR0 = 512-1;                          // PWM Period
      TA1CCTL1 = OUTMOD_7;                      // CCR1 reset/set
      TA1CCR1 = 384;                            // CCR1 PWM duty cycle
      TA1CCTL2 = OUTMOD_7;                      // CCR2 reset/set
      TA1CCR2 = 128;                            // CCR2 PWM duty cycle
      TA1CTL = TASSEL_2 + MC_1 + TACLR;         // SMCLK, up mode, clear TAR

      __bis_SR_register(LPM0_bits);             // Enter LPM0
      __no_operation();                         // For debugger
    }

  • Hi, 

    Thanks. I am trying just to get the output on one port pin P2.1 . I want the Timer A count from 327 to 654. Why my original code is not taking 327 into account? Why Timer A is not counting from 327 to 654? I expect my code to TURN the output high (P2.1) from 327 to 654 and then keep it low from 0 to 327. 

    jess

  • Hi Jessica, 

    There's a problem in using pin attached into the CCR0 like P2.1.

    CCR0 is used to reset the timer. The timer simply counts up. When it reaches CCR0 it resets, and that set's the period.

    CCR1 and CCR2 invert the output to 0 when their value is reaches and that way they control the duty to the pins they are attached too. 

    When the timer resets the output goes back to high, that happens when the CCR0 value is reached, if you are using the up mode.

    I don't know if there is even a way to use CCR0 connected pins for PWM 

  • you cant really use any pin connected to the CCR0 has a PWM output, only for other timer functions like capture

  • Luis, you can. However, using CCR0 for PWM requires additional software support. Let the timer run in cont mode then and change the CCRx values on each compare interrupt. This method can also be used if you need different cycle lengths for the CCRs (in up mode with plain hardware PWM, you have same cycle length for all CCRs, set by CCR0).

  • Jessica:

    Is this a trick question from a professor?

    It actually looks like you could get 50% (only) duty cycle by setting up the right mode and counting up and down, with a plus output on the up count and a ground on the down count. However, it is not adjustable at all, so it hardly qualifies as a "PWM." I think the solution I showed earlier from TI is a pretty good fit for what you really wanted.

  • So how can this PWM be applied to a MSP430F5529? I couldn't get the modifications to the code from the comments
  • Rather than adapting this code, it's probably better to start with one of the TI examples (SLAC300G) from the MSP430F5529 product page.

    Example MSP430F55xx_ta2_19.c might be a good bet.
  • The timer modules are identical for all MSPs. So TimerA on the 5438 is operating the same way (with the same configuration instructions) as on the 5529. The only difference is the port pin initialization, as the timer outputs are routed to different pins on different MSPs.

    I wouldn't follow Bruce's advice to start with the TI examples. They are a good starting point when trying to understand how timers work. If you really fully understood how an example is working, you are prepared for writing your own code from scratch. (and if you really understood, you'll also understand, why)
    But trying to use an example as code base for your project is not a good idea. It usually only brings sorrow and sub-optimal results. Either an example does exactly what you need, for exactly the MSP it was written for, or you're better off with your own code.
    Tip: take a sheet of paper and a ruler and draw a time line, then go along the line and simulate what happens at which count for a specific setting, based on the user's guide documentation. Compare this with a drawing of what you want to achieve. If they match, you're half way to your goal. (the other half is writing code that really does what you think it should do)

**Attention** This is a public forum