PIC32MK1024MCM064定时器2中断服务程序(ISR)卡死求助
PIC32MK定时器ISR卡住无法返回主循环的问题解决
问题根源分析
你的代码首次触发Timer2中断后卡在ISR中,主要由以下几个错误导致:
32位定时器未清除高16位计数器
启用32位定时器模式(T2CONbits.T32=1)时,Timer2和Timer3组成32位计数器,TMR2是低16位,TMR3是高16位。你仅清除了TMR2,TMR3保留了中断触发时的高值,重新开启定时器后,TMR3:TMR2会快速达到PR3:PR2(PR3默认0),立即再次触发中断,导致ISR反复执行无法返回主循环。PB2DIV寄存器配置错误
PB2DIVbits.PBDIVRDY是只读状态位,手动赋值会导致配置失效;- 你想要128分频,但
PB2DIVbits.PBDIV=0b0000000实际是1分频,导致定时器时钟远快于预期。
中断标志清除时机不当
你在ISR末尾清除中断标志,若处理过程中意外触发中断(即使概率低),会导致重复进入ISR。ISR中不必要的定时器启停
自触发定时器无需在ISR中关闭再开启,此操作不仅冗余,还可能引入时序问题。ISR中调用阻塞式延迟
中断服务程序应尽量简洁,长时间阻塞会破坏系统实时性,甚至引发其他异常。
修正后的代码
定时器配置函数修正
void Timer2_setup(void){ PB2DIVbits.ON = 0b0; // 关闭PB2CLK以修改分频 PB2DIVbits.PBDIV = 0b00001000; // 设置PB2CLK为SYSCLK/128 PB2DIVbits.ON = 0b1; // 重新开启PB2CLK //---------------------------------------------------- T2CONbits.ON = 0b0; // 关闭Timer2 T2CONbits.TCS = 0b0; // 使用内部外设时钟 T2CONbits.T32 = 0b1; // 启用32位定时器模式(Timer2+Timer3) T2CONbits.TCKPS = 0b101; // 1:256预分频 T2CONbits.SIDL = 0b1; // 空闲模式下停止定时器 TMR2 = 0x0; // 清除低16位计数器 TMR3 = 0x0; // 清除高16位计数器 PR2 = 124999U; // 低16位周期值(8MHz SYSCLK下约1秒) PR3 = 0x0; // 高16位周期值 //---------------------------------------------------- // 中断配置 IFS0bits.T2IF = 0b0; // 预先清除中断标志 IEC0bits.T2IE = 0b1; // 启用Timer2中断 IPC2bits.T2IP = 0b001; // 设置中断优先级为1 }
中断服务程序修正(简洁版,推荐)
// 全局标志位,用于在主循环中处理中断任务 volatile bool timer_triggered = false; void __ISR( _TIMER_2_VECTOR, IPL1SRS) Timer2_Handler (void){ IFS0bits.T2IF = 0b0; // 立即清除中断标志,避免重复触发 timer_triggered = true; // 设置中断触发标志 TMR2 = 0x0; // 清除低16位计数器 TMR3 = 0x0; // 清除高16位计数器 }
主循环修正
int main ( void ) { TRISAbits.TRISA7 = 0; LATAbits.LATA7 = 0; TRISBbits.TRISB14 = 0; LATBbits.LATB14 = 0; TRISBbits.TRISB15 = 0; LATBbits.LATB15 = 0; Timer2_setup(); __builtin_enable_interrupts(); // 全局启用中断 T2CONbits.ON = 0b1; // 启动Timer2 while (1) { LATBbits.LATB14 = 1; delay_ms(300); LATBbits.LATB14 = 0; LATBbits.LATB15 = 1; delay_ms(300); LATBbits.LATB15 = 0; // 在主循环中处理中断触发的任务 if(timer_triggered){ timer_triggered = false; LATAbits.LATA7 = 1; delay_ms(300); LATAbits.LATA7 = 0; } } return (EXIT_FAILURE); }
关键注意事项
- 32位定时器模式下,必须同时操作
TMR2和TMR3、PR2和PR3; - 中断标志应在ISR开头清除,避免重复触发;
- ISR应保持极简,仅处理必要的硬件操作(如清标志、清计数器),耗时任务放在主循环中通过标志位触发;
- 外设时钟分频寄存器的只读位不要手动赋值,严格按照数据手册的配置流程操作。
内容的提问来源于stack exchange,提问作者Vilius Žalėnas
相关产品推荐
相关产品推荐

