STM32保姆级入门教程|第6章:定时器中断原理 + 精准LED闪烁(1s_2s_3s)实战(功能超详细+CubeIDE手把手)

原创 ✍️

文章标签:#stm32 #stm32cubeide #定时器中断 #TIM2 #led精准闪烁 #嵌入式入门 #单片机实战 #中断回调函数

系列前置博客(必看!否则跟不上哦😜):

  1. STM32保姆级入门教程|第1章:零基础必看,从认知到实战全解析
  2. STM32保姆级入门教程|第2章:STM32CubeIDE 使用+STM32F103RCT6 + J-Link 实现 PA0 引脚 LED 点亮
  3. STM32保姆级入门教程|第3章:从新建工程到LED闪烁点灯(Hex生成+ST-Link/J-Link切换全攻略)
  4. STM32保姆级入门教程|第4章:GPIO输入+外部中断 实现按键控制LED(手把手全流程)
  5. STM32保姆级入门教程|第5章:GPIO内部结构 + 8种模式 + 功能详解

📚 本章目录(点击可跳转,懒人福音✨)

  1. 前言(为什么要学定时器中断?)
  2. 本章核心功能目标(学完能搞定啥?)
  3. 定时器是什么?核心功能讲透(通俗不烧脑)
  4. 定时器中断完整工作原理(一步一步拆明白)
  5. 实战目标:LED精准亮灭(1s2s/3s)
  6. CubeIDE手把手配置(一步一截图,零踩坑)
  7. 代码功能详解(逐行拆解,新手也能懂)
  8. 下载验证(见证奇迹的时刻🤩)
  9. 2秒3秒亮灭修改(教你灵活变通)
  10. 关键功能总结(新手必背,避免踩坑)
  11. 常见问题排查(遇到问题不用慌)
  12. 下篇预告 + 资料包

💡 前言

大家好,我是BackCatK Chen😎!

前面我们用 HAL_Delay() 实现了LED闪烁,但我敢说,90%的新手都踩过这个坑------HAL_Delay会"霸占"CPU,单片机啥也干不了,只能傻傻等时间到,而且精度还一般,项目里根本用不了!

今天咱们就学STM32的"核心技能"------定时器中断,它就像单片机的"专属闹钟",后台默默计时,时间到了自动提醒CPU干活,不阻塞、精度高、稳定性拉满,是工业项目、电子产品的"标配"!

本章我把定时器功能、中断原理、分频计算、回调函数、实战配置全部讲到最细,全程用"大白话+表情包+一步一截图",新手看完不仅能学会,还能彻底吃透,再也不用死记硬背!


🎯 本章核心功能目标(清晰明确,学完不迷茫)

  1. 搞懂 ✅ STM32定时器的本质和核心功能(再也不被"PSC、ARR"搞懵)
  2. 掌握 ✅ 定时时间计算公式(精准到秒,再也不会算错)
  3. 学会 ✅ CubeIDE配置TIM2定时器(全截图,一步都不落下)
  4. 掌握 ✅ 定时器中断启动方法(一行代码搞定)
  5. 学会 ✅ 中断回调函数编写(逐行解释,知道每句代码干啥)
  6. 实现 ✅ :
    • LED 1秒亮 → 1秒灭(精准无漂移)
    • LED 2秒亮 → 2秒灭(灵活修改参数)
    • LED 3秒亮 → 3秒灭(举一反三)
  7. 理解 ✅ 为什么定时器比HAL_Delay更强大、更专业(项目开发必懂)

⏰ 定时器是什么?核心功能讲透(最通俗,不烧脑)

2.1 定时器本质(一句话讲懂)

定时器 = 单片机内部一个"独立运行的精准电子秒表" 🔧

它最牛的地方在于:不需要CPU盯着,自己在后台默默计数,时间到了就主动"拍一下"CPU,让CPU去处理定时任务,CPU平时该干嘛干嘛,互不干扰!

