Electronics - MSP430 - Using timer and interruption to generate a delay of 1 second

The first two features to understand in a microcontroller are timers and interruptions.

Indeed, without a timer nor interruptions, it's quite impossible to have an accurate timing in a program.

Let's see that in this tutorial and let's generate a timing of 1 second with the G2553 microcontroller.

First of all

The essential documents needed for any project with a MSP430 microcontroller are:

The main goal of  a timer is to generate a counter and check if a particular number in this counter has been reached.

This is the job of the famous Capture Compare (CC) register.

This register compares a number set by the programmer (a human being generally) and trigger a signal when this value is reached.

So the CC will capture the number in the counter and compare it with the value set by the programmer.

This signal is generally caught by an Interrupt Service Routine (ISR) in order to achieve a specific task.

In our example, we will use this ISR to light a LED.

I don't know if we can do easiest than that!

A timer works only if there is something that can generate a tick.

This operation is made by an oscillator, that can be internal or external.

The main difference between an internal and an external oscillator (like a quartz) is that the internal is less accurate but easiest to handle with only software.

But we won't talk about external oscillators in this tutorial, only internal.

There are two internal oscillators in the MSP430:

  1. VLO  --> Very Low Oscillator
  2. DCO --> Digital Controller Oscillator

These oscillators are used by the clocks.

In the MSP430G2553, there are 3 clocks:

  1. MCLK --> Master clock (used by the CPU with high speed oscillators)
  2. SMCLK --> Sub Main clock (used by peripherals with high speed oscillators)
  3. ACLK --> Auxiliary clock (used by peripherals with low speed oscillators)

In our example we will use the DCO with the SMCLK for our timer peripheral.

Peripherals

Port

With the code below I set the bit 0 of the P1DIR register in order to have the LED ready to light.

I light it in the ISR by changing each time this bit from 0 to 1 and from 1 to 0.

It explains why the LED is blinking.

Then I set the bit 4 to high from the P1DIR and from the P1SEL registers in order to have the clock on this pin.

Oscillator

I set the DCO to have approximatively an oscillation of 1.5 MHz.

Then I divided it by 4 to have once again an approximation of 387 kHz.

More information in the datasheet page 29.

Timer

Finally I set the timer to have SCMCLK as clock, I use the MC_1 to have the timer repeatedly counts from 0 to the value of TACCR0 set to 24198.

More information in the user guide page 358.

With all that settings we have 1 second delay (on the video we can see 0.999 second with a logic analyzer).

Low-power mode and interruption

In order to have a system with a low-power mode, we set it with LPM0_bits and we enable the Global Interrupt Enabled (GIE).

So each time the counter reach the value 24198, it will trigger an interruption.

This interruption is the function __interrupt void badprog_timer_a0() which will change the value of the P1OUT.P0 bit from 0 to 1 and 1 to 0 to have a LED blinking.

Code

#include <msp430.h>

/**
 * Main
 */
int main(void) {
    WDTCTL = WDTPW + WDTHOLD;           // Stop WDT

    P1DIR &= 0x00;                        // P1DIR reset
    P1OUT &= 0x00;                        // P1OUT reset
    P1DIR |= (1 << 0);                    // P1DIR P1.0 -- LED

    P1DIR |= (1 << 4);                    // P1DIR P1.4 -- CLOCK
    P1SEL |= (1 << 4);                    // P1SEL P1.4 -- CLOCK

    DCOCTL |= 0xE0;                        // DC0 CTL     = 1110 0000
    BCSCTL1 |= 0x87;                    // BCS CTL1     = 1000 0111

    BCSCTL2 |= DIVS_2;                    // SMCLK divided by 2^2=4

    TACTL = TASSEL_2 + MC_1 + ID_3;        // TA0 CTL = 1011 01000
    CCTL0 = CCIE;                        // TA0 CCTL0
    CCR0 = 24198;                        // TA0 CCR0 value is 24198 (0x5E86)

    __bis_SR_register(LPM0_bits + GIE); // LowPower0 + Global Interrupt Enabled
}

/**
 * Timer A0 interrupt service routine
 */
#pragma vector=TIMER0_A0_VECTOR
__interrupt void badprog_timer_a0(void) {
    P1OUT ^= (1 << 0);
}

Conclusion

If you understood this simply but useful code you got the basis of a the MSP430G2553 microcontroller.

You are now able to use a timer that uses a clock, that itself uses an oscillator.

Good job, you've made it! laugh

Comments

Comment: 

What is the use of P1SEL?

Comment: 

Hello sunny,

P1SEL is used in order to select the function of a particular pin.

In our example, if you check the MSP430G2553 datasheet, in page 47 (table 18), you'll see the pin functions of the Pin 1.4.

And thus if you set the pins like that:

  • P1DIR = 1 
  • P1SEL = 1

And others to 0, you'll have the SMCLK set on the pin P1.4.

cool

Comment: 

BCSCTL1 |= 0x87;

Should not be 0x78 ?

Comment: 

Why?

Comment: 

is this the same code that can be used for msp430fg6426?

Comment: 

Hello phylab,

To check that you have to take a look at the datasheets of your MSP430 fg6426 microcontroller and compare them with the MSP430 G2553.

Comment: 

Hello,
How did u get the value 24198 for 1 second? Could u please explain.

Comment: 

please find out Error in the following code
#include <MSP430.h>
#include <stdint.h>
uint8_t x;
int main (void)
{
WDTCTL= WDTPW | WDTHOLD;
x=0x00;
P2DIR=0xFF;
P2OUT=~BIT0;
TACCR0=49999;
TACCTL0=CCIE;
TACTL=MC_1 | ID_0 | TASSEL_2 |TACLR;
__enable_interrupt();
for(;;){
__bis_SR_register(LPM4_bits+GIE);
}
}
#pragma vector = TIMER_A0_VECTOR
__interrupt void TA0_ISR(void)
{

P2OUT ^=BIT0;

}

Comment: 

how can I generate 20 mins delay ?

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.