13
May 12
MSP430G2452 PWM example
With the TI MSP430G2452 you can use the internal timer to generate a PWM modulated output. Not all the IO pins can be used as an timer output for PWM, so you need to check the datasheet for the MSP430 uC for the pin description.
In this example the TimerA0 is running in count-up mode counting up to TACCR0. Every time the TimerA0 counts to TACCR1 the specified output pin is set to high until the counter reaches TACCR0 where the output pin is set to low again.
So with the modification of TACCR0 and TACCR1 you can modify the duty cycle of the PWM signal on the output pin. The duty cycle is the ratio of signal high time to signal low time and equal to TACCR1/TACCR0.
The complete periode time of the PWM signal is set with the TACCR0 value.
To show how different duty cycles effect the output pin, the button on the launchpad is configured as an input for increasing the duty cycle by 10% on each button push.
(This example code is for the msp-gcc4 compiler. If you use a different compiler you need to check the interrupt vector names in your msp430g2452.h file for the correct vector names)
#include <msp430g2452.h> #include <legacymsp430.h>
/* Ratio for this PWM test ist TACCR1/TACCR0 (duty cycle) Select low values for both registers for higher sampling frequency */
int main(void) { WDTCTL = WDTPW + WDTHOLD; DCOCTL= 0; BCSCTL1= CALBC1_1MHZ; DCOCTL= CALDCO_1MHZ; P1DIR = BIT6 | BIT0 | BIT4; P1OUT &= ~(BIT6 | BIT0 | BIT4); P1DIR &= ~BIT3; P1IE |= BIT3; // P1.3 interrupt enable P1IFG &= ~BIT3; // P1.3 IFG cleared P1REN |= BIT3; // P1.3 Resistor enable (Pull up or Pull down) // set sub-system clock divider to 8 BCSCTL2 |= DIVS_3; // set TACCRO register -> count to TACCR0 = 100; // select TimerA source SMCLK, set mode to up-counting TACTL = TASSEL_2 | MC_1; // set ouput to Port P1.6 P1SEL |= BIT6; // select timer compare mode TACCTL1 = OUTMOD_7 | CCIE; // Interrupt called when counter reaches TACCR1 // set up counter_limit for interrupt TIMER0_A1_VECTOR TACCR1 = 0;
// enable all interrupts __enable_interrupt(); // endless loop for (;;) { } return 0; }
// This will be called when timer counts to TACCR1. interrupt(TIMER0_A1_VECTOR) ta1_isr(void) { // clear interrupt flag TACCTL1 &= ~CCIFG; }
interrupt(PORT1_VECTOR) p1_isr(void) { if (P1IN & BIT3) { TACCR1 = (TACCR1 +10)%100; } P1OUT ^= BIT0; P1IFG &= ~BIT3; // P1.3 IFG cleared P1IES ^= BIT3; }