MSP430
Timers
and PWM

Modified

Ray Wisman

Resources

Timers - http://www.ccs.neu.edu/home/noubir/Courses/SWARM/S09/slides/msp430-clocks-timers.pdf

Pulse Width Modulation Video (not me but still worthwhile) - http://www.pdnotebook.com/2012/06/videopulse-width-modulation/

Pulse width modulation described - http://en.wikipedia.org/wiki/Pulse-width_modulation

Clocks

A clock signal controls timing on a computer, a typical digital clock signal is below.

 

MSP430 CPU and other system devices use three internal clocks:

  1. Master clock, MCLK, is used by the CPU and a few peripherals.
     
  2. Subsystem master clock, SMCLK, is distributed to peripherals.
     
  3. Auxiliary clock, ACLK, is also distributed to peripherals.

Typically SMCLK runs at the same frequency as MCLK, both in the megahertz range.

ACLK is often derived from a watch crystal and therefore runs at a much lower frequency. Most peripherals can select their clock from either SMCLK or ACLK.

For the MSP430 processor, both the MCLK and SMCLK clocks are supplied by an internal digitally controlled oscillator (DCO), which runs at about 1.1 MHz.

DCO - Digitally Controlled Oscillator internal runs at about 1Mhz.

The frequency of the DCO is controlled through sets of bits in the module’s registers at three levels. There calibrated frequencies of 1, 8, 12, and 16 MHz. To change frequency simply copy values into the clock module registers.

The following sets the DCO used by the CPU to 1MHz, which seems to be the default value:

BCSCTL1 = CALBC1_1MHZ;     // Set range

DCOCTL = CALDCO_1MHZ;     // Set DCO step and modulation

 

Timers/Counters

Timers are fundamentally counters driven by a clock signal, commonly incrementing or decrementing the counter on each clock tick.

When the counter reaches some predefined value (e.g. 0), the timer can generate an interrupt. The result is a reasonably accurate time base for executing functionality such as maintaining a reference clock (seconds, minutes, etc.) or performing some operation on a regular basis (blink a LED every second).

The count of a 16-bit timer in continuous mode below repeats counting from 0 to FFFFh. Using UP mode, other limits can be specified.

The clock tick drives the counter, with each clock tick incrementing the counter.

MSP430 timers can interrupt (TAIFG) when the timer reaches a specified limit, serving to perform accurately timed operations.

For example, a timer clock of FFFFh Hz and a count limit of FFFFh could generate an interrupt every second by setting the TAIFG.

 

The MSP430 has many options for creating timers, we will limit ourselves to a simple one that illustrates the basic concepts.

Keep in mind a timer has at least 3 key parts:

  1. clock input that ticks at a specified rate,
     
  2. counter that counts the clock ticks in UP mode,
     
  3. interrupt procedure called when count limit reached.

Timer

TA0CTL

Timer A0 control register.

TASSEL_1 = 01 in bits 9-8, selects timer A 0 source clock as ACLK, 12KHz.

MC_1 = 01 in bits 5-4, sets UP count mode, counting up to the value in TA0CCR0 and generating an interrupt if enabled.

Counter

TA0CCTL0

Control register for Timer A0 counter 0. Interrupts are enabled by writing a 1 into bit 4 of this register.

TA0CCR0

Holds the 16-bit count value.

12000 is used because the ACLK clock operates at approximately 12KHz and we want to toggle the LEDs at approximately at one second intervals. With interrupts enabled, an interrupt is generated when the count reaches 12000.

The counter, in UP mode, is automatically reset to 0 when count limit reached.

Interrupts

TA0CCTL0

Enables/disables timer A0 interrupts

TIMER0_A0_VECTOR

Vector for timer A0

 

One important point is that timers can run independently to the CPU clock, allowing the CPU to be turned off and then automatically turned on when an interrupt occurs.

_BIS_SR(LPM0_bits + GIE);           places CPU in low power mode with interrupts enabled.

SR/R2

Status register.

CPUOFF = 1 in bit 4 turns off the CPU until interrupt occurs.

GIE = 1 in bit 3 enables global interrupts (same as EINT instruction).

Full disclosure

Counters in the examples are off by 1. Since the count starts at 0, a count of 12000 would have a limit of 11999. For clarity and arithmetic ease, we'll live with the small error.

14. Toggle red LED every second.
#include <msp430g2553.h>