2.2 定时器4大核心功能(新手重点记前2个)

  1. 🕒 精准计时:从微秒级到秒级,精度极高,不会漂移(比HAL_Delay强10倍)
  2. 🔔 自动触发中断:时间一到,自动通知CPU,不用CPU一直查询
  3. 🚀 不阻塞程序:CPU可以同时运行其他代码(比如一边计时,一边检测按键)
  4. 📌 拓展功能:PWM输出、输入捕获、编码器计数(后续章节慢慢学,先搞定基础)

本章我们只聚焦前两个核心功能:精准计时 + 中断触发 → 控制LED亮灭,把基础打牢!

2.3 定时器 vs HAL_Delay(功能大比拼,一眼看清差距)

实现方式 功能特点 是否阻塞CPU 精度 项目使用建议
HAL_Delay() 干等,CPU卡住不动 是 ❌(坑!) 一般(有误差) 调试临时用,项目不推荐
定时器中断 后台计时,自动提醒 否 ✅(推荐!) 极高(无漂移) 必须用,工业级标准

💡 结论:只要是项目开发,必用定时器中断!HAL_Delay只能用来临时调试,别当真~


🔍 定时器中断完整工作原理(功能流程拆明白,新手也能懂)

3.1 先搞懂:中断是什么?(通俗比喻)

中断就像你家里的闹钟 ⏰:

  1. 你在看书(CPU运行主程序)
  2. 闹钟响了(定时器中断触发)
  3. 你立刻停下看书,去关闹钟(CPU暂停主程序,执行中断回调函数)
  4. 关完闹钟,继续看书(CPU回到主程序,正常运行)

简单说:中断 = 优先级最高的"紧急任务",时间到了必须优先处理!

3.2 定时器中断工作全流程(逐步骤功能解释,必看!)

结合STM32F103芯片,我们一步步拆解,每一步都讲清功能:

  1. 📡 系统时钟供给 :STM32F103默认系统时钟是 72MHz(高频时钟,太快了,定时器用不了)
  2. ⚙️ 预分频器(PSC):把72MHz的高频时钟"减速",变成我们需要的低频时钟(比如10kHz)
  3. 🔢 计数器(CNT):从0开始,每来一个时钟脉冲,就自动加1(相当于秒表"滴答"一下)
  4. 📏 自动重装载值(ARR):设定一个"目标值",计数器数到这个值就"溢出"(相当于秒表到点了)
  5. 🔔 中断触发:计数器溢出后,立刻向CPU发送"中断信号",提醒CPU处理任务
  6. 📝 执行回调函数:CPU收到信号,暂停主程序,执行我们写的"翻转LED"代码
  7. 🔄 自动重启:计数器自动清0,重新开始计数,循环往复,实现LED持续闪烁

3.3 最核心公式(精准定时,必须背!背会直接封神🤩)

定时时间的计算,就靠这一个公式,再也不用瞎猜参数:

定时时间(秒)= (PSC + 1) × (ARR + 1) / 定时器时钟

⚠️ 重点提醒:

  • STM32F103 定时器时钟 = 72MHz = 72000000Hz(固定值,不用改)
  • PSC和ARR都是"从0开始计数",所以要加1(新手最容易漏加,导致时间算错!)

举个例子:想实现1秒定时,代入公式就能算出PSC和ARR,后面实战会详细算,不用担心~


🎯 实战目标:LED精准亮灭(1s/2s/3s)

沿用前面章节的硬件配置,不新增任何硬件,只改软件配置,实现3种精准闪烁效果:

✅ 效果1:LED 1秒亮 → 1秒灭(循环,精准无漂移)

✅ 效果2:LED 2秒亮 → 2秒灭(循环,修改参数即可)

✅ 效果3:LED 3秒亮 → 3秒灭(循环,举一反三)

硬件基础:PA0引脚 → LED(推挽输出),和第5章完全一致,不用重新接线!


🛠️ CubeIDE手把手配置(一步一截图,零踩坑,新手直接照搬)

