This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Setting up Multiple Interrupts from Single Timer on MSP430F5529

Other Parts Discussed in Thread: MSP430F5529

Hello everyone,

I am having some issues setting up multiple interrupts based off of the same timer source.  I thought this would be relatively simple to implement, by simply altering the values written to two separate capture/compare registers and then having an interrupt service routine driven by each capture/compare register.  However, when I attempt to implement this, I find that the two interrupts are not called at the same rate, even when I write the same value to both capture/compare registers.  Here is a scaled-down version of the code I am implementing, and I'm not quite sure what I'm missing to have these ISR's called at the same rate (I know one will have higher priority than the other, but they aren't even close as far as how fast they get called; for example, the value of "a" will equal 2 and the value of "b" will be something ridiculous like 35479).

#include "msp430f5529.h"

/*
* main.c
*/
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR = BIT0;
P4DIR = BIT7;

//Interrupt timer setup:
TBCCTL0 = CCIE; // TBCCR0 interrupt enabled
TBCCR0 = 1000; //Capture/Compare register value
TBCCTL1 = CCIE; // TBCCR1 interrupt enabled
TBCCR1 = 1000; // Capture/Compare register 1 value
TBCTL = TBSSEL_1 + MC_2 + TBCLR; // ACLK, upmode, clear TBR


__bis_SR_register(GIE); //enable maskable interrupts

while(1){

}
return(0);
}

// Timer B0 interrupt service routine
#pragma vector=TIMERB0_VECTOR
__interrupt void TIMERB0_ISR (void){
static unsigned int a = 0;
P1OUT ^= BIT0;
a++;
}

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

// %%%%%%%%%%%%%%%%%%%%%% ATTEMPT TO IMPLEMENT MULTIPLE INTERRUPTS %%%%%%%%%%%%%%%%%%%%%%
#pragma vector=TIMERB1_VECTOR
__interrupt void TIMERB1_ISR (void){
static unsigned int b = 0;
P4OUT ^= BIT7; //toggles LED2
b++;
}

// %%%%%%%%% END SECOND INTERRUPT SERVICE ROUTINE %%%%%%%%%%%%%%%%%%%%%%%%%%%

Any suggestions you may have or gratuitous errors you may see would be very appreciated to know about.  

As always, thanks in advance for your help!

-Thomas

  • TIMERB1_ISR doesn't clear its interrupt, so it just keeps interrupting. TIMERB0_ISR gets in every so often since it is higher priority. Try inserting "(void)TB0IV;" up at the beginning of TIMERB1_ISR.

  • Bruce McKenney47378 said:
    Try inserting "(void)TB0IV;" up at the beginning of TIMERB1_ISR.

    While this will clear the highest-pending interrupt request flag, it is not guaranteed that it will be the 'right one'. In this specific case, only one interrupt will occur, but with respect of future extensions of this code, I'd suggest doing it 'right' form the beginning:

    switch(__even_in_range(TB0IV, 14) {
    case 2: // TBCCR1 interrupt
      //do the job here
      break;
    default: ;
    }

  • I guess I would argue that reading TB0IV by definition clears the "right one", i.e. the one that will keep the ISR spinning.

    But yes, I offered that fix as a band-aid, to get the OP moving forward again. The obvious follow-on exercise -- looking through the user manual to figure out "What in the world does that line of code do?" -- was left to the reader.

  • Bruce McKenney47378 said:
    I guess I would argue that reading TB0IV by definition clears the "right one", i.e. the one that will keep the ISR spinning.

    It will definitely clear the one that keeps it spinning, but probably not the one that shall be handled. If there is only one enabled, then of course both are identical, but if not... (I've too often seen TxIE been set for no reason, causing havoc)

    Bruce McKenney47378 said:
    But yes, I offered that fix as a band-aid, to get the OP moving forward again.

    Well, just get him moving again doesn't mean he's moving into the right direction or won't hit the next wall ahead soon. That's why I added the more complex version that not only restarts the engine but also puts him back on track. :)

**Attention** This is a public forum