你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32C5教程】(6)定时器 PWM 输出实验

[复制链接]
HuangXF 发布时间:2026-10-21 13:23

1. 项目简介

1.1 实验目标

本实验在 NUCLEO-C542RC 开发板上,使用 STM32C542RCT6 的 TIM2 通道 1(TIM2_CH1)输出 PWM 信号驱动板载 LED(PA5),PWM 频率约为 1 kHz;占空比在 10% ~ 90% 之间周期性往复变化,周期约为 2 s,实现呼吸灯效果。

功能需求:

  • 使用 TIM2 通道 1 输出 1 kHz PWM 信号,驱动板载 LED(PA5)
  • 占空比在 10% ~ 90% 之间周期性往复变化
  • 一个完整呼吸周期(10% → 90% → 10%)约为 2 s
  • LED 亮度平滑渐亮、渐暗

开发板和 MCU 型号: NUCLEO-C542RC 开发板,搭载 STM32C542RCT6 MCU。

1.2 实验条件

硬件:

  • NUCLEO-C542RC 开发板
  • 支持数据传输的 USB Type-C 线(用于连接 ST-LINK 接口)

软件:

  • STM32CubeMX2(用于引脚、时钟配置与代码生成)
  • VS Code + STM32Cube 插件(用于编译、烧录、调试)

<br>

2. 硬件说明

2.1 NUCLEO-C542RC 开发板

NUCLEO-C542RC 是 ST 基于 STM32C542RCT6 推出的 Nucleo-64 开发板。主要特性:

  • MCU:STM32C542RCT6,Arm Cortex-M33 内核,最高主频 144 MHz,256 KB Flash,64 KB RAM
  • 调试器:板载 STLINK-V3EC,支持大容量存储、虚拟串口和调试端口三种功能
  • 用户 LED:LD1,连接 PA5
  • 用户按键:B1,连接 PC13
  • 复位按键:B2
  • 扩展接口:Arduino Uno V3 和 ST morpho 连接器

本实验使用板载的 LD1,无需额外外设。

<br>

2.2 引脚说明

引脚 别名 功能 复用功能 有效电平
PA5 LD1 板载用户 LED TIM2_CH1(AF1) 高电平点亮

PA5(LD1):配置为复用功能(ALTERNATE)、推挽输出(PUSHPULL),由 TIM2 通道 1 直接输出 PWM 波形驱动。

<br>

3. STM32CubeMX2 工程配置

3.1 新建工程

本实验采用 MCU 方式创建工程,即以芯片型号 STM32C542RC 为起点,而非开发板方式。

  1. 进入 MCU 选择界面 启动 STM32CubeMX2,在首页点击 MCU,进入芯片型号选择列表。
  2. 搜索并选中芯片 在 MCU name 输入框中输入 STM32C542RC(或完整型号 STM32C542RCT6),从筛选出的列表中选择对应型号。
  3. 填写项目信息 输入项目名称 TIM_PWM_1kHz 和项目保存路径。项目名称避免使用特殊字符,路径建议使用纯英文目录。

image.png

3.2 基础配置

工程创建后,软件自动进入 Pinout 视图。

时钟配置:本工程系统时钟配置为 144 MHz,APB1 分频系数为 1,TIM2 输入时钟为 144 MHz。

image.png

3.3 TIM2 配置

(1)配置 TIM2 通道 1 为 PWM 输出

在左侧外设列表中找到 Timers → TIM2,点击展开。在 Mode 区域中,将 Channel1 设置为 PWM Generation CH1。

设置完成后,Pinout 视图中 PA5 引脚会自动分配为 TIM2_CH1(复用功能 AF1)。

image.png

(2)配置定时参数

在 TIM2 的 Parameter Settings 中设置:

参数 值 说明
Prescaler (PSC) 1439 144 MHz ÷ 1440 = 100 kHz
Counter Mode Up 向上计数
Counter Period (ARR) 99 100 kHz ÷ 100 = 1 kHz
auto-reload preload Enable 建议启用自动重装载预装载

PWM 频率计算:

PWM 频率 = TIM2时钟 / ((PSC + 1) × (ARR + 1))
= 144,000,000 / ((1439 + 1) × (99 + 1))
= 144,000,000 / (1440 × 100)
= 1000 Hz = 1 kHz

image.png

(3)配置 PWM 通道

在 Channel1 的配置区域中:

参数 值 说明
Mode PWM1 PWM 模式 1
Pulse (CCR1) 0 初始占空比(后续由代码修改)
Output compare preload Enable 使能比较预装载
CH Polarity High 通道极性为高

占空比计算:

占空比 = Pulse / (ARR + 1) = Pulse / 100

即脉冲值 10 对应约 10%,脉冲值 89 对应约 90%。

