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
相关产品推荐
相关产品推荐

