You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F103C8T6定时器中断异常:__enable_irq后while(1)无法执行求助

问题排查与解决方案

核心问题分析

你的代码存在两个关键问题,导致__enable_irq()后主循环无法运行,以及计数器异常:

1. 系统时钟配置不完整

configure_clock()函数仅开启了HSE外部时钟,但未将其设置为系统时钟源,也未配置总线分频参数。这会导致系统时钟处于未初始化的异常状态,定时器以极高频率触发中断,CPU被中断完全占用,主循环while(1)无法获得执行时间。

2. 定时器中断频率过高

TIM2->PSC = 1和TIM2->ARR = 8的设置会让定时器中断频率异常高(假设时钟正常的情况下,中断频率会达到数十MHz级别),CPU持续处理中断,主循环根本无法执行。

代码修正步骤

步骤1:修复系统时钟配置

将configure_clock()修改为标准的72MHz时钟配置(适配STM32F103C8T6):

void configure_clock(void){
    // 开启HSE并等待就绪
    RCC->CR |= RCC_CR_HSEON;
    while(!(RCC->CR & RCC_CR_HSERDY));
    
    // 配置FLASH预取指和等待周期
    FLASH->ACR |= FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_2;
    
    // 配置AHB/APB分频:AHB不分频,APB1分频2,APB2不分频
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV1;
    
    // 配置PLL:HSE作为输入,倍频9倍(8MHz*9=72MHz)
    RCC->CFGR |= RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9;
    
    // 开启PLL并等待就绪
    RCC->CR |= RCC_CR_PLLON;
    while(!(RCC->CR & RCC_CR_PLLRDY));
    
    // 切换系统时钟到PLL
    RCC->CFGR |= RCC_CFGR_SW_PLL;
    while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}

步骤2:调整定时器参数,降低中断频率

修改configure_timer(),设置合理的分频和自动重装载值,让中断频率为1Hz(方便测试LED闪烁):

void configure_timer(void){
    RCC->APB1ENR |= (0x1 << TIME2EN);
    
    // TIM2时钟为72MHz(APB1分频2,定时器时钟=APB1时钟*2)
    // PSC=7199,ARR=9999 → 中断频率=72MHz/(7199+1)/(9999+1) = 1Hz
    TIM2->PSC = 7199;
    TIM2->ARR = 9999;
    
    TIM2->CR1 |= TIM_CR1_CEN; // 启动定时器
    TIM2->DIER |= TIM_DIER_UIE; // 使能更新中断
}

步骤3:优化中断服务函数(规范写法)

确保中断标志位清除的操作更清晰,同时改用32位变量减少原子性问题:

volatile uint32_t t_counter = 0; // 32位足够,避免32位机上64位变量的非原子读写问题

void TIM2_IRQHandler(void){
    if(TIM2->SR & TIM_SR_UIF){
        t_counter++;
        TIM2->SR &= ~TIM_SR_UIF; // 清除更新中断标志
    }
}

步骤4:主循环逻辑微调

由于中断频率改为1Hz,t_counter >= 40对应40秒闪烁一次,可根据需求自行调整阈值:

while(1){
    if(t_counter >= 40){
        GPIOC->ODR ^= (1 << 13);
        t_counter = 0;
    }
}

额外注意事项

  • 确保开发板上HSE时钟源(8MHz晶振)正常工作,若没有外部晶振,可改用HSI作为时钟源(修改时钟配置函数为HSI倍频到72MHz)。
  • 多中断场景下,需用NVIC_SetPriority()配置合理的中断优先级,避免抢占问题。
  • volatile关键字必须保留,防止编译器优化掉全局变量的读写操作。

内容的提问来源于stack exchange,提问作者Mohammad Seraj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:45:02