MSP430FR2355定时器LED延时异常:中断提前触发求助
MSP430FR2355定时器延时异常:无论设置多久都约2秒触发中断
问题根源
初始化阶段误启动定时器
你在initialize函数里提前执行了TB0CTL |= MC__UP;启动定时器,但此时TB0CCR0还未赋值,默认是16位最大值0xFFFF。ACLK为32.768kHz,定时器计数到0xFFFF的时间刚好是65535 / 32768 ≈ 2秒,这就是为什么不管你设置多少延时,第一次中断总会在2秒左右触发。浮点数计算导致精度丢失
TB0CCR0 = (timerMS * 32.768);用浮点数乘法计算计数值,整数转换时会损失精度,尤其是大延时值误差更明显。定时器设置流程不规范
setTimer里没先停定时器就修改TB0CCR0,容易造成计数混乱;重复设置MC__UP也是冗余操作。
修正后代码
#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; // 配置定时器:仅设置时钟源和分频,暂不启动 TB0CTL |= TBCLR; // 清除定时器寄存器 TB0CTL |= TBSSEL__ACLK; // 选择ACLK(32.768kHz) TB0CTL |= ID__8; // 8分频,将ACLK降至4096Hz,支持最长约16秒延时 TB0CCTL0 |= CCIE; // 使能捕获比较中断 __enable_interrupt(); // 开启全局中断 } void turnOnYellowLED() { P1OUT |= YELLOW_LED_PIN; } void turnOffYellowLED() { P1OUT &= ~YELLOW_LED_PIN; } void setTimer(int timerMS) { // 先停止定时器,避免设置CCR0时计数混乱 TB0CTL &= ~MC_3; // 用整数运算计算计数值,避免浮点数精度问题 // 4096Hz = 32768Hz / 8,计数值 = 延时毫秒数 * 4096 / 1000 TB0CCR0 = (timerMS * 4096) / 1000; // 启动定时器 TB0CTL |= MC__UP; // 重置标志位 timerExpired = false; } int main(void) { WDTCTL = WDTPW | WDTHOLD; // 停止看门狗定时器 initialize(); turnOnYellowLED(); setTimer(10000); // 设置10秒延时 while (1) { if (timerExpired) { turnOffYellowLED(); TB0CTL &= ~MC_3; // 可选:停止定时器,防止重复触发 } } return 0; } #pragma vector = TIMER0_B0_VECTOR __interrupt void ISR_TB0_CCR0(void) { // 停止定时器 TB0CTL &= ~MC_3; // 手动清除中断标志(硬件会自动清除,手动清除更稳妥) TB0CCTL0 &= ~CCIFG; timerExpired = true; }
关键说明
- 要实现超过2秒的延时(比如你的10秒需求),必须对ACLK分频:设置
ID__8后,ACLK被8分频为4096Hz,16位定时器最大延时可达65535 / 4096 ≈ 16秒,完全满足需求。 - 改用整数运算计算计数值,彻底避免浮点数带来的精度误差。
- 初始化时不要提前启动定时器,必须等设置好
TB0CCR0后再启动,杜绝默认最大值触发的意外中断。
内容的提问来源于stack exchange,提问作者Jordan De Sotle
相关产品推荐
相关产品推荐