void main(void) {
	WDTCTL = WDTPW + WDTHOLD; 			// Stop watchdog timer

	P1DIR |= BIT0; 					// Set P1.0 to output direction
	P1OUT &= ~BIT0; 			     	// Set the red LED on

	TA0CCR0 = 12000;					// Count limit (16 bit)

	TA0CCTL0 = 0x10;					// Enable counter interrupts, bit 4=1

	TA0CTL = TASSEL_1 + MC_1; 			// Timer A 0 with ACLK @ 12KHz, count UP

	_BIS_SR(LPM0_bits + GIE); 	          // LPM0 (low power mode) with interrupts enabled
} 

#pragma vector=TIMER0_A0_VECTOR
   __interrupt void Timer0_A0 (void) {		// Timer0 A0 interrupt service routine

	P1OUT ^= BIT0;						// Toggle red LED
}	

Question 1

Timer A0 source clock selected as ACLK @ 12KHz.

  1. What happens if this statement is removed?                    _BIS_SR(LPM0_bits + GIE);
     
  2. What happens if this statement is removed?                    TA0CCTL0 = 0x10;
     
  3. What happens if the above statement is changed to:        _BIS_SR(LPM3_bits + GIE);
     
  4. What happens if statement in a. is replaced by:               _BIS_SR(GIE);
     
  5. What changes are needed to toggle every 3 seconds?
     
  6. What changes are needed to toggle every 30 seconds?
     

http://mspsci.blogspot.com/2010/08/tutorial-09-timers.html

There are three modes to operate Timer_A.

Continuous mode: Timer_A acts just like a 16-digit, binary odometer; it counts from 0 to 0xFFFF and then "rolls over" to 0 again.

Up mode; as in continuous mode, counts up to set limit then rolls over to 0.

Up/down mode, is similar to up mode having an upper limit. Rather than rolling over to 0, it turns around and counts down to 0.

In addition to the three ways of counting in Timer_A, there are also a few ways to use the counter.

Timer_A has the ability to set "checkpoints" in its counting (Value Line devices only have two, but other devices have a third). TI calls these checkpoints Capture/Compare Registers. The most basic use of these registers is to set values at which the counter flags the processor to do something special. One of these registers sets the upper limit in up and up/down mode. The other register only flags the processor and allows the timer to keep on counting. (This is also the behavior of the first register in continuous mode.)

This type of use is the Compare mode of the register; we set a value that is compared to the current count in Timer_A. If the values are equal, it signals that's the case to the processor. Capture mode behaves a little differently; the timer waits for some type of signal (often from some sort of input) and then records the current value of the timer in the register without stopping the timer, somewhat like the lap time function of a stopwatch.

Registers

There are at least seven registers used in any device with the Timer_A peripheral. In the Family User's Guide, pages 12-20 through 12-23 list the register maps.

TA0CTL -- The Timer_A Control Register is used to set up the source between the timer and a clock, and select the mode used.

The TASSELx bits (8 and 9) tell the timer which clock to use as its source.

TASSEL_0  = TACLK

TASSEL_1  = ACLK @ 12KHz.

TASSEL_2  = SMCLK @ 1MHz

TASSEL_3  = INCLK

The clock frequency can be divided by a further factor of 2, 4, or 8 using the IDx bits (6 and 7). (Note that this is further division to any divisions done from the clock source for the clock itself; could potentially have a total division of up to 64 from the clock source for this peripheral.)

The MCx bits (4 and 5) select the particular mode for the timer to use. Note particularly that setting these bits to 0 (the default setting on POR) halts the timer completely.

TACLR is bit 2. If you write a 1 to this bit, it resets the timer. The MSP430 will automatically reset this bit to zero after resetting the timer.

TAIE and TAIFG (bits 0 and 1) control the ability of the timer to trigger interrupts.

TA0R -- The Timer_A Register is the actual counter; reading this register reports the current value of the counter.

TA0CCRx -- The Timer_A Capture/Compare Registers, of which there are two (TACCR0 and TACCR1) are where specific values to use are stored. In compare mode, the timer signals an event on the values. Particularly, TACCR0 stores the value that Timer_A counts in up and up/down mode. In capture mode, the processor will record the value of TAR when the MSP430 is signaled to do so.

TA0CCTLx -- The Timer_A Capture/Compare Control Registers correspond to the TACCRx registers. These set the behavior of how the CCR's are used.

CMx (bits 14 and 15) change what type(s) of signals tell the timer to perform a capture.

CCISx (bits 12 and 13) select where the input signals are taken.

SCS and SCCI (bits 11 and 10 respectively) change the synchronicity; the timer normally operates asynchronously to the input signals.

