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.

MSP430G2332: How to configure 2 PWM signals?

Part Number: MSP430G2332

Hi, 

I am new to MSP430. I want to have 2 PWM signals. One has 25kHz with 60% duty cycle on P1.1 pin. The other one has 0.016Hz with 75% duty cycle on P2.1 pin. 

Here is what I do. It is very clumsy.

#include <msp430.h>

int main(void)
{
    WDTCTL = WDTPW + WDTHOLD;
    //P2.1 and P2.2
    P2DIR |= 0x07;                            // 
    //PWM
    P1DIR |= 0x04;                            // Set P1.1 to output direction
    P1SEL |= 0x04;                            // P1.1 TA0.1 options
    CCR0 = 38;                             // PWM Period
    CCTL1 = OUTMOD_7;                         // CCR1 reset/set
    CCR1 = 23;                               // pwm 60%
    TACTL = TASSEL_2 + MC_1;                  // SMCLK, up mode

  for (;;)
  {
    volatile unsigned int i,j;
    j = 70;
    i = 10000;                              // Delay
    do
    {
        j--;
        do (i--);
        while (i != 0);
    } while (j != 0);
    P2OUT ^= 0x07;                           // PS12 and LED off
    j = 23;
    i = 10000;                              // Delay
    do
    {
        j--;
        do (i--);
        while (i != 0);
    } while (j != 0);
    P2OUT ^= 0x07;                           // PS12 and LED on
  }
}

Do we have a better way to realize the function?

25kHz PWM has very bad accuracy because SMCLK is around 1MHz. How can I increase the CLK frequency?

Thanks,

Xiaoming

  • Second question first: At startup, SMCLK "vaguely resembles" 1MHz -- when I've looked it's maybe 0.9MHz or 1.1MHz. You want to use the calibrated DCO constants. Curiously, I don't see an example of this in Resource Explorer, but the essence:

    >BCSCTL1 = CALBC1_1MHZ; 
    >DCOCTL = CALDCO_1MHZ; 

    With a calibrated SMCLK, the PWM should be quite accurate.

    --------------------------

    First question: I recommend __delay_cycles over do-loops for delays. __delay_cycles is quite accurate, and it's immune to optimization. To avoid magic numbers, I suggest something like:

    > #define  HZ   1000000UL     // 1MHz

    Then to delay 60 seconds, you can

    > __delay_cycles(60 * HZ);  // 60 seconds

    ---------------------------

    Your timer setup for 25kHz becomes:

    #define PWM_HZ  25000UL   // 25kHz

    > CCR0 = HZ / PWM_HZ - 1;  // PWM period at 25kHz

    > CCR1 = ((6 * HZ / 10) / PWM_HZ);  // 60% duty at 25kHz 

    [Edit: Removed unneeded cast for readability.]

  • Thank you for your answer! Your recommendation works. 

    I have one more question:

    25kHz has bad resolution since it is based on 1MHz clock. I mean I can create accurate 60% duty cycle but not 61%. For 1MHz clock based 25kHz PWM, one step is 2.5% duty cycle difference. How can I make the resolution better?

    Regards,

    Xiaoming

  • According to the data sheet (SLAS723H) p. 1 the G2332 has 4x calibrated clock frequencies: [1,8,12,16]MHz. If you use (e.g.) CALDCO_8MHZ/CALBC1_8MHZ (and change HZ) I'm pretty sure the arithmetic still works. This would give you resolution of 25kHz/8MHz= ~0.3%. __delay_cycles uses an "unsigned long" (32 bits) but I don't think you're near that limit yet.

    Using >= 8MHz also opens up the possibility of using the PWM timer (interrupt) to count up to 60 seconds. This would allow your program to do something else rather than just spinning in __delay_cycles all the time. But if what you have does what you want, that's fine.

  • Hi Bruce,

    Thank you for your help!

**Attention** This is a public forum