I'll post my code below.
The problem is that the MSP's ISR_TRAP function (a function that handles ISRs that are not otherwise handled) is triggering and trapping me in its endless loop. This happens after P2.1's ISR has successfully triggered, and before the Timer B ISR does anything.
The problems is that TB0CCR4 (Timer B's Capture and Compare Register #4) should trigger an ISR when TB0R counts up to the value contained in it. That value is TB0R+delay, where delay is currently just a global variable at the top of the code. According to the debugger in CCS, the timer is counting up to and past the value stored in CCR4, but not triggering the interrupt.
If the program worked as intended, the MSP's onboard red led would turn on when the button is pressed for P2.1, and then off when the timer reaches the value stored in CCR4.
I can't figure out what's going on here, and any help would be much appreciated. Especially if the explanation can shed some light on what the timer is doing/not doing.
#include <msp430.h>
//GLOBALS
unsigned int delay = 0x00ff;
//Main
int main(void)
{
WDTCTL = WDTPW | WDTHOLD;
P8OUT &= ~0xff;
P2OUT &= ~0xff;
P1OUT &= ~BIT0;
P2DIR &= ~BIT1;//input
P2REN |= BIT1;//pullup
P2OUT |= BIT1;//sit high
P8DIR |= BIT4;//output
P8OUT &= ~BIT4;//output low
TB0CTL = TBSSEL__ACLK | ID__1 | MC__CONTINUOUS | TBCLR;//enable TB0R and choose its options
TB0CCR4 = 0x0000;//Initialize TB0CCR4, just in case there's garbage in the register
PM5CTL0 &= ~LOCKLPM5;
__enable_interrupt();//enable interrupts
P2IES |= BIT1;//falling edge interrupt on P2.1
P2IFG &= ~0xff;//clear flags
P2IE |= BIT1;//interrupts enabled on P2.1
while(1){}//go forever
return 0;
}
//INTERRUPTS
#pragma vector = PORT2_VECTOR //interrupt vector for port 2
__interrupt void Port_2(void) //interrupt function names can be anything
{
switch(__even_in_range(P2IV,P2IV_P2IFG7))
{
case P2IV_NONE: break;
case P2IV_P2IFG0: break;
case P2IV_P2IFG1: //P2.1 vector
P2IE &= ~BIT1; //disable interrupts
P2IFG &= ~0xff;
TB0CCTL4 |= CCIE; //enable timer interrupts
TB0CCR4 = TB0R + delay; //set next event
P1DIR ^= BIT0; //enable output
P1OUT ^= BIT0; //turn on onboard led
break;
case P2IV_P2IFG2: break;
case P2IV_P2IFG3: break;
case P2IV_P2IFG4: break;
case P2IV_P2IFG5: break;
case P2IV_P2IFG6: break;
case P2IV_P2IFG7: break;
default: break;
}
}
#pragma vector = TIMER0_B0_VECTOR //interrupt vector for timer B
__interrupt void T0B7_ISR(void)
{
switch(__even_in_range(TB0IV,14))
{
case 0: break;
case 2: break;
case 4: break;
case 6: break;
case 8: // ccr4
P1OUT ^= BIT0; //toggle onboard LED
P2IE |= BIT1; //re-enable interrupts after delay
TB0CCTL4 &= ~CCIE; //disable interrupts on CCR4
break;
case 10: break;
case 12: break;
case 14: break;
default: break;
}
}
-
\$\begingroup\$ Which MSP430? If I have the same one, I will try this on mine. \$\endgroup\$Mattman944– Mattman9442020年10月19日 08:40:29 +00:00Commented Oct 19, 2020 at 8:40
1 Answer 1
The manual says:
Timer_B Interrupts
Two interrupt vectors are associated with the 16-bit Timer_B module:
- TBxCCR0 interrupt vector for TBxCCR0 CCIFG
- TBIV interrupt vector for all other CCIFG flags and TBIFG
TIMER0_B0_VECTOR
is for TB0CCR0; TIMER0_B1_VECTOR
is for the other CCRs and TBIFG and is handled with TB0IV. Your CCR4 must be handled with the latter.
(And there are symbols for the vector values, something like TB0IV_TBCCR4
or TBIV__TBCCR4
.)
-
\$\begingroup\$ That's absolutely right. Changing the vector fixed the problem. For some reason I thought the B0 vector was a superset of the B1 vector, but reviewing the user guide, I see that it isn't. Thanks! \$\endgroup\$Formeanlegion– Formeanlegion2020年10月19日 13:15:40 +00:00Commented Oct 19, 2020 at 13:15