【嵌入式开发学习】第6天:STM32 定时器(精确延时 + PWM 输出)

核心目标:掌握 STM32 定时器的核心用法 —— 用定时器中断实现 “非阻塞精确延时”(替代HAL_Delay)、用 PWM 输出控制 LED 亮度 / 电机转速,理解定时器在嵌入式中的核心价值(精准计时、外设驱动)。

一、定时器原理:嵌入式的 “精准时钟”(30 分钟)

STM32 的定时器是片上外设,本质是 “可编程计数器”,通过计数时钟脉冲实现精准计时,比HAL_Delay(阻塞式)更灵活、精准,核心用途:

  1. 精确延时(非阻塞,不占用 CPU);
  2. 生成 PWM 波(控制 LED 亮度、电机转速、舵机角度);
  3. 频率测量、脉冲计数(如检测传感器脉冲)。
1. 定时器分类(STM32F103 为例,新手先掌握这 2 种)
  • 通用定时器(TIM2-TIM5):最常用,支持定时中断、PWM 输出,16 位计数器(计数范围 0-65535);
  • 高级定时器(TIM1、TIM8):功能更多(如死区控制),适合电机控制,新手先聚焦通用定时器。
2. 定时中断核心逻辑(记牢!)
  1. 配置定时器时钟(STM32F103 默认 APB1 时钟为 72MHz);
  2. 设置预分频器(PSC):将时钟分频,降低计数频率(如 72MHz÷7200=10kHz,即每 100us 计数一次);
  3. 设置自动重载值(ARR):计数器计数到 ARR 后,自动清零并触发中断(如 ARR=100,即 100×100us=10ms 触发一次中断);
  4. 使能中断并编写中断服务函数(ISR):中断触发时执行自定义逻辑(如翻转 LED)。
3. PWM 核心概念
  • PWM(脉冲宽度调制):通过周期性高低电平的占空比(高电平时间 / 周期)控制输出量;
  • 占空比:高电平占一个周期的百分比(0%= 全低,50%= 高低各半,100%= 全高);
  • 嵌入式场景:占空比 50%→LED 半亮,占空比 100%→LED 全亮,占空比 0%→LED 熄灭。

二、实操 1:定时器中断实现非阻塞 1sLED 闪烁(50 分钟)

目标:用 TIM3 定时器中断实现 1s 翻转一次 LED,替代HAL_Delay(非阻塞,CPU 可同时做其他事)。

步骤 1:CubeIDE 配置定时器
  1. 新建工程 “Timer_Interrupt”,选择 STM32F103C8T6;
  2. 配置 GPIO:PC13 设为 GPIO_Output(LED);
  3. 配置定时器(左侧 “Timers→TIM3”):
    • Mode:选择 “Internal Clock”(内部时钟驱动);
    • 预分频器(Prescaler):填 7199(72MHz÷(7199+1)=10kHz,计数周期 100us);
    • 自动重载值(Counter Period):填 9999(100us×(9999+1)=1000000us=1s,即 1s 触发一次中断);
    • 使能中断:点击 “NVIC Settings”,勾选 “TIM3 global interrupt”,优先级默认;
  4. 生成初始化代码(Project→Generate Code)。
步骤 2:编写中断逻辑
  1. 打开main.c,定义全局变量(记录中断次数):

    c

    /* USER CODE BEGIN 2 */
    uint32_t timer_count = 0;  // 定时器中断计数
    /* USER CODE END 2 */
    
  2. main函数中启动定时器:

    c

    /* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start_IT(&htim3);  // 启动TIM3定时器中断
    /* USER CODE END 2 */
    
  3. 重写定时器中断回调函数(在main.c的 “USER CODE BEGIN 4” 区域):

    c

    /* 定时器中断回调函数:TIM3触发中断时执行 */
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
      if (htim->Instance == TIM3)  // 确认是TIM3触发的中断
      {
        timer_count++;  // 每次中断计数+1
        if (timer_count >= 1)  // 计数1次(即1s)
        {
          HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);  // 翻转LED
          timer_count = 0;  // 重置计数
        }
      }
    }
    
  4. 主循环中添加其他逻辑(验证非阻塞):

    c

    while (1)
    {
      /* 主循环可同时执行其他任务,不受延时影响 */
      printf("主循环运行中...\n");  // 模拟其他任务(需配置串口,后续可补充)
      HAL_Delay(200);  // 这里的延时不影响LED的1s闪烁
      /* USER CODE END WHILE */
    }
    