全程用我们第5章的工程,不用新建,直接继承GPIO配置,节省时间~

步骤1:打开第5章工程(继承PA0 LED配置)

打开之前保存的工程,工程中已包含:

  • PA0:LED 推挽输出(不用改)
  • PA5:按键上拉输入(本章用不到,不管它)

💡 小提醒:如果忘记保存工程,重新打开第5章的工程即可,不用重新配置GPIO~

步骤2:开启TIM2内部时钟(定时器"供电")

操作步骤:

  1. 点击左侧 Timers 文件夹,展开后选择 TIM2(STM32F103的TIM2是16位定时器,够用了)
    2. 在右侧 Clock Source 下拉菜单中,选择 Internal Clock(内部时钟)

📌 功能解释:让TIM2使用单片机内部的72MHz时钟运行,这是定时器工作的基础,必须选对!

步骤3:配置PSC和ARR(实现1秒精准定时,核心步骤)

切换到 Parameter Settings 界面,配置以下3个参数(直接照搬,不用自己算,后面会讲计算过程):

  • Prescaler (PSC):7199(预分频器,减速用)
  • Counter Period (ARR):9999(自动重装载值,定时目标值)
  • Auto-reload Preload:Enable(自动重装载,循环计时)

💡 功能详解:

  • PSC(预分频器):把72MHz时钟分成7200份,每份就是10kHz(72MHz ÷ 7200 = 10kHz)
  • ARR(自动重装载值):计数器从0数到9999,刚好是10000个脉冲
  • Auto-reload Preload:开启后,计数器溢出后会自动清0,重新开始计数,实现循环定时

📌 计算过程(1秒定时,手把手算,新手也能会)(或者考虑我之前的博客有更详细的说明:STM32定时 计算公式):
定时时间 = (7199+1) × (9999+1) / 72000000
= 7200 × 10000 / 72000000
= 72000000 / 72000000 = 1 秒

完美!刚好是1秒,精准无误差~

步骤4:开启NVIC中断(打开"闹钟开关")

操作步骤:

  1. 切换到 NVIC Settings 界面
  2. 找到 TIM2 global interrupt,勾选 Enable(开启TIM2中断总开关)
  3. 优先级(Priority)默认即可(新手不用改,后续再讲中断优先级)

📌 功能解释:这一步相当于"打开闹钟的声音",如果不开启,定时器就算时间到了,也不会通知CPU,中断就没用了!

步骤5:生成代码(CubeIDE自动写底层,懒人福利)

点击右上角保存图标(💾),弹出提示点击Yes,等待代码生成完成后进入代码编辑界面。

💡 小提醒:生成代码后,会自动打开工程,不用手动打开,直接开始编写代码即可~


💻 代码功能详解 + 实战编写(逐行拆解,新手也能懂)

生成代码后,我们只需要添加2部分代码:

  1. 启动定时器中断(让"闹钟"开始工作)
  2. 编写中断回调函数("闹钟响了"要做的事------翻转LED)

6.1 启动定时器中断(必须写,一行代码搞定)

操作步骤:

  1. 打开 main.c 文件(左侧Project窗口,展开Src文件夹,找到main.c)
  2. while(1) 循环的上方,添加以下代码:
c 复制代码
// 启动TIM2定时器中断(核心代码,一行都不能少)
HAL_TIM_Base_Start_IT(&htim2);

📌 逐行功能解释:

  • HAL_TIM_Base_Start:启动定时器的基础功能(相当于"打开秒表")
  • _IT:表示"开启中断模式"(相当于"打开闹钟声音")
  • &htim2:指定我们要启动的是TIM2定时器(不能写成TIM1、TIM3,否则报错)

6.2 编写中断回调函数(核心中的核心!)

中断回调函数的作用:定时器时间到了,自动执行这个函数里的代码(我们要做的就是"翻转LED")。

操作步骤:

  1. 打开工程CoreSrcmain.c文件,在/* USER CODE BEGIN Includes */下方添加宏定义(封装引脚和电平):
