I am trying to write a function for another program that implements one of the timers for the MSP430FR2355 board. I would like to be able to:
- Turn on my LED
- Start a timer that runs in the background
- Turn off the LED once the timer is up
Below is my code that should outline what I need. Again, this is for another project but I need to be able to work with timers before I can use them with my other code.
The code below initializes the LED and the timer and has three other helper functions:
- A function to turn on my LED
- A function to turn off my LED
- And a function to start the timer. (takes a parameter of the delay in milliseconds)
I would just like the code to run once, turn the LED on, wait 10 seconds, and then turn the LED off. The problem is that no matter what I put for the delay, the interrupt statement is always hit in about 2 seconds and I dont know why.
Any help would be appreciated.
#include <msp430.h>
#include <stdbool.h>
#define YELLOW_LED_PIN BIT4
volatile bool timerExpired = false;
void initialize() {
P1DIR |= YELLOW_LED_PIN;
P1OUT &= ~YELLOW_LED_PIN;
// Configure Timer
TB0CTL |= TBCLR;
TB0CTL |= TBSSEL__ACLK;
TB0CTL |= MC__UP;
TB0CCTL0 |= CCIE; // Enable Timer_A interrupt
__enable_interrupt(); // Enable global interrupts
}
void turnOnYellowLED() {
P1OUT |= YELLOW_LED_PIN;
}
void turnOffYellowLED() {
P1OUT &= ~YELLOW_LED_PIN;
}
void setTimer(int timerMS) {
// Convert milliseconds to timer counts (ACLK = 32.768 kHz)
TB0CCR0 = (timerMS * 32.768);
// Start the timer
TB0CTL |= MC__UP;
// Reset the flag
timerExpired = false;
}
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
initialize();
turnOnYellowLED();
// Example: Set a timer for 5000 ms (5 seconds)
setTimer(10000);
while (1) {
// Your main loop logic here
// Check if the timer has expired
if (timerExpired) {
// Timer expired, do something
turnOffYellowLED();
// Additional actions...
}
}
return 0;
}
#pragma vector = TIMER0_B0_VECTOR
__interrupt void ISR_TB0_CCR0(void) {
// Timer_A0 interrupt service routine
TB0CTL &= ~MC__UP; // Stop the timer
TB0CCTL0 &= ~CCIFG; // Clear interrupt flag
timerExpired = true; // Set the flag indicating that the timer has expired
}
float, which will then be truncated to the lower integer. The problem is that if the value is bigger than 65535 (0xFFFFu), it leads to undefined behaviour. See section 6.3.1.4 of the C standard:If you are lucky, the implementer of the compiler saturates this value to the maximum value representable, in this case 0xFFFF. This would explain why you get a two seconds interrupt (65535 counts at 32.768kHz is 2 seconds).
If you want delays longer than 2 seconds you have to use a prescaler for the timer clock. This would be the
IDbits of theTB0CTL. For example if you set these bits to0b11, you can have delays up to 16 seconds. See in the reference manual on page 409 for more details. If you need longer delays, you will have to set the source clock for your timer toSMCLK, configureSMCLKto be sourced from theREFOand divide this further using theDIVMbits (see page 101 of the reference manual).You are setting a flag manually to indicate that the interrupt was serviced and polling it in the main loop. This is unnecessary because you could just poll the
TBIFGflag from theTB0CTLregister. This way you would not even need to implement the ISR.