CAP (bit 8) changes whether capture mode (1) or compare mode (0) is used.

OUTMODx (bits 5-7) select various output modes for the CCR's signal when the timer flags a capture or compare event.

CCIE and CCIFG (bits 4 and 0) are more interrupts associated with the CCR's.

CCI and OUT (bits 3 and 2) are the input and output for the CCR.

COV (bit 1) is the capture overflow; this bit is set to 1 if two captures are signaled before the first capture value is able to be read.

TA0IV -- The Timer_A Interrupt Vector Register; since there are multiple types of interrupts that can be flagged by Timer_A, this register holds details on what interrupts have been flagged.

The only bits used here are bits 1-3 (TAIVx), which show the type of interrupt that has happened, allowing us to take different actions to resolve the different types of interrupts.

Figure below lists the Timer0 and Timer1 registers and values for the program that follows:

15. Toggle red LED every two seconds/green LED every second.

#include <msp430g2553.h>

void main(void) {

  WDTCTL = WDTPW + WDTHOLD;        // Stop watchdog timer

  P1DIR |= BIT0;                   // Set P1.0 to output direction
  P1OUT &= ~BIT0;                  // Set the red LED off

  P1DIR |= BIT6;                   // Set P1.6 to output direction
 
P1OUT &= ~BIT6;                  // Set the green LED off

  TA0CCR0 = 12000;                 // Count limit (16 bit)
 
TA0CCTL0 = 0x10;                 // Enable Timer A0 interrupts, bit 4=1
 
TA0CTL = TASSEL_1 + MC_1;        // Timer A0 with ACLK, count UP

  TA1CCR0 = 24000;                 // Count limit (16 bit)
 
TA1CCTL0 = 0x10;                 // Enable Timer A1 interrupts, bit 4=1
 
TA1CTL = TASSEL_1 + MC_1;        // Timer A1 with ACLK, count UP

  _BIS_SR(LPM0_bits + GIE);        // LPM0 (low power mode) interrupts enabled

}

#pragma vector=TIMER1_A0_VECTOR    // Timer1 A0 interrupt service routine

  __interrupt void Timer1_A0 (void) {

   P1OUT ^= BIT0;                  // Toggle red LED
}

#pragma vector=TIMER0_A0_VECTOR    // Timer0 A0 interrupt service routine

  __interrupt void Timer0_A0 (void) {

   P1OUT ^= BIT6;                  // Toggle green LED
}

Question 1.5

Timer clock set to ACLK @ 12KHz by:                     TA0CTL = TASSEL_1 + MC_1;
                                    TA1CTL = TASSEL_1 + MC_1;

  1. What results by the change of:                       TA1CCR0 = 12000;
     
  2. What results by the changes to SMCLK @ 1MHz:  TA1CTL = TASSEL_2 + MC_1;
                                        TA1CCR0 = 50000;
     

 

Example timing ADC conversion by timer.

Toogle green LED on Timer0 interrupt and start ADC conversion.

Toogle red LED on ADC conversion complete interrupt.

16. ADC temperature (toogle red) every second using Timer0 (toggle green).

#include <msp430g2553.h>

long sample;

long DegreeF=0;

  1. void main(void) {

  2.   WDTCTL = WDTPW + WDTHOLD;         // Stop watchdog timer
     

  3.   P1DIR |= BIT0;                    // Set P1.0 to output direction
      P1OUT &= ~BIT0;                   // Set the red LED on
      P1DIR |= BIT6;                    // Set P1.6 to output direction
      P1OUT &= ~BIT6;                   // Set the green LED on
     

  4.   ADC10CTL1 = INCH_10 + ADC10DIV_3; // Temp Sensor ADC10CLK/4
      ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
                                       
    // Ref voltage/sample & hold time
                                                                                                  // reference generator ON/ADC10 ON/Int Enabled

  5.   TA0CCR0 = 12000;                  // Count limit (16 bit)
      TA0CCTL0 = 0x10;                  // Enable Timer A0 interrupts, bit 4=1
      TA0CTL = TASSEL_1 + MC_1;         // Timer A0 with ACLK, count UP
     

  6.   _BIS_SR(LPM0_bits + GIE);         // LPM0 (low power mode) interrupts enabled

  7. }
     

  8. #pragma vector=TIMER0_A0_VECTOR     // Timer0 A0 interrupt service routine
      
    __interrupt void Timer0_A0 (void) {
     

  9.   P1OUT ^= BIT6;                    // Toggle green LED
     

  10.   ADC10CTL0 |= ENC + ADC10SC;       // ADC sampling and conversion start

  11. }
     

  12.  #pragma vector=ADC10_VECTOR        // ADC10 interrupt service routine

  13.   __interrupt void ADC10_ISR (void) {
     

  14.   sample = ADC10MEM;                // Read ADC sample
     

  15.   DegreeF = ((sample - 630) * 761) / 1024;
     

  16.   P1OUT ^= BIT0;

  17. }