c 复制代码
/* USER CODE BEGIN Includes */
// 封装LED引脚和电平逻辑,后期修改仅需改此处
#define LED1_PORT GPIOA
#define LED1_PIN  GPIO_PIN_0
#define LED1_ON   GPIO_PIN_RESET  // 低电平点亮
#define LED1_OFF  GPIO_PIN_SET    // 高电平熄灭
/* USER CODE END Includes */
  1. main.c 文件的最下方(main 函数结束之后),添加以下代码:
c 复制代码
// 定时器中断回调函数(重中之重!)
// 功能:当定时器溢出(时间到)时,自动调用此函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    // 判断:是不是TIM2定时器触发的中断(防止其他定时器干扰)
    if(htim->Instance == TIM2)
    {
        // 核心功能:翻转PA0引脚电平(LED亮 ↔ 灭)
        HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
    }
}

📌 逐行功能拆解(新手必看,搞懂每一句):

  1. HAL_TIM_PeriodElapsedCallback:STM32 HAL库的"定时器溢出回调函数",名字固定,不能改,改了就不会自动执行!
  2. TIM_HandleTypeDef *htim:参数,用来判断是哪个定时器触发的中断(比如TIM2、TIM3)
  3. if(htim->Instance == TIM2):判断当前中断是不是TIM2触发的,避免其他定时器(比如TIM3)干扰,新手一定要加,否则可能出问题!
  4. HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin):翻转LED电平------原来亮,就变灭;原来灭,就变亮(LED_GPIO_Port和LED_Pin是第5章定义的,不用改)

💡 小技巧:回调函数不用手动调用,定时器时间到了,会自动触发执行,是不是很方便?


✨ 下载验证(见证奇迹的时刻!)

代码编写完成后,就可以下载到单片机,看看LED是不是精准1秒闪烁~

操作步骤:

  1. 连接J-LinkST-Link到单片机和电脑
  2. 点击CubeIDE右上角的"下载"按钮(图标是一个向下的箭头)
  3. 下载完成后,单片机自动运行程序

精准LED闪烁

✅ 预期现象:LED 精准1秒亮 → 1秒灭,循环往复,无漂移、不卡顿,此时CPU还能同时处理其他任务(比如检测按键),比HAL_Delay强太多!

🎉 恭喜!你已经学会了定时器中断的核心用法,离项目开发又近了一步~


🔄 修改为2秒/3秒亮灭(教你灵活变通,举一反三)

学会了1秒闪烁,2秒、3秒就很简单了,只需要修改PSC和ARR的值,代入公式重新计算即可,不用改代码!

8.1 实现2秒亮灭(精准无误差)

参数配置(直接照搬):

  • PSC = 7199(不变,还是把72MHz分成7200份)
  • ARR = 19999

计算过程:
时间 = (7199+1) × (19999+1) / 72000000
= 7200 × 20000 / 72000000 = 2 秒

8.2 实现3秒亮灭(精准无误差)

参数配置(直接照搬):

  • PSC = 7199(不变)
  • ARR = 29999

计算过程:
时间 = (7199+1) × (29999+1) / 72000000
= 7200 × 30000 / 72000000 = 3 秒

💡 小技巧:PSC可以不变,只改ARR的值,就能调整定时时间,ARR越大,定时时间越长,新手可以自己试试调整ARR,看看LED闪烁速度的变化~


📝 关键功能总结(新手必背,避免踩坑!)

  1. ⚙️ PSC 预分频器:功能是"减速",把72MHz高频时钟变成低频时钟,数值越大,时钟越慢;
  2. 📏 ARR 自动重装载值:功能是"设定定时目标",数值越大,定时时间越长;
  3. 🔔 中断:功能是"时间到提醒CPU",必须开启NVIC中断,否则无效;
  4. 📌 回调函数:功能是"存放定时任务"(比如翻转LED),名字固定,不能改;
  5. 📊 核心公式:定时时间 = (PSC+1)×(ARR+1)/72000000(记牢,不会算错);
  6. 🚀 启动函数:HAL_TIM_Base_Start_IT(&htim2)(一行都不能少,否则定时器不工作)。

❌ 常见问题排查(遇到问题不用慌,对照排查!)

新手最容易踩的4个坑,全部整理好了,遇到问题直接对照:

  1. 🚫 LED不闪烁 → 原因:忘记添加 HAL_TIM_Base_Start_IT(&htim2),定时器没启动;
  2. ⏱️ 时间不准 → 原因:PSCARR计算错误(漏加1),或未开启Auto-reload Preload;
  3. 🔇 中断不触发 → 原因:NVIC中断未开启(步骤4没做),或回调函数名字写错;
  4. 💡 灯不亮 → 原因:PA0引脚未配置为推挽输出(回到第5章检查GPIO配置)。

📢 下篇预告(精彩不容错过!)

STM32保姆级入门教程|第7章:串口通信(USART)收发数据 + printf重定向打印调试

手把手教你:配置串口、实现printf打印、串口收发数据、上位机通信,学会串口调试,再也不用瞎猜程序有没有运行!

原创不易,若本文对你有帮助,欢迎点赞👍、收藏⭐、关注➕,有任何问题可在评论区留言,我会一一回复!

本文所使用的工程文件已上传至配套资源中,如有需要可自行下载。也可关注博主后留言获取。

🎁欢迎关注公众号,获取更多技术干货!

博主准备到这份资料包涵盖了从硬件电路设计STM32单片机开发 ,再到Linux系统学习的全链路内容,适合不同阶段的学习者:

  • 硬件基础:包含硬件电路合集、硬件设计开发工具包,帮你打牢底层基础。
  • STM32专项:从环境搭建、开发工具、传感器模块到项目实战,还有书籍和芯片手册,一站式搞定STM32学习。
  • C语言进阶:C语言学习资料包,助你掌握嵌入式开发的核心语言。
  • 面试求职:嵌入式面试题合集,提前备战技术面试。
  • Linux拓展 :Linux相关学习资料包,拓宽技术视野。
📂资料包目录
  • 00-STM32单片机环境搭建
  • 01-硬件电路合集
  • 02-硬件设计开发工具包
  • 03-C语言学习资料包
  • 04-STM32单片机开发工具包
  • 05-STM32传感器模块合集
  • 06-STM32项目合集
  • 07-STM32单片机书籍&芯片手册
  • 08-Linux相关学习资料包
相关推荐
橙露2 小时前
STM32 定时器与 PWM 输出:电机调速、LED 呼吸灯实战
stm32·单片机·嵌入式硬件
youcans_3 小时前
【FOC-MBD】(19)反 Park 坐标变换链路
stm32·单片机·嵌入式硬件·simulink·代码生成
Full Stack Developme3 小时前
Java Simple Serial Connector 教程
java·stm32·单片机
youcans_3 小时前
【FOC-MBD】(20)矢量空间脉宽调制 (SVPWM)输出
stm32·单片机·嵌入式硬件·matlab·代码生成
-Springer-5 小时前
STM32 学习 —— 个人学习笔记10-2(I2C 通信外设 & 硬件 I2C 读写 MPU6050)
笔记·stm32·学习
Zevalin爱灰灰6 小时前
基于STM32实现OTA&BootLoader 第五章——OTA功能开发【下】
stm32·单片机·物联网·mqtt·嵌入式·esp8266
LCG元7 小时前
STM32实战:基于STM32F103的MQTT协议通信(EMQ X Broker)
stm32·单片机·嵌入式硬件
深念Y7 小时前
从CH341A编程器、SPI Flash到Linux+STM32理解
linux·stm32·flash·bios·固件·编程器·闪存
小柯博客7 小时前
从零开始打造 OpenSTLinux 6.6 Yocto 系统 - STM32MP2(基于STM32CubeMX)(八)
c语言·git·stm32·单片机·嵌入式硬件·嵌入式·yocto