STM32F4定时器中断实战:双定时器(TIM2/TIM3)协同控制LED闪烁

张开发
2026/4/18 0:35:30 15 分钟阅读

分享文章

STM32F4定时器中断实战:双定时器(TIM2/TIM3)协同控制LED闪烁
1. 为什么需要双定时器协同控制LED很多刚接触STM32的朋友可能会有疑问控制LED闪烁用延时函数不就行了吗为什么还要大费周章使用定时器中断这里我先分享一个实际项目中的教训。去年我做了一个智能花盆项目需要同时控制补光灯、水泵和风扇如果只用延时函数整个系统就会卡死在循环里无法响应其他操作。这就是定时器中断的价值所在——它能让多个任务并行运行。STM32F4系列芯片拥有多达14个定时器其中TIM2和TIM3是最常用的通用定时器。它们就像两个独立的秒表可以按照各自设定的节奏工作。比如我们可以让TIM2每100ms触发一次中断控制LED1TIM3每500ms触发中断控制LED2两个LED就能互不干扰地按照不同频率闪烁。2. 硬件准备与工程搭建2.1 最小系统搭建我建议使用STM32F407 Discovery开发板来实践它自带两个用户LEDPF9和PF10正好对应我们要控制的GPIO引脚。如果使用其他板子记得根据原理图修改LED对应的引脚定义。硬件连接很简单LED1正极接PF9负极通过220Ω电阻接地LED2正极接PF10负极通过220Ω电阻接地2.2 开发环境配置使用Keil MDK或者STM32CubeIDE都可以我个人更推荐后者因为它的图形化配置工具能帮我们省去很多底层配置工作。新建工程时记得选择正确的芯片型号STM32F407xx然后开启TIM2和TIM3的外设时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE);3. 定时器参数计算与配置3.1 时钟树分析STM32F4的定时器时钟源有点复杂我刚开始也经常搞混。简单来说TIM2和TIM3挂在APB1总线上默认时钟频率是84MHz。但要注意如果APB预分频系数不为1定时器时钟会自动倍频。比如APB1分频系数是4时实际定时器时钟会是84MHz*2168MHz。3.2 关键参数设置定时器的核心是两个参数预分频器(PSC)和自动重装载值(ARR)。计算公式是 中断周期 (ARR1)*(PSC1)/定时器时钟频率假设我们要实现TIM2100ms中断周期TIM3500ms中断周期以168MHz时钟为例// TIM2配置100ms TIM_TimeBaseStructure.TIM_Prescaler 8400-1; // 分频后频率168MHz/840020kHz TIM_TimeBaseStructure.TIM_Period 2000-1; // 2000个计数100ms // TIM3配置500ms TIM_TimeBaseStructure.TIM_Prescaler 8400-1; // 同上 TIM_TimeBaseStructure.TIM_Period 10000-1; // 10000个计数500ms4. 中断优先级与冲突处理4.1 NVIC配置技巧当多个定时器同时工作时中断优先级就显得尤为重要。STM32使用抢占优先级和子优先级两级机制我建议这样设置// TIM2配置较高优先级 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0; // TIM3配置较低优先级 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0;4.2 中断服务函数优化新手常犯的错误是忘记清除中断标志位导致程序卡死在中断中。正确的写法应该是void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update)) { GPIO_ToggleBits(GPIOF, GPIO_Pin_9); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } }5. 调试技巧与常见问题5.1 使用逻辑分析仪验证光看LED闪烁可能不够直观我习惯用Saleae逻辑分析仪抓取GPIO波形。正常情况应该能看到PF9引脚每100ms翻转一次PF10引脚每500ms翻转一次如果发现周期不对可以检查时钟配置是否正确PSC和ARR值计算是否有误是否在中断中执行了耗时操作5.2 典型问题排查最近有个学员遇到TIM3不工作的问题最后发现是APB1时钟没开启。这里分享几个常见坑点忘记调用RCC_APB1PeriphClockCmd()中断优先级设置冲突没有调用TIM_Cmd()启用定时器在中断服务函数中执行复杂计算导致错过后续中断6. 功能扩展与实践建议6.1 呼吸灯效果实现掌握了基础闪烁后可以尝试用PWM模式实现呼吸灯效果。只需要修改TIM输出模式TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 50; // 初始占空比 TIM_OC2Init(TIM3, TIM_OCInitStructure);6.2 多定时器协同方案在实际项目中我经常用TIM2做系统心跳比如1ms中断TIM3做功能定时。这时要注意心跳定时器优先级设为最高中断服务函数尽量精简可以使用标志位在main循环中处理耗时任务记得第一次调试多定时器系统时我因为优先级设置不当导致系统不稳定后来养成了先用简单测试案例验证每个定时器单独工作正常的好习惯。

更多文章