Phone

    00852-6915 1330
  • Contents

Today,let's talk something about MSP430 interrupts and times.

 

About "Interrupt"

 

Do you know what is an "interrupt"?

  • Interrupt is a signal that informs our MCU that a certain event has happened,causing the interruption of the normal flow of the main program and the execution of an "interrupt routine",that handles the event and takes a specified action.

  • Interrupts are essential to avoid wasting the processor's valuable time in polling loops, waiting for external events (in fact they are used in Real-Time Operating Systems, RTOS).

 

In the MSP430 architecture, there are several types of interrupts: timer interrupts, port interrupts, ADC interrupts and so on. Each one of them needs to be enabled and configured to work, and there is a separate "service routine" for every interrupt.

 

About code 

Now let's see how to use timer and port interrupts to flash some LEDs,we will keep the ADC interrupt for the next turorial. So,let's write some code!

 

#include "msp430g2231.h" void main(void){
 WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT  

You should recognize those lines,we used them in the last tutorial to add the definition file for our MCU, declare the main function and stop the watchdog timer.

  CCTL0 = CCIE;                             // CCR0 interrupt enabled
 TACTL = TASSEL_2 + MC_1 + ID_3;           // SMCLK/8, upmode  
 CCR0 =  10000;                           // 12.5 Hz  

Here's some interesting stuff. These lines configure the timer interrupt. We first enable it by setting the CCIE bit in the CCTL0 register.

Then we set the clock for the timer module in the TimerA control register.

If you have a look at the msp430g2231.h file, you can see that:

  • TASSEL_2 selects the SMCLK (supplied by an internal DCO which runs at about 1 MHz);

  • MC_1 selects the "UP mode", the timer counts up to the number stored in the CCR0 register;

  • ID_3 selects an internal 8x divider for the supplied clock (in our case we have SMCLK/8).

 

Finally, we set the CCR0 register. We configured the TimerA module to count up to the number stored in this register before overflowing and triggering the interrupt.

By setting it at 10000, we get an overflow-frequency of 12,5 Hz. In fact we have (SMCLK/8)/10000 = 12,5 .

You may obtain several frequencies by changing this number (remember that the MSP430 has a 16-bit timer, so the value stored in the CCR0 register must not be higher than 65535), changing the dividers or adding an if-else block with a counter in the interrupt routine. Let's go ahead.

 

  P1OUT &= 0x00;               // Shut down everything
 P1DIR &= 0x00;              
 P1DIR |= BIT0 + BIT6;       // P1.0 and P1.6 pins output the rest are input
 P1REN |= BIT3;                 // Enable internal pull-up/down resistors
 P1OUT |= BIT3;                 //Select pull-up mode for P1.3

 

 

These lines should be familiar too, but there are some additions: firstly, we clear the PORT1 output and direction registers. Then we set the P1.0 and P1.6 pins as outputs and the rest as inputs. The last two lines enable the pull-up resistor on the switch (BIT3) so that the normal state (button not pressed) will be "1".

  P1IE |= BIT3;                    // P1.3 interrupt enabled
 P1IES |= BIT3;                  // P1.3 Hi/lo edge
 P1IFG &= ~BIT3;               // P1.3 IFG cleared

With these lines of code, we first tell the MCU to listen to the P1.3 pin for logic-state changes (effectively enabling the interrupt on that particular pin).

Then we select the edge when the interrupt is raised (from High to Low or Low to High); remember that the button on the LaunchPad connects the input pin to GND when pushed and to VCC when not. For this reason we seletct Hi/Lo edge.

Finally we clear the interrupt flag for that pin. The interrput flag register P1IFG reports when an interrupt is raised, and it should be cleared at the end of the interrupt service routine.

  _BIS_SR(CPUOFF + GIE);        // Enter LPM0 w/ interrupt   
 while(1)                      //Loop forever, we do  everything with interrupts!
 {}
}

With this line, as you can remember, we shut down the CPU to spare some power while keeping the interrupts enabled. Then we enter a loop to be sure the MCU does nothing else, as we do our job with interrupts.

// Timer A0 interrupt service routine#pragma vector=TIMERA0_VECTOR__interrupt void Timer_A (void){
 P1OUT ^= BIT0;                            // Toggle P1.0}

This is the TimerA interrupt service routine. Every time the TimerA overflows, the code inserted in this routine (note the special declaration) is executed. As you can see we only toggle the P1.0 pin (red led on LaunchPad), then we return to normal execution.

// Port 1 interrupt service routine#pragma vector=PORT1_VECTOR__interrupt void Port_1(void){    
  P1OUT ^= BIT6;                        // Toggle P1.6  
  P1IFG &=~BIT3;                        // P1.3 IFG cleared    }

This is the Port1 interrupt service routine. Every time the we push the P1.3 button, the code inserted in this routine (note the special declaration) is executed. We toggle the P1.6 pin (greenled on LaunchPad), clear the P1.3 interrupt flag (very important) and then we return to normal execution.

Compile and program the LaunchPad, you should see the red led blink, and the green led toggle when you press the P1.3 button.

Here's the full code, enjoy!

#include "msp430g2231.h"  
 void main(void){
 WDTCTL = WDTPW + WDTHOLD;     // Stop WDT  
 CCTL0 = CCIE;                             // CCR0 interrupt enabled
 TACTL = TASSEL_2 + MC_1 + ID_3;           // SMCLK/8, upmode
 CCR0 =  10000;                     // 12.5 Hz  
 P1OUT &= 0x00;               // Shut down everything
 P1DIR &= 0x00;              
 P1DIR |= BIT0 + BIT6;            // P1.0 and P1.6 pins output the rest are input
 P1REN |= BIT3;                   // Enable internal pull-up/down resistors
 P1OUT |= BIT3;                   //Select pull-up mode for P1.3
 P1IE |= BIT3;                       // P1.3 interrupt enabled
 P1IES |= BIT3;                     // P1.3 Hi/lo edge
 P1IFG &= ~BIT3;                  // P1.3 IFG cleared
 _BIS_SR(CPUOFF + GIE);          // Enter LPM0 w/ interrupt
 while(1)                          //Loop forever, we work with interrupts!
 {}
}
 
// Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) {  
  P1OUT ^= BIT0;                          // Toggle P1.0 }
// Port 1 interrupt service routine#pragma vector=PORT1_VECTOR__interrupt void Port_1(void){    
  P1OUT ^= BIT6;                      // Toggle P1.6
  P1IFG &= ~BIT3;                     // P1.3 IFG cleared }

 

Kynix

Kynix was founded in 2008, specializing in the electronic components distribution business. We adhere to honesty and ethics as our business philosophy and have gradually established an excellent reputation and credibility in our international business. With the accurate quotation, excellent credit, reasonable price, reliable quality, fast delivery, and authentic service, we have won the praise of the majority of customers.

Join our mailing list!

Be the first to know about new products, special offers, and more.

Leave a Reply

We'd love to hear from you! Feel free to share your thoughts and comments below. Rest assured, your email address will remain private.

Name *
Email *
Captcha *
Rating:

Kynix

  • How to purchase

  • Order
  • Search & Inquiry
  • Shipping & Tracking
  • Payment Methods
  • Contact Us

  • Tel: 00852-6915 1330
  • Email: info@kynix.com
  • Follow Us

authentication

Kynix

© 2008-2026 kynix.com all rights reserved.