Part Number: MSP430FR6989
I have the code below, where I am attempting to debounce a button press, and to use the button to toggle the onboard LED.
As can be seen in the msp_init() function, I have set up the B timer to use as my debounce timer, and I am using CCR4 as the register to trigger the B1 vector ISR. When I run the program in debug mode, I've noticed that TB0R is not incrementing, although the family user guide (S. 26.2.1) suggests it should count up with each rising edge of the clock. As a result, TB0R is always 0x0000, and as a result of that, CCR4 always ends up as whatever value I plug into the debounce variable.
Since I have not set a low power mode, I believe I must be in active mode, and as such all the clocks should be running. Thus, TB0CTL |= TBSSL__ACLK should cause TB0R to increment in step with the ACLK. However, in the debugger TB0R simply does not increment at all. This is true whether I use the step-through functions (which other posts suggest sometimes do not let the timer increment), or the "run/play" button, and whether I set breakpoints within ISRs. Likewise, if I flash the program, I'll be able to turn the light on, but the debounce timer interrupt is never reached, and so I'm never able to turn the light back off with a second button press.
Why doesn't TB0R increment, and what do I need to do to get it to count up?
#include <msp430.h>
//===============FUNCTION PROTOTYPES==========================
void msp_init();
//===================== GLOBAL SCOPE =====================
//DEFINITIONS
#define ROWS (BIT1 | BIT2 | BIT3 | BIT4)
#define COLS (BIT4 | BIT5 | BIT6 | BIT7)
//USEFUL CONSTANTS AND OTHER VALUES
unsigned int debounce = 0x01ff;//debounce delay will be finalized later.
//====================== MAIN =============================
void main(void)
{
//TIMER STUFF
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
PM5CTL0 &= ~LOCKLPM5;
//Constants
unsigned char numbers[3] = {0xff,0xff,0xff};//ones, tens, hundreds
unsigned char i = 0;
unsigned char sum;
//Initialization
P2OUT &= ~0xff;
P8OUT &= ~0xff;
P9OUT &= ~BIT0;
msp_init();
__enable_interrupt();
//Port Interrupts on P2.
P2IES |= ROWS;//falling edge
//P2IES &= ~ROWS;//rising edge
P2IFG &= ~0xff;//clear interrupt flags
P2IE |= ROWS;//interrupts on 1-4
//Testing Loop:
while(1){}
}
//====================== FUNCTIONS ==============================
//MSP INITIALIZATION
void msp_init()
{
//Set up output ports for LEDs
P2DIR |= BIT6 | BIT7; // P2.6 and P2.7 set as output
P2SEL1 &= ~(BIT6 | BIT7); // connect P2.6 and P2.7
P2SEL0 |= BIT6 | BIT7; // to TB0.5 and TB0.6
P3DIR |= BIT6 | BIT7; // P3.6 and P3.7 set as output
P3SEL1 |= BIT6 | BIT7; // connect P3.6 and P3.7
P3SEL0 &= ~(BIT6 | BIT7); // to TB0.2 and TB0.3
//Initialization:
P8DIR |= COLS;//Output
P8OUT &= ~COLS;//Output 0
P2DIR &= ~ROWS;//Input
P2REN |= ROWS;//Pullup Resistor
P2OUT |= ROWS;//Output to 1 (will be pulled down later)
TB0CTL = TBSSEL__ACLK | ID__1 | MC__UP | TBCLR;//setup timer b
}
//========================== INTERRUPTS ========================
#pragma vector = TIMER0_B1_VECTOR
__interrupt void T0B1_ISR(void)
{
switch(__even_in_range(TB0IV,14))
{
case 0: break; // No interrupt
case 2: break; // CCR1 not used
case 4: break; // CCR2
case 6: break;
case 8://ccr4
TB0CCTL4 &= ~CCIE;//disable interrupts
P2IE |= ROWS;//re-enable interrupts after debounce delay
break;
case 10: break;
case 12: break;
case 14: break;
default: break;
}
}
#pragma vector = PORT2_VECTOR // associate funct. w/ interrupt vector
__interrupt void Port_2(void) // name of ISR
{
switch(__even_in_range(P2IV,P2IV_P2IFG7))
{
//I'm using P2.1-2.4 as inputs.
case P2IV_NONE: break; // Vector 0: no interrupt
case P2IV_P2IFG0: break; // Vector 2: P2.0
case P2IV_P2IFG1://BIT1, and so on below
//On the interrupt:
P2IE &= ~ROWS;//disable interrupts
P2IFG &= ~0xff;//clear interrupt flags
TB0CCR4 = TB0R + debounce;//disable button interrupts for debounce period
TB0CCTL4 = CCIE;//enable interrupts on TB0CCR4
//testing
P1DIR ^= BIT0;
P1OUT ^= BIT0;
break;
case P2IV_P2IFG2: break;
case P2IV_P2IFG3: break;
case P2IV_P2IFG4: break;
case P2IV_P2IFG5: break; // Vector 12: P2.5
case P2IV_P2IFG6: break; // Vector 14: P2.6
case P2IV_P2IFG7: break; // Vector 16: P2.7
default: break;
}
}