MSP430 - Timer Interrupts

Published by MrChips in the blog MrChips's blog. Views: 11385


Interrupts can be tricky to program and they function somewhat magically.

However, it is a very important feature of embedded microcontroller systems and should be used to its full advantage.

Here is a simple example of the interrupt mechanism followed by some explanations.

Code (Text):
  1. // Timer example using interrupts
  2. // 2013.04.26 - MrChips
  3.  
  4. #include "io430.h"
  5.  
  6. #define ON 1
  7. #define OFF 0
  8.  
  9. #define LED1 P1OUT_bit.P0
  10. #define LED2 P1OUT_bit.P6
  11.  
  12. void init(void)
  13. {
  14.  
  15.   // Stop watchdog timer to prevent time out reset
  16.   WDTCTL = WDTPW + WDTHOLD;
  17.  
  18.   P1OUT = 0x00;
  19.   P1DIR = 0xFF;
  20.  
  21.   // initialize Timer0_A
  22.   TA0CCR0 = 62500;  // set up terminal count
  23.   TA0CTL = TASSEL_2 + ID_3 + MC_1; // configure and start timer
  24.  
  25.   // enable interrupts
  26.   TA0CCTL0_bit.CCIE = 1;   // enable timer interrupts
  27.   __enable_interrupt();    // set GIE in SR
  28. }
  29.  
  30. #pragma vector = TIMER0_A0_VECTOR
  31. __interrupt void myTimerISR(void)
  32. {
  33.   LED1 = ~LED1;
  34. }
  35.  
  36. void main( void )
  37. {
  38.   init();
  39.  
  40.   while (1)
  41.   {
  42.     // any code goes here
  43.   }
  44.  
  45. }
  46.  
You will notice only three or four changes from our previous program.

Programming for interrupts is like following a cake recipe. There are a number of essential steps in order to make it work. Make a single mistake in any one step and your cake will turn out to be a flop.

Thank goodness that I am better at programming than I am at baking cakes!

There are four essential steps in setting up interrupts and getting it to work properly.

  1. The interrupt service routine (ISR) to handle the interrupt must be written.
  2. The microcontroller must have the address of the ISR located in the interrupt vector table.
  3. The device must be enabled to generate interrupts.
  4. The microprocessor must have its interrupt hardware enabled to handle interrupts.

Step 1

I have created a timer ISR called myTimerISR( ). The name can be anything you choose and is of importance only to you. The compiler will accept any name you choose as long as it follows the naming conventions and is not already being used.

Note that definition of this ISR is preceeded with the word __interrupt which starts with double underscore.

What the heck is this #pragma thing anyway?

#pragma is a catch-all preprocessor directive that is used to extend the functionality of the compiler that is not already covered by predefined directives.

In this example, the compiler (and the linker) is being told that we are going to create an ISR for TIMER0_A0_VECTOR.

Look at the contents of the header file "io430g2553.h" and you will find at the end of the file the #define statements for all the interrupt vectors for this chip.

Our ISR is called when the timer register (TA0R) counts up to the terminal count (TA0CCR0).

What we do in the ISR is entirely up to us. In this simple example, we will simply toggle LED1 as in the previous example. That is, I have moved the task that was previously performed in the main loop to the ISR. This leaves nothing for us to do in the main loop.

In general, this frees up the main program loop for some other task to be performed.

When the device interrupt flag is set, an interrupt is generated provided that the remaining Steps 2 to 4 are in place. When the interrupt is acknowledged, the device interrupt flag must be cleared otherwise the same device will keep on interrupting. On the MSP430 mcu, the interrupt flag is automatically cleared when the interrupt is acknowledged.


Step 2

The address of our ISR, i.e. myTimerISR( ), must be burned into location 0xFFF2 of the mcu flash memory. This is done automatically for us by our #pragma statement and the __interrupt statement.


Step 3

The device will only generate an interrupt if its interrupt enable flag is set. We do this with the instruction

TA0CCTL0_bit.CCIE = 1;


Step 4

The mcu will not respond to any interrupts unless the general interrupt enable (GIE) bit is set in the status register (SR).

This is done using

__enable_interrupt( );

Again, note that this statement starts with double underscore.


There you have it, your first simple timer interrupt example.


Coming up next

Using the low frequency 32768Hz crystal oscillator.

It's time to find that crystal and get out the soldering iron.
Andrey Shevtsov and Omer Dagan like this.
You need to be logged in to comment