In this post I am going to describe, as simply as possible, how to configure a Texas Instruments MSP430G2452 mcu to create precise time periods using the Timer A interrupt. The MSP430G2452 is one of the mcu’s provided with the low cost EXP430G2 LaunchPad.
The EXP430G2 LaunchPad
Even though I have been using the LaunchPad for only a couple of months, I have found it to be an excellent way to learn about microcontrollers along with the variety of low cost development boards and free software tools (i.e. Code Composer Studio) that TI has made available. Also, the LaunchPad has a built-in flash programmer – no other external hardware is required. Although I have not yet tried, you should be able to use the LaunchPad as an external programmer to program an mcu installed on a breadboard using only four wires – two of them would be Vcc and Ground plus TEST and RST (jumpers are installed at these locations). The LaunchPad also comes with two onboard LEDs and pushbuttions.
The EXP430G2 LaunchPad is breadboard friendly and has a number of “BackPacks” that can be added to enhance its capability. Also, while it seems that the number of microcontrollers that are in DIP packages decreases every year, TI still offers a fair number of microcontrollers in DIP packages. I consider this very important as it allows you to easily replace the mcu (the mcu on the Launchpad is in a socket) should it become damaged as mistakes can happen to anybody – especially someone just starting out.
Code Composer Studio
I am using Code Composer Studio (CCS, Version 6.2) to write my programs in C and then use it to program the flash memory on the mcu. The 16k code limited version of Code Composer Studio is a free download from TI and is a very versitile IDE. It comes with a “Resource Explorer” which allows you to easily find and download code examples and other necessary documentation, including viewing online videos that helps you to get started. TI also provides periodic free automatic updates to CCS.
Of course, you still need to have a basic understanding of electronics, the C programming language or assembly if you so desire, digital logic, and the hexadecimal system. Also, there is a bit of an initial learning curve to get through, especially for beginners – also true for any new IDE. That said, Texas Instruments has made a tremendous amount of resources and community support available for all of its development boards and devices.
Using the Timer Interrupt
Before working with timer A, review the section on interrupt vector addresses located in the data sheet and the timer A section in the user guide.
1.) Data sheet for the M430G2452 (TI document #SLAS722G).
2.) User guide for the M430G2452 (TI document #SLAU144).
3.) In Code Composer Studio open the header file (msp430g2452.h) for the M430G2452.
M430G2452 Timer A Description
The M430G2452 contains a single 16 bit timer designated as Timer0_A3 with the three indicating the number of combination capture /compare registers available. Here we will be using a single compare register. This timer has four operating modes and also contains two timer interrupt vectors.
M430G2452 Timer A Interrupt Description
Two interrupt vectors are associated with the 16-bit Timer0_A3 module. Compare register TACCR0 is an interrupt vector for TACCR0 CCIFG and TAIV is an interrupt vector for the remaining two CCIFG flags and TAIFG. In compare mode, any CCIFG flag is set if TAR counts up to the associated TACCRx register value. The TAIFG flag is set when the timer (TAR) completes counting down to zero. Software is able to set or clear any CCIFG flag.
All CCIFG flags request an interrupt when their corresponding CCIE bit and the GIE bit are set. The TACCR1 CCIFG, TACCR2 CCIFG, and TAIFG flags are prioritized and combined to source a single interrupt vector. A program read of the interrupt vector register TAIV is used to determine which flag requested an interrupt. In the code example below, I used an “if” statement to assign interrupt #10 to the output. A “switch/case” statement can also be used.
In addition to controlling the timer delay using the value in the TA0CCR0 compare register, the IDx value in the TA0CTL register can also be changed to create other timer delays. Check the header file for more information.
Note; When using any interrupt, the code should be kept as short as possible. Calling a function inside an interrupt and the nesting of interrupts should be avoided if possible. Use an interrupt to check bit status or to update variables is best. Don’t forget to enable all maskable interrupts by setting the GIE bit in the status register.
How to determine the correct vector address
1.) In the data sheet, determine the timer interrupt address for the interrupt source that you want to use.
2.) In Code Composer Studio, locate the timer interrupt address in the header file. Then use the interrupt vector name shown in the header file in the interrupt function definition in your program. See table below.
M430G2452 Interrupt Vector Table
|Interrupt Source||Interrupt Flag||Interrupt Address||Header File Definition|
Timer Interrupt Code Example
//2 JANUARY 2017
//USE MSP430G2452 LAUNCHPAD
//CREATE TIMER DELAY USING BOTH TIMER INTERRUPTS
//TIMER VALUES; 250 = 1mS
//TIMER VALUES; 2500 = 10mS
//TIMER VALUES; 12500 = 50mS
//TIMER VALUES; 25000 = 100mS
//TIMER VALUES; 37500 = 150mS
//TIMER VALUES; 50000 = 200mS
//TIMER VALUES; 62500 = 250mS
//ASSIGN TIMER VALUES
const unsigned char Time_1mS = 250;
const unsigned int Time_10mS = 2500;
const unsigned int Time_50mS = 12500;
const unsigned int Time_100mS = 25000;
const unsigned int Time_200mS = 50000;
const unsigned int Time_250mS = 62500;
//configure mcu, port 1 and 2 all outputs, 1mHz clock
WDTCTL = WDTPW + WDTHOLD;
P1DIR |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7;
P2DIR |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7;
//assign i/o function to port2
P2SEL &= ~BIT6;
P2SEL &= ~BIT7;
P2SEL2 &= ~BIT6;
P2SEL2 &= ~BIT7;
DCOCTL = 0;
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
BCSCTL2 |= SELM0 + DIVM_0 + DIVS_0;
BCSCTL2 &= ~SELS;
//configure timer A control register
//use smclk, clock divide/2, up/down mode
TA0CTL |= TASSEL_2 + ID_1 + MC_3;
//enable timer interrupt
TA0CTL |= TAIE;
//clear timer interrupt flag
TA0CTL &= ~TAIFG;
//value for timer compare
TA0CCR0 = Time_10mS;
//no capture, output mode 0, enable compare interrupt
TA0CCTL0 |= CM_0 + OUTMOD0 + CCIE;
//configure timer A capture - compare mode
TA0CCTL0 &= ~CAP;
//clear timer flag
TA0CCTL0 &= ~CCIFG;
//enter low power mode - enable global interrupts
__bis_SR_register(LPM0_bits + GIE);
//timer A compare register interrupt (CCIFG)
#pragma vector = TIMER0_A0_VECTOR
interrupt void timer_A0_irq (void)
//toggle led1 (red) output
P1OUT ^= BIT0;
//timer A interrupt (TAIFG)
#pragma vector = TIMER0_A1_VECTOR
interrupt void timer_A1_irq (void)
//read interrupt vector register to determine interrupt source
//0Ah (10) = timer overflow
//toggle led2 (green) output
if(TA0IV == 10) P1OUT ^= BIT6;