MSP-430 Duty Cycle/PWM

Hello, I am new to the MSP430 and I have been having troubles with the duty cycle. The problem is that I need a duty cycle of 8.33us, with 6.68us one output (P1.0) and 1.45us(P1.6) but the maximum frequency of the MSP430G2231 from what I've read is 32,768.

Here is the sample code I've been using to perform this.

#include "io430.h"

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x41; // P1.0 output and P1.6 output
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = 1000-1;
TACTL = TASSEL_1 + MC_1; // ACLK, upmode

// _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupt causes error, must not be from this MCU.
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{

P1OUT ^= 0x01; // Toggle P1.0

CCR0 += 1000-1; //add offset to CCR0

}

Thanks in advance.

  • Natalia Alicea

    Hello, I am new to the MSP430 and I have been having troubles with the duty cycle. The problem is that I need a duty cycle of 8.33us, with 6.68us one output (P1.0) and 1.45us(P1.6) but the maximum frequency of the MSP430G2231 from what I've read is 32,768.

     Hi Natalia, what this means?

     Duty cycle is specified as a pulse duration or percentage of cycle time, which is your cycle time 8.33uS? it is too fast to use interrupt, it must be set by hardware and also resolution at max speed of 16MHz is near 6-7 bit...

    Natalia Alicea

    // Timer A0 interrupt service routine
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {

    P1OUT ^= 0x01; // Toggle P1.0

    CCR0 += 1000-1; //add offset to CCR0

    }

     This is generating a flashing of led at half the cycle time of timer, timer is fired after every 1000 pulse at rate that I suppose be the standard 1.1MHz of this family.

  • In reply to Roberto Romano:

    Yes, just understood what u meant by doing it by hardware...just trying to figure out how to do it now. By software I managed to get a signal at 80us and 20us but need it faster so going to try that.

  • In reply to Natalia Alicea:

     Hi Natalia, if you wish to generate hardware fast pwm at precise position of ramp then you must set CCR0 to max value and CCR1 and CCR2 at value you wish generate the pulse on dedicated output.

     To do that you need setup I/O subsystem  port (PxDIR to output) to alternate timer function (PxSEL to alternate)  then init timert register to act as UP counter and capture compare channel to do the OUTMOD function more close to your application.

     As an hint start with some hardware generation example from TI distribution and ask again.

  • Natalia Alicea
    the maximum frequency of the MSP430G2231 from what I've read is 32,768.

    This is the frequency of an externally attached watch crystal. The MSP itself can run its CPU and timers with up to 16MHz. However, not as precise and stable as with a crystal.

    The default frequency is 1MHz, which would give you a maximum timer tick resolution of 1µs. However, the resolution of 0.01µs you ask for would require 100MHz clock, whcih is beyond the capabilities of the MSP.

    The maximum clock frequency is 16MHz which would give you 0.0625µs timer resolution (1/16 µs). But unfortunately, this MSP onyl comes wiht one calibrated frequency and it is 1MHz. So for fairly precise 16MHz, you'd have to calibrate each and every MSP on your own.

    But there is another problem: this MSP only has one TimerA2. This means this MSP has only one timer, and besides the CCR unit required for the PWM frequency (TA0CCR0 = 133 for 8,3125µs) there is only one more CCR unit for producing a PWM output. And you need two. So I suggest switching to the MSP430G2553. This one has two timers with three CCR units each, and also provides calibration values for 16MHz.

    One more thing,

    Natalia Alicea
    CCR0 = 1000-1;
    ...
    CCR0 += 1000-1; //add offset to CCR0

    The initialization with -1 is correct, because '0' is a count too, so 0..999 is 1000 counts.
    However, if you progress the register (a mechanism I use too for my 1ms interrupt), then you of course have to add 1000 and not 1000-1.

    Natalia Alicea
    P1DIR |= 0x41; // P1.0 output and P1.6 output

    Why did you set P1.6 to output? The TA0.1 signal on P1.6 comes from the CCR1 unit, not from CCR0. You didn't set an OUTMODe anyway, nor did you set P1SEL.x, so P1.6 is just fixed low output.

    Natalia Alicea
    TACTL = TASSEL_1 + MC_1; // ACLK, upmode

    Combining upmode with interrupt-based increase of CCR0 leads to nice interference patterns.

    The tiemr counts to CCR0, resets to 0 and triggers an interrupt. Insid ethe ISR, CCR0 is incremented, so this time the tiemr counts from 0 to the new CCR0 value, adn again. Your period is increasign with each loop until CCR0 overflows, then the game begins from start with a small speriod, which enlarges by 1000 timer ticks on each loop.
    Definitely not what you wanted. :)