Question 1.6

Trace the line numbers executed.

 

PWM (http://dbindner.freeshell.org/msp430/)

Pulse Width Modulation Video (not me but still worthwhile) - http://www.pdnotebook.com/2012/06/videopulse-width-modulation/

Pulse-width modulation (PWM) is a commonly used technique for controlling power to inertial[ambiguous] electrical devices, made practical by modern electronic power switches.

The average value of voltage (and current) fed to the load is controlled by turning the switch between supply and load on and off at a fast pace. The longer the switch is on compared to the off periods, the higher the power supplied to the load is.

The PWM switching frequency has to be much faster than what would affect the load, which is to say the device that uses the power. Typically switching's have to be done several times a minute in an electric stove, 120 Hz in a lamp dimmer, from few kilohertz (kHz) to tens of kHz for a motor drive and well into the tens or hundreds of kHz in audio amplifiers and computer power supplies.

Period is the time of each pulse, both the On and Off times.

Duty cycle describes the proportion of 'on' time to the regular interval or 'period' of time; a low duty cycle corresponds to low power, because the power is off for most of the time. Duty cycle is expressed in percent, 100% being fully on.

The main advantage of PWM is that power loss in the switching devices is very low. When a switch is off there is practically no current, and when it is on, there is almost no voltage drop across the switch. Power loss, being the product of voltage and current, is thus in both cases close to zero. PWM also works well with digital controls, which, because of their on/off nature, can easily set the needed duty cycle.

 

PWM signal consists of two parts:

Period

Time of each pulse.

5Hz signal has periods of 1/5 second = 0.2 second.

Duty cycle

The percentage of period the PWM signal is On or high.

A period of 0.2 second and 10%

duty cycle = 0.10 * 0.2 second = 0.02 seconds.

If the signal has a low voltage of 0 and a high voltage of 10 volts, a 50% duty cycle produces an average of 5 volts, a 10% duty cycle produces an average of 1 volt.

 

LED under PWM control

 

PWM on the LaunchPad
 

PWM will be used to control the brightness of the green LED by varying the duty cycle, a longer duty cycle results in a brighter LED.

LED (green) direction is set and selected for PWM.

    P1DIR |= BIT6;              // Green LED as output
    P1SEL |= BIT6;              // Green LED controlled by Pulse width modulation

Timer A0 PWM → green LED


TA0CCR0/TA0CCR1

Timer registers determine when events occur and the clock count limit. Combined, the register values determine the PWM period (TA0CCR0) and duty cycle (TA0CCR1).

    TA0CCR0 = 1000;             // PWM period
                                //
12KHz clock gives 12000/1000 = 12Hz = 1/12s period

    TA0CCR1 = 100;              // PWM duty cycle = TA0CCR1/TA0CCR0
                                // time cycle on vs. off, on 10% initially

Achieves a 10% duty cycle, where PWM output is 1 for 10% of the time and 0 for 90%

"TA0CCR1 output is reset (0) when the timer counts to the TA0CCR1 value and is set (1) when the timer counts to the TA0CCR0 value" (From User Guide).

Means that when TA0CCR0 count is reached PWM output is 1 and counting starts over, and when TA0CCR1 is reached, PWM output is 0.

Question 2

TA0CCR0 = 1000;

Give the TA0CCR1 setting for a 25% duty cycle.

 

TA0CCTL1

Controls PWM output, whether high or low when TA0CCR1 is below the count.

   TA0CCTL1 = OUTMOD_7;            // TA0CCR1 reset/set
                                   // high voltage below
TA0CCR1 count and low voltage when past

TA0CCR0=8 (0-8) period 9 ticks

TA0CCR1=2 (0-2) duty cycle 3/9=33%

33% duty cycle is generated

Clock TA0CCR0
Period
TA0CCR1
Duty Cycle
PWM
0 0 0 1
1 1 1 1
2 2 2 1
3 3 0 0
4 4 1 0
5 5 2 0
6 6 0 0
7 7 1 0
8 8 2 0
9 0 0 1
10 1 1 1
11 2 2 1
12 3 0 0
13 4 1 0
14 5 2 0
15 6 0 0
16 7 1 0
17 8 2 0
18 0 0 1
19 1 1 1
20 2 2 1
21 3 0 0
 

 

 

Question 2.1

  1. What is the duty cycle for:

    TA0CCR0=7 (0-7)

    TA0CCR1=1 (0-1)
     

  2. Give the table above for 16 clock ticks.
     

  3. Give the period and duty cycle diagram for 16 clock ticks.

 

TA0CTL

Timer A control sets SMCLK as clock source and count Up Mode.

TA0CCR0 = 8;                 // 33% duty cycle
TA0CCR1 = 2;
TA0CTL = TASSEL_1 + MC_1;    // Timer A control set to submain clock TASSEL_1 and count up mode MC_1

12KHz clock input to Timer A, the PWM output:

12000/9 = 1333 periods per second

1s/1333 = 0.00075s period duration.

 

Question 2.2

Give the settings for a 25% duty cycle and a 2 second period (using 12KHz clock input to Timer A).

TA0CCR0 =

TA0CCR1 =

 

 

_BIS_SR(LPM0_bits);   // Enter Low power mode 0

Placing system in LPM0 keeps the SMCLK and timer A operating to control the PWM while shutting down the CPU.

 

Timers depend on the clock frequency.

The default DCO (digital controlled oscillator) which is the source of the MCLK and in this case the ACLK at approximately 12KHz, making the PWM period about 1 second and .10 second duty cycle or 10%.

17. Green LED 10% brightness

#include <msp430g2553.h>

void main(void){

    WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer

    P1DIR |= BIT6;                        // Green LED

    P1SEL |= BIT6;                        // Green LED selected for Pulse Width Modulation

    TA0CCR0 = 12000;                      // PWM period, 12000 ACLK ticks or 1/second

    TA0CCR1 = 1200;                       // PWM duty cycle, time cycle on vs. off, on 10% initially

    TA0CCTL1 = OUTMOD_7;                  // TA0CCR1 reset/set -- high voltage below TA0CCR1 count
                                          // and low voltage when past

    TA0CTL = TASSEL_1 + MC_1;             // Timer A control set to submain clock TASSEL_1 ACLK
                                          // and count up to TA0CCR0 mode MC_1

    _BIS_SR(LPM0_bits);                   // Enter Low power mode 0
}


Question 3

Timer A source clock selected as ACLK, 12KHz.               TA0CTL = TASSEL_1 + MC_1;

  1. What happens if this statement is removed?                    _BIS_SR(LPM0_bits);
     
  2. What happens if this statement is removed?                    TA0CTL = TASSEL_1 + MC_1;
     
  3. What happens if statement in a. is replaced by:               _BIS_SR(GIE);
     
  4. No interrupt handler! How does the green LED change?
     
  5. What changes are needed for a 33% duty cycle?
     
  6. What changes are needed for a 3 second period and 33% duty cycle?
     

 

Example

Use WDT to toggle red LED at ≈32ms intervals and timer A to generate 10% duty cycle to green LED.

18. Green LED 10% brightness, flashing red LED.

#include <msp430g2553.h>

void main(void){

    WDTCTL = WDT_MDLY_32;                 // Watchdog timer ≈32ms

    IE1 |= WDTIE;                         // enable Watchdog timer interrupts

    P1DIR |= BIT6+BIT0;                   // Green and red LED

    P1SEL |= BIT6;                        // Green LED Pulse width modulation

    TA0CCR0 = 1000;                       // PWM period

    TA0CCR1 = 100;                        // PWM duty cycle, time cycle on vs. off, on 10% initially

    TA0CCTL1 = OUTMOD_7;                  // CCR1 reset/set -- high voltage below count
                                          // and low voltage when past

    TA0CTL = TASSEL_1 + MC_1;             // Timer A control set to submain clock TASSEL_1
                                          // and count up mode MC_1

    _BIS_SR(LPM0_bits + GIE);             // Enter Low power mode 0 with interrupts enabled
}

#pragma vector=WDT_VECTOR                 // Watchdog Timer interrupt service routine

  __interrupt void watchdog_timer(void) {

    P1OUT ^= BIT0;                        // Toggle red LED
}


Question 3.1

Timer A source clock selected as ACLK, 12KHz.               TA0CTL = TASSEL_1 + MC_1;

  1. What happens if this statement is removed?                    _BIS_SR(LPM0_bits + GIE);
     
  2. What happens if statement in a. is replaced by:               _BIS_SR(GIE);
     
  3. What happens if statement in a. is replaced by:               _BIS_SR(LPM0_bits);

 

Example - Pulse green LED

Use WDT to change at ≈32ms intervals, the green LED duty cycle.

Effect is the green LED cycles through becoming brighter then dimmer then brighter ...

pwmDirection - always 1 or -1 to control whether duty cycle is increasing (1) or decreasing (-1).

TA0CCR1 - Increased (or decreased) by increments of 20, increasing (or decreasing) the duty cycle and therefore the brightness of the green LED.

19. Green LED changes brightness.

#include <msp430g2553.h>

int pwmDirection = 1;

void main(void){

    WDTCTL = WDT_MDLY_32;                 // Watchdog timer ≈32ms

    IE1 |= WDTIE;                         // enable Watchdog timer interrupts

    P1DIR |= BIT6;                        // Green LED for output

    P1SEL |= BIT6;                        // Green LED Pulse width modulation

    TA0CCR0 = 1000;                       // PWM period

    TA0CCR1 = 1;                          // PWM duty cycle, time cycle on vs. off, on 1/1000 initially

    TA0CCTL1 = OUTMOD_7;                  // TA0CCR1 reset/set -- high voltage below count and
                                          // low voltage when past

    TA0CTL = TASSEL_2 + MC_1;             // Timer A control set to SMCLK clock TASSEL_2, 1MHz
                                          // and count up mode MC_1

    _BIS_SR(LPM0_bits + GIE);             // Enter Low power mode 0
}

#pragma vector=WDT_VECTOR                 // Watchdog Timer interrupt service routine

  __interrupt void watchdog_timer(void) {

    TA0CCR1 += pwmDirection*20;           // Increase/decrease duty cycle, on vs. off time

    if( TA0CCR1 > 980 || TA0CCR1 < 20 )   // Pulse brighter (increasing TA0CCR1) or dimmer
       pwmDirection = -pwmDirection;
}

Question 4

Timer A source clock selected as SMCLK, 1MHz.              TA0CTL = TASSEL_2 + MC_1;

  1. What is the duration of one PWM period?
     
  2. What is the duration of time LED is On, the duty cycle?
     

 

C and Assembler

#include <msp430g2553.h>

void main(void) {
	WDTCTL = WDTPW + WDTHOLD; 			// Stop watchdog timer
	P1DIR |= 0x41; 					// Set P1.0 and P1.6 to output direction
	P1OUT &= 0xbf; 					// Set the red LED on
	P1OUT |= 0x01; 					// Set the green LED off

	CCR0 = 12000;					// Count limit
	CCTL0 = 0x10;					// Enable counter interrupts, bit 4=1
	TACTL = TASSEL_1 + MC_1; 			// Timer A with ACLK, count UP

	_BIS_SR(LPM0_bits + GIE);       		           // LPM0 (low power mode) with interrupts enabled
} 

#pragma vector=TIMER0_A0_VECTOR
   __interrupt void Timer0_A0 (void) { // Timer0 A0 interrupt service routine
	P1OUT ^= 0x41;					// Toggle red/green LEDs
}	
 	.cdecls C,LIST,  "msp430g2553.h"
      .text                           ; Progam Start
main  mov.w   #0280h,SP               ; Initialize stackpointer
      mov.w   #WDTPW+WDTHOLD,&WDTCTL  ; Stop WDT
      bis.b   #01000001b,&P1DIR       ; P1.0 and P1.6 output
      bic.b   #00000001b,&P1OUT       ; Set green LED off
      bis.b   #01000000b,&P1OUT       ; Set red LED on
      mov.w   #10h,&CCTL0             ; CCR0 interrupt enabled, bit 4 = 1
      mov.w   #12000,&CCR0            ; Count 12000 to CCR0
      mov.w   #TASSEL_1+MC_1,&TACTL   ; ACLK source (~12KHz), UP mode (count up to CCR0 value)
						
      bis.w   #CPUOFF+GIE,SR          ; CPU off, interrupts enabled

TA0   xor.b   #01000001b,&P1OUT       ; Toggle P1.0 and P1.6
      reti                            		

;     Interrupt Vectors
      .sect   ".reset"                ; MSP430 RESET Vector
      .short  main                    ;
      .sect   ".int09"                ; Timer_A0 Vector
      .short  TA0                 
      .end