Jump to content

Enable PWM on Port 2 of MSP430

Recommended Posts

I was looking at the header file, but I can't find it mentioned  as Unsigned....how do you know this, is it in any manual?, I just followed 32767 becasue I thought that I had to match the clock speed. The limitations on choosing a diiferent CCR0 values: does it come from the var type only, or do you have hardware constrains?

Do you think that some outmnodes are better than others for a particular application (or suitable),: dc motors, steppers, servos, led etc?


Please send a link to you video of polymorphic tune player :smile:

Meanwhile I'm going to test the SLAA120 "PWM DC Motor Control Using Timer_A of the MSP430" it seem like a good next step on my learning curve.


Thanks and greets all


(1) because it was a 16bit timer and msp430s are 16bit MCUs (so general registers are 16bit wide), it's usually too obvious and u will miss it. and at machine level everything is unsigned, until your application decides it need negative number representation.


from slau144



12.1 Timer_A Introduction
Timer_A is a 16-bit timer/counter with three capture/compare registers. Timer_A can support multiple
capture/compares, PWM outputs, and interval timing. Timer_A also has extensive interrupt capabilities.
Interrupts may be generated


(2) i can't advise u on which outmod to use on what application as i am no expert. i am just a better manual / pdf reader than u :smile: . they all can be useful in many different applications. for myself, i always tried to find the most simplistic solution (that includes layout and assembly). most times my solutions are not well thought-thru and very un-reliable (hacks). as it is just a hobby to me.


(3) i don't want u hi-jack this thread for my projects. there is this "bad-apple" video + audio toy i did for a POTM (project of the month) last last year. here is the link.http://forum.43oh.com/topic/1501-ti-launchpad-plays-bad-apple/


i kind of enjoy the sound, but this was done w/ s/w mixing to get polyphonic, u can watch the youtube to see how it sound like (i didn't capture in good quality though). an older version is using timer channels and outmod4 to flip pins. i will post the "setup" code below. it's not pwm, just square waves.


(4) i has this link bookmarked which is quite useful to reach the more important msp430 datasheets.




i think u can also benefit by the wiki msp430, it had a more general description (more easy to understand) for beginners. it work for me when i started w/ msp430.

Share this post

Link to post
Share on other sites


here is a polyphonic tune player setup w/ 5 timer channels. the setup relatively straight-forward and the interrupt is interesting as there are only two interrupt handler slots for 3 channels.

#include <msp430.h>
#include <stdio.h>

// .. blah blah omitted something

//  c chung (www.simpleavr.com)
//  November 1, 2011
//  . this project requires a g2553 taking advantage of it's dual timer As
//  . since i am using the dip packaged g2553, only 5 channels are available
//  . likewise u can reduce to 2 channels for g2231, g2452 etc
//  . for 28pin tsop g2553s, 6 channel is possible (via TA2/CCTL2)
//  . use included tune.pl to generate "content.h" from midi file
//  . see tune.pl for options
   5 channel polyphonic tone player

//           MSP430G2553
//         ---------------
//     /|\|            XIN|-
//      | |               |
//      --|RST        XOUT|-             +--[ 2.2k ]-+-----o audio Out, buzzer, earphone, etc
//        |               |              |           |     o
//        |  (TA0.0)  P1.1|--[ 39ohm ]---+          ---    |    (try different values for your low-pass)
//        |  (TA0.1)  P1.2|--[ 39ohm ]---+     0.1u ---    |
//        |  (TA1.0)  P2.0|--[ 39ohm ]---+           |     |
//        |  (TA1.1)  P2.1|--[ 39ohm ]---+          ___   ___
//        |  (TA1.2)  P2.4|--[ 39ohm ]---+          ///   ///

uint8_t notes[] = { 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62, };

#include "mmc.h"
#include "content.h"
#define isdigit(n) (n >= '0' && n <= '9')       // totally unrelated and not used macro

volatile uint16_t play_at[] = { 0, 0, 0, 0, 0, };
volatile uint8_t  ticks = 0;

int main(void) {
    IE1 |= WDTIE;

    // all counters from 2 timers set to pin toggle, w/ interrupt enabled
    P1DIR |= BIT1|BIT2;
    TA0CCR0 = TA0CCR1 = 0;
    TA0CTL = TASSEL_2 + MC_2 + TAIE;

    P2DIR |= (BIT0|BIT1|BIT4);
    TA1CCR0 = TA1CCR1 = TA1CCR2 = 0;
    TA1CTL = TASSEL_2 + MC_2 + TAIE;


    const uint8_t *p = data;
    const uint8_t pin[] = { 0x01, 0x02, 0x10, 0x11, 0x14, };
    uint8_t init = 0;
    uint8_t cmd  = 4;

    while (*p) {
        uint8_t dur = *p++;

        while (ticks) asm("nop");       // wait it out

        uint8_t i;
        for (i=0;i<5;i++) {
            if (!init || *(p-6) != *p) {
                uint8_t note = *p;
                if (note) {
                    uint16_t freq = notes[note%12];
                    note /= 12;

                    while (--note) freq <<= 1;          // calculate (approximate) frequency
                    play_at[i] = (8000000/freq) -1;     // this is the count we need for pwm
                    if (i <= cmd) {
                        if (pin[i] < 0x10)              // turn on timer output
                            P1SEL |= (1<<pin[i]);
                            P2SEL |= (1<<(pin[i]&0x0f));
                else {
                    if (pin[i] < 0x10)                  // silent, turn output pin off
                        P1SEL &= ~(1<<pin[i]);
                        P2SEL &= ~(1<<(pin[i]&0x0f));

        init = 1;

        ticks = dur/TICK_DIV;       // approximate timing from perl script



//interrupt(TIMERA0_VECTOR) Timer_A0(void) {
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer0_A0 (void) {
    CCR0 += play_at[0];
//interrupt(TIMERA1_VECTOR) Timer_A1(void) {
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer0_A1 (void) {
    switch(TAIV) {
        case  2:
            CCR1 += play_at[1];
        case 10:
            if (ticks) ticks--;

//interrupt(TIMERB0_VECTOR) Timer_B0(void) {
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A0 (void) {
    TA1CCR0 += play_at[2];

//interrupt(TIMERB1_VECTOR) Timer_B1(void) {
#pragma vector=TIMER1_A1_VECTOR
__interrupt void Timer1_A1 (void) {
    switch(TA1IV) {
        case  2:
            TA1CCR1 += play_at[3];
        case  4:
            TA1CCR2 += play_at[4];
        case 10:



Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now