image.png

(4)确认引脚配置

回到 Pinout 视图,PA5 应显示为 TIM2_CH1(复用功能)。可以设置 User Label 为 LD1。

<br>

3.4 项目配置

  1. 点击 Project Settings,进入工程设置页面。
  2. 在 IDE Format 下拉选项中选择 CMake。
  3. 在 CMake Toolchain 下拉选项中选择 GCC。
  4. 确认配置无误后,点击 Generate Code。CubeMX2 会执行配置检查,如果没有错误,开始在指定路径下生成 CMake 工程文件。
  5. 生成完成后,项目路径下会出现标准 CMake 工程结构,包含 Core/、Drivers/、CMakeLists.txt 等。

image.png

4. 编程实现

4.1 实现思路

采用 “TIM2 硬件 PWM + 主循环更新占空比” 的方案:

mx_tim2_init() // CubeMX2 生成:1 kHz 时基、PWM1 模式、PA5 复用
│
▼
HAL_TIM_OC_EnableComparePreload() // 使能比较预装载
│
▼
HAL_TIM_OC_SetCompareUnitPulse() // 设置初始脉冲 = 10(10%)
│
▼
HAL_TIM_OC_StartChannel() // 启动通道 1 输出
│
▼
HAL_TIM_Start() // 启动计数器,PWM 开始输出
│
▼
主循环:脉冲值 10 → 89 → 10,每步延时 13 ms,往复扫描

与定时器中断实验的区别:第 5 篇用 TIM6 周期中断实现 LED 闪烁,本篇用 TIM2 硬件 PWM 输出实现呼吸灯。前者由 CPU 在中断中翻转引脚,后者由定时器硬件自动产生 PWM 波形,CPU 只需修改占空比。

比较预装载的作用:使能比较预装载后,每次写入的新占空比会在下一个更新事件(PWM 周期边界)才生效,波形切换更平滑,不会产生毛刺。

各步骤使用的 HAL 函数:

步骤 HAL 函数 作用
使能比较预装载 HAL_TIM_OC_EnableComparePreload() 占空比在周期边界更新
设置脉冲值 HAL_TIM_OC_SetCompareUnitPulse() 写入通道 1 的 CCR 值
启动输出通道 HAL_TIM_OC_StartChannel() 使能 TIM2_CH1 输出
启动计数器 HAL_TIM_Start() 启动 TIM2 计数,PWM 开始输出
软件延时 HAL_Delay() 控制呼吸速度(13 ms/步)

4.2 关键代码

在 VS Code 中打开生成的 CMake 工程,找到 Core/Src/main.c,添加以下代码。

(1)文件头部添加头文件与宏定义

#include "main.h"
#include "mx_tim2.h"

/* TIM2_CH1 PWM 参数:周期 99 / 1 kHz,占空比在 10% ~ 90% 之间扫描 */
#define PWM_PERIOD         99u   /* TIM2 ARR,与 1 kHz 时基一致 */
#define PWM_PULSE_MIN      10u   /* 10% 占空比 */
#define PWM_PULSE_MAX      89u   /* 90% 占空比 */
#define PWM_STEP_DELAY_MS  13u   /* 一个完整周期约 2 s:2*80*13 = 2080 ms */

<br>

(2)主函数

int main(void)
{
  if (mx_system_init() != SYSTEM_OK)
  {
    return (-1);
  }
  else
  {
    /* 生成的 mx_tim2_init() 已配置 1 kHz 时基、PWM1 模式和 PA5 引脚。
     * 使能比较预装载后,每次写入的占空比都在下一个更新事件生效。 */
    hal_tim_handle_t *htim2 = mx_tim2_gethandle();

    if (HAL_TIM_OC_EnableComparePreload(htim2, HAL_TIM_OC_COMPARE_UNIT_1) != HAL_OK)
    {
      return (-1);
    }

    /* 从最小占空比开始,避免上电时 LED 完全熄灭 */
    if (HAL_TIM_OC_SetCompareUnitPulse(htim2, HAL_TIM_OC_COMPARE_UNIT_1, PWM_PULSE_MIN) != HAL_OK)
    {
      return (-1);
    }

    /* 启动通道 1 输出,再启动计数器,产生 PWM */
    if (HAL_TIM_OC_StartChannel(htim2, HAL_TIM_CHANNEL_1) != HAL_OK)
    {
      return (-1);
    }
    if (HAL_TIM_Start(htim2) != HAL_OK)
    {
      return (-1);
    }

    /* 呼吸灯:占空比在 10% ~ 90% 之间往复扫描 */
    uint32_t pulse;
    while (1)
    {
      /* 渐亮:10% -> 90% */
      for (pulse = PWM_PULSE_MIN; pulse <= PWM_PULSE_MAX; pulse++)
      {
        (void)HAL_TIM_OC_SetCompareUnitPulse(htim2, HAL_TIM_OC_COMPARE_UNIT_1, pulse);
        HAL_Delay(PWM_STEP_DELAY_MS);
      }
      /* 渐暗:90% -> 10% */
      for (pulse = PWM_PULSE_MAX; pulse >= PWM_PULSE_MIN; pulse--)
      {
        (void)HAL_TIM_OC_SetCompareUnitPulse(htim2, HAL_TIM_OC_COMPARE_UNIT_1, pulse);
        HAL_Delay(PWM_STEP_DELAY_MS);
      }
    }
  }
}

