In the first tutorial, we have explained how to blink a LED at a fixed interval. But the biggest problem of this first program was that the processor was working full time to do almost nothing (i.e. waiting). In this tutorial, we explain how to take advantage of timers to do the same function.

 About timers

Most of processors have timers. What is a timer? It's simply a counter with some extra features. Among other features, counters can be set to count until some predefined value and issue an interrupt when finished. We are going to explain this first functionality.

MSP430 timers

MSP430 has 4 timers. TA0, TA1, TA2 and TB. Concerning this first functionality, they are all equivalent. They can be setup to call a specific function in case a specific event occurs. For instance in case of our counter, we can setup a count limit, run the counter and catch an event when the counter reaches this limit. The event can be caught in a specific function commonly called interrupt service routine or ISR.

What we need to do:

  • Set the timer to some value with interrupt capability
  • Write an interrupt function which will be called evetytime the timer finishes.

As MSP430's default clock is about 1MHz, we can setup the timer upper limit to 50000 in order to change the LED status every 50 ms. It will blink at 10Hz, which should be visible.

The program looks as follows

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

#include <msp430F5659.h>

int main(void) {
    WDTCTL = WDTPW + WDTHOLD;               // Stop WDT
    P2DIR |= 0x03;                          // P2.0 output + P2.1 output (oscillo)
    TA0CCTL0 = CCIE;                        // CCR0 interrupt enabled
    TA0CCR0 = 50000;
    TA0CTL = TASSEL_2 + MC_1 + TACLR;       // SMCLK, upmode, clear TAR
    __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0, enable interrupts
}

// Timer0 A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void) {
    P2OUT |= 0x02;
    P2OUT ^= 0x01;                          // Toggle P1.0
    P2OUT &= ~0x02;
}

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

As we can see, after a few settings, the processor is put to sleep. The processor does almost nothing but sleeps, and wakes up once in a while to invert the status of the LED and then goes back to sleep. This is the power of interrupts: when there is no need for processing, do nothing. You can notice that port2 bit 1 has also been use. The purpose was to measure how much time the processor is working. By hooking an oscilloscope on PORT2.1, we get the following result:

Hima

As you can see, I had to boost luminosity to get the peaks appear because they are extremely short when compared to the signal period and they were almost invisible.

The interval between pulses of P2.1 is about 48 ms.

By zooming on the pulse, I could mesure its width which is around 7µs. The CPU is therefore working 7µs every 48 ms, which means that its load is in the 0.1 ~ 0.2% range.

 

 

 

 

 Now the other advantages of our new blinker program:

  • With this new technique, we have eliminated the need of a clock-consuming delay function
  • The load of the processor is extremely low
  • The timing does not depend on the processing. If we add some tasks in the interrupt routine, the period will stay exactly at the same value.

What to do next?

This program shows a method which is economical in CPU power. But we can notice that the timing is not very accurate. The default clock is around 1 MHZ, but in case of exactly 1 MHz, using a timer of 50000 should yield a period very close to 50 ms.

In the next tutorial, we are going to explain how to get an accurate timing using the processor's real time clock crystal.

Download the C code

A summary of the first tutorials has been added as a downloadable zip file here.