步骤 3:下载测试

程序下载后,LED 每 1s 闪烁一次,同时主循环持续打印信息 —— 证明定时器中断是 “非阻塞” 的,CPU 可并行处理多个任务。

三、实操 2:定时器 PWM 输出控制 LED 亮度(50 分钟)

目标:用 TIM4 定时器生成 PWM 波,通过调节占空比,实现 LED 从暗到亮、从亮到暗的渐变。

步骤 1:CubeIDE 配置 PWM
  1. 新建工程 “Timer_PWM”,选择 STM32F103C8T6;
  2. 配置 GPIO:选择一个支持 PWM 的引脚(如 PB6,对应 TIM4_CH1),设置为 “PWM Generation CH1”;
  3. 配置定时器(左侧 “Timers→TIM4”):
    • Mode:Internal Clock;
    • 预分频器(Prescaler):填 7199(72MHz÷7200=10kHz,计数周期 100us);
    • 自动重载值(Counter Period):填 99(100us×100=10ms,PWM 周期 10ms,频率 100Hz,适合 LED);
    • PWM 模式:点击 “Configuration→PWM Generation CH1”,Mode 选 “PWM Generation CH1”,Pulse(初始占空比)填 0(初始 LED 熄灭);
  4. 生成初始化代码。
步骤 2:编写 PWM 占空比调节逻辑
  1. main.c中定义占空比变量:

    c

    /* USER CODE BEGIN 2 */
    uint16_t duty_cycle = 0;  // 占空比(0-99,对应0%-100%)
    int8_t step = 1;          // 占空比调节步长(1=递增,-1=递减)
    /* USER CODE END 2 */
    
  2. 启动 PWM 输出(main函数中):

    c

    /* USER CODE BEGIN 2 */
    HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);  // 启动TIM4通道1的PWM输出
    /* USER CODE END 2 */
    
  3. 主循环中调节占空比:

    c

    while (1)
    {
      /* 调节占空比:0→99递增(LED变亮),99→0递减(LED变暗) */
      duty_cycle += step;
      if (duty_cycle >= 99) step = -1;  // 达到最大占空比,开始递减
      if (duty_cycle <= 0) step = 1;    // 达到最小占空比,开始递增
      
      /* 设置PWM占空比:__HAL_TIM_SET_COMPARE(定时器句柄, 通道, 占空比) */
      __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, duty_cycle);
      
      HAL_Delay(50);  // 控制渐变速度(50ms调节一次,肉眼可见渐变)
      /* USER CODE END WHILE */
    }
    
步骤 3:下载测试

将 LED 正极接 PB6 引脚,负极接 GND(或直接使用板载 LED 对应的 PWM 引脚),下载后能看到 LED 从暗逐渐变亮,再从亮逐渐变暗,实现平滑渐变。

四、第六天必掌握的 3 个关键知识点(10 分钟自测)

  1. 定时器中断核心参数:预分频器(PSC)和自动重载值(ARR),定时时间 =(PSC+1)×(ARR+1)÷ 时钟频率;
  2. 非阻塞延时的优势:CPU 可同时执行其他任务,比HAL_Delay更高效;
  3. PWM 占空比调节:通过__HAL_TIM_SET_COMPARE函数修改,范围是 0 到 ARR 值(对应 0%-100%)。

总结

今天掌握了嵌入式 “精准计时” 和 “模拟量控制” 的核心工具!定时器中断解决了HAL_Delay的阻塞问题,PWM 是控制 LED 亮度、电机转速的基础(后续舵机、直流电机控制都依赖 PWM)。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值