代码说明:

  • mx_tim2_gethandle() 返回 CubeMX2 生成的 TIM2 句柄。
  • HAL_TIM_OC_EnableComparePreload() 使能比较预装载,占空比更新在周期边界生效,波形更平滑。
  • HAL_TIM_OC_SetCompareUnitPulse() 写入通道 1 的脉冲值(CCR),脉冲值 = 占空比 × (ARR+1) / 100。
  • HAL_TIM_OC_StartChannel() 启动通道 1 输出,HAL_TIM_Start() 启动计数器。两步必须都调用,否则 PWM 无法输出。
  • 呼吸循环使用简单的线性扫描(渐亮/渐暗),每步 13 ms,一步改变约 1% 占空比,人眼观察为平滑呼吸效果。
  • 一个完整循环耗时约 2 × 80 步 × 13 ms = 2080 ms ≈ 2 s。

<br>

5. 编译烧录与运行测试

5.1 编译与烧录

  1. 打开工程:用 VS Code 打开 CubeMX2 生成的 CMake 工程文件夹(如 TIM_PWM_1kHz_cmake)。
  2. 编译:点击 VS Code 底部状态栏的 Build 按钮,或使用命令面板执行 CMake 构建。编译完成后,终端应输出 Build finished with exit code 0,无 error。
  3. 连接开发板:用支持数据传输的 USB Type-C 线连接 NUCLEO-C542RC 的 ST-LINK USB 口(CN1)。
  4. 确认设备识别:打开设备管理器,在“端口 (COM 和 LPT)”下应能看到 STLink COMx。
  5. 烧录:点击 VS Code 中的运行按钮,将固件下载到开发板。

image.png

image.png

5.2 运行与测试

烧录完成后,程序自动开始运行。观察板载 LED LD1 的闪烁情况:

  • 测试 1:呼吸灯效果 观察 LD1 亮度变化:由暗渐亮 → 由亮渐暗 → 循环往复,亮度变化平滑,无明显闪烁或跳变。

  • 测试 2:呼吸周期 一个完整的呼吸周期(暗 → 亮 → 暗)约为 2 秒。可用手机秒表计时核对。

  • 测试 3:PWM 波形(可选) 用示波器或逻辑分析仪测量 PA5 引脚,可观察到:

    • 频率约 1 kHz 的 PWM 方波
    • 占空比在 10% ~ 90% 之间周期性变化
    • 脉宽变化呈三角波规律

image.png

image.png

测试结果: ☑ 编译通过,无错误 ☑ 烧录成功 ☑ LD1 呈呼吸灯效果,亮度平滑变化 ☑ 呼吸周期约 2 秒 ☑ 示波器观测 PA5,频率约 1 kHz,占空比在 10% ~ 90% 之间往复变化 功能正常。

6. 小结

本实验通过 TIM2 通道 1 硬件 PWM 输出实现了板载 LED 的呼吸灯效果,掌握了 STM32C5 系列定时器硬件 PWM 输出的配置与使用方法。

核心逻辑可以概括为:“TIM2 硬件产生 1 kHz PWM → 主循环更新占空比 → 三角波扫描实现呼吸效果”。

有两点需要注意:

  • 第一,启动 PWM 需要两步。 HAL_TIM_OC_StartChannel() 使能输出通道,HAL_TIM_Start() 启动计数器,两者缺一不可。只调用其中一个,PWM 不会输出。
  • 第二,使能比较预装载。 HAL_TIM_OC_EnableComparePreload() 让新的占空比在下一个 PWM 周期边界才生效,避免波形切换时出现毛刺。

与上一篇定时器周期中断实验相比,中断方案由 CPU 在中断服务程序中翻转引脚,本实验由定时器硬件自动产生 PWM 波形,CPU 只需更新占空比,这是两者的核心技术差异。

<br>

版权声明:

Copyright by [email]ai4mcu@qq.com[/email] 2026 Crated:2026-10

![image.png](

image.png
赞 收藏 评论0 发布时间:2026-10-21 13:23

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版