Skip to main content

MSP430 series chips have two types of Timers known as Timer_A and Timer_B. Both of them are 16 bit timers with several capture compare channels and selectable clock sources. Timer_B is slightly complex than Timer_A and offers more extensive interrupt capabilities and capture compare channels.

MSP430Gxxx series chips that ship with Launchpad development board usually have two Timer_A modules named as Timer0_A3 and Timer1_A3.Here A3 indicates the number of Capture Compare registers (here 3 registers) available in each timer.Timer A is a 16 bit Timer/Counter with 3 capture compare registers.

Block Diagram

    Block Diagram of Timer_A simplified  
The Timer can be clocked either by SMCLK, ACLK,TACLK or INCLK. If you are not familiar with SMCLK or ACLK,You can check out the Clock system of MSP430 here.

SMCLK is an internal clock generally taken from DCO (Digitally Controlled Oscillator) and is in the Megahertz range. The DCO clock is temperature dependent and may change depending upon temperature.

ACLK is an internal clock taken either from VLO or an external 32KHz clock crystal connected to the MSP430.ACLK when taken from an external clock crystal is usually stable and do not change with temperature. The ACLK frequency is usually in Kilo hertz range (32KHz).

TACLK and INCLK are external clocks that can be connected to MSP430 through external pins.

TASSELx bits are used to select the required clock to the 16 bit Timer register and IDx bits are used to select clock divider which are present in the TACTL register.

The 16 bit Timer A register(TAR) starts counting on the positive edge of the clock. TAR can be cleared by setting the TACLR bit to 1.

 

Timer A Operating Modes

Timer_A has 4 operating modes selected by the MCx bits in TACTL register.

MCx = 00 – Timer is halted and Timer stops counting.

MCx = 01 – Timer is started in the Up Mode.

MCx = 10 – Timer is started in Continuous Mode.

MCx = 11 – Timer is started in Up/Down Mode

 

Timer A Interrupts

Timer A in MSP430 have two interrupt vector locations,one for TACCR0 and the other for rest of the channels as well as the Timer overflow (TAIFG).

The register TACCR0 has a separate vector location which has a higher priority compared to the other timer interrupts.

In IAR embedded workbench, It is defined as TIMER0_A0_VECTOR for Timer0_A3 and as TIMER1_A0_VECTOR for Timer1_A3 in the header file (msp430g2553.h).

 

 

Rest of the capture compare channels (CCR1 and CCR2) along with the Timer overflow (TAIFG) are given separate vector location . Since all of them are combined together the interrupt vector register TAIV is used to determine which flag requested an interrupt.

In IAR embedded workbench,It is defined as TIMER0_A1_VECTOR for Timer0_A3 and as TIMER1_A1_VECTOR for Timer1_A3 in the header file (msp430g2553.h).

To identify which flag caused the interrupt it is recommended to use a switch structure like this inside the ISR.

switch(TAIV) 

    case 0x002: // CCR1 interrupt comes here 
                break;

    case 0x004: //CCR2 interrupt comes here 
                break;

    case 0x00A: //TAR overflow interrupt comes here 
                break; 
}

 

Continuous Mode (MCx = 10)

In Continuous Mode ,the timer repeatedly counts up to 0FFFFh and restarts from zero. When the Timer overflows TAIFG flag is set and an interrupt is generated if TAIE bit is set.

Continous Mode of MSP430 Timer A

Now lets write a small program to blink an LED connected to P1.0 of MSP430G2553 (Launchpad board) whenever TAR overflows. I am using IAR embedded workbench and launchpad development platform. Create a new C Project in IAR and compile the code given below.

#include "msp430g2553.h" 
void main(void) 

 WDTCTL = WDTPW + WDTHOLD; // Stop the WDT

 // Port Configuration 
 P1DIR |= BIT0; // P1.0 output 
 P1OUT &= ~BIT0; // P1.0 = 0

 // Timer 0 Configuration 
 TACTL |= MC_0; // Stop Timer0_A3 
 TACTL  = TASSEL_1 + ID_2 + TAIE;// ACLK,ACLK/4,enable TAR interrupt 
 TACTL |= MC_2; // Start Timer0 in Continuous Mode

 _BIS_SR(LPM0_bits + GIE); // Sleep in LPM0 with interrupts enabled 
}

#pragma vector = TIMER0_A1_VECTOR //Timer0,TAIFG interrupt vector 
__interrupt void TimerA(void) 

 switch(TAIV) 
 { 
   case 0x002: // CCR1 not used 
               break; 
   case 0x004: //CCR2 not used 
               break; 
   case 0x00A: P1OUT ^= BIT0; //TAR overflow interrupt 
               break; 
 } 
}

In the above code we are using the ACLK sourced from a 32KHz watch crystal to provide clock to the timer module.

TASSEL_1 is a constant defined in msp430g2553.h file which is used to select the Timer Clock as ACLK. You can also individually set the TASSELx bits but TASSEL_1 makes life easier for the programmer.

ID_2 is used to set the clock divider here ACLK/4 ,So 32KHz/4 = 8KHz which would give the time period at 0.125ms.

TAIE is used to enable the timer overflow interrupt(maskable).

After the above parameters are configured in the TACTL register ,we start the timer in Continuous mode by setting MCx =10. 
TACTL |= MC_2 
and put the CPU in low power mode (LPM0) with interrupts enabled.

The TAR starts to run and overflows in about 8 seconds (0.125ms *65536).The TAIFG flag is set and the code reaches the ISR for Timer0 and toggles the LED connected to P1.0.

When going into the Low Power Modes Please remember the clocks which  will be disabled in that Low Power Mode.For eg you are using SMCLK to trigger your Timer A and you decides to put the micro controller into LPM3.In LPM3 SMCLK is disabled, Timer A will not update itself and your timer and the peripherals triggered by it stays dead. Also remember to enable the GIE bit when going into LPM.

Configuring CCRx interrupts

In Continuous mode you can also set the interrupts for other channels like CCR0,CCR1 and CCR2.You have to enable the interrupt enable bits for the corresponding registers and load the values in to the capture compare registers.

In the code snippet shown below ,we are using SMCLK instead of ACLK by setting the TASSEL_2 bits .Here i am showing only the timer configuration code segment you can find the full code in the zip file.

Here we are configuring all the capture compare registers(CCR) as well as the timer overflow interrupt.We enable the TAIFG interrupt in TACTL first and then load all the CCR registers with the count value.After that CCR interrupts for the respective registers are enabled and counter is started in continuous mode.

// Timer 0 Configuration 
TACTL = MC_0;// Stop the timer 
TACTL = TASSEL_2 + ID_3 + TAIE;// Timer Clock = SMCLK,1MHz/8 = 125KHz,enable TAR interrupt

CCR0 = 10000; // Count in CCR0 register 
CCR1 = 30000; // Count in CCR1 register 
CCR2 = 40000; // Count in CCR2 register

CCTL0 |= CCIE; // Enable CCR0 interrupt 
CCTL1 |= CCIE; // Enable CCR1 interrupt 
CCTL2 |= CCIE; // Enable CCR2 interrupt

TACTL |= MC_2; // Start the timer in continuous mode

_BIS_SR(LPM0_bits + GIE); // Sleep in LPM0 with interrupts enabled

When the Timer register counts and reaches the value 10000 ,CCR0 interrupt is triggered and the program control goes to the CCR0 interrupt routine of Timer 0.You can then lit up an LED or do something.

#pragma vector = TIMER0_A0_VECTOR //CCR0 interrupt vector 
__interrupt void CCR0_Interrupt(void) 

     P1OUT ^= BIT0; //toggle an LED  
}

When TAR reaches the count = 30000 the CCR1 interrupt is triggered,CCR2 interrupt is triggered at 40000 and finally the timer overflow (TAIFG) is triggered as TAR rolls over.