PUYA TIMER1 — PWM 输出(HAL 库)

PUYA PY32F0xx_Firmware V1.5.0 TIMER1 PWM 输出(TIM1_PWM)示例教学

TIMER1 — PWM 输出(HAL 库)

固件库: PY32F0xx_Firmware V1.5.0
芯片: PY32F030
源文件: PUYA/PY32F0xx_Firmware_V1.5.0/Projects/PY32F030-STK/Example/TIMER1/TIM1_PWM/Src/main.c


功能简介

定时器(TIMER)是 MCU 最灵活的外设之一,可完成定时、计数、PWM 输出、输入捕获、编码器接口等。本示例聚焦最常用的 PWM(脉冲宽度调制)输出

PY32F030 的 TIM1 是高级定时器,带 4 路独立比较通道。本例配置:

  • 定时器时钟 8MHz(HSI),预分频 800,自动重装载值 ARR = 50
  • 4 个通道的比较值 CCRx 分别设为 10/20/30/40,于是占空比为 20% / 40% / 60% / 80%;
  • HAL_TIM_PWM_Start() 启动 4 路 PWM,输出到对应引脚(在 HAL_TIM_MspInit 中映射为 TIM1_CH1~CH4)。

PWM 频率 = 定时器时钟 / (预分频 × (ARR+1)) = 8MHz / (800 × 50) = 200Hz。占空比 = CCR / (ARR+1)。

硬件准备

  • PY32F030 开发板
  • 示波器 / 逻辑分析仪(测 TIM1_CH1~CH4 引脚),或接 4 颗 LED(串限流电阻)观察亮度
  • 无需额外接线(用板载/引脚直出)

完整代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "main.h"

#define PERIOD_VALUE  (uint32_t)(50 - 1)   /* ARR:计数上限 49 */
#define PULSE1_VALUE  10                    /* CH1 比较值 -> 占空比 10/50 = 20% */
#define PULSE2_VALUE  20                    /* CH2 -> 40% */
#define PULSE3_VALUE  30                    /* CH3 -> 60% */
#define PULSE4_VALUE  40                    /* CH4 -> 80% */

TIM_HandleTypeDef    TimHandle;
TIM_OC_InitTypeDef   sConfig;

int main(void)
{
  HAL_Init();
  APP_SystemClockConfig();              /* 系统时钟:HSI 8MHz */

  /* 定时器时基配置 */
  TimHandle.Instance              = TIM1;
  TimHandle.Init.Period           = 50;            /* 自动重装载值 ARR */
  TimHandle.Init.Prescaler        = 800 - 1;       /* 预分频 799 -> 8MHz/800 = 10kHz */
  TimHandle.Init.ClockDivision    = TIM_CLOCKDIVISION_DIV1;
  TimHandle.Init.CounterMode      = TIM_COUNTERMODE_UP;       /* 向上计数 */
  TimHandle.Init.RepetitionCounter = 1 - 1;                  /* 重复计数 0 */
  TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) APP_ErrorHandler();

  /* PWM 输出通道参数 */
  sConfig.OCMode      = TIM_OCMODE_PWM1;     /* PWM 模式 1 */
  sConfig.OCPolarity  = TIM_OCPOLARITY_HIGH; /* 有效电平为高 */
  sConfig.OCFastMode  = TIM_OCFAST_DISABLE;
  sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  sConfig.OCIdleState  = TIM_OCIDLESTATE_RESET;

  sConfig.Pulse = PULSE1_VALUE; /* CH1 */
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK) APP_ErrorHandler();
  sConfig.Pulse = PULSE2_VALUE; /* CH2 */
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_2) != HAL_OK) APP_ErrorHandler();
  sConfig.Pulse = PULSE3_VALUE; /* CH3 */
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_3) != HAL_OK) APP_ErrorHandler();
  sConfig.Pulse = PULSE4_VALUE; /* CH4 */
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_4) != HAL_OK) APP_ErrorHandler();

  /* 启动 4 路 PWM 输出 */
  HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_3);
  HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_4);

  while (1) {}
}

代码分段讲解

1. 频率与占空比计算

  • PWM 频率 = TIM_CLK / ((PSC+1) × (ARR+1))
    • 本例:8MHz / (800 × 50) = 200Hz
  • 某通道占空比 = CCRx / (ARR+1)(PWM1 且极性为高时):
    • CH1:10/50 = 20%,CH2:20/50 = 40%,CH3:30/50 = 60%,CH4:40/50 = 80%

2. PWM 模式 1 / 2

  • TIM_OCMODE_PWM1:计数 < CCR 时输出有效(高),≥ CCR 时无效(低)。
  • TIM_OCMODE_PWM2:极性相反。改变模式或 OCPolarity 可反转波形,但占空比数值关系不变。

3. 引脚映射

TIM1_CH1~CH4 具体复用哪个 GPIO 引脚,由 HAL_TIM_MspInit()py32f0xx_hal_msp.c)里的 HAL_GPIO_Init + Alternate 决定。若你改了引脚,需同步修改 MSP 配置。

4. 高级定时器 TIM1 的特殊性

TIM1 是高级定时器,带互补输出与死区(可用于电机/电源)。本例未用互补通道(N 端),仅用普通 CH1~CH4 输出。

实验现象

  • TIM1_CH1~CH4 输出 200Hz PWM,占空比分别为 20% / 40% / 60% / 80%;
  • 接 LED 时可见 4 颗亮度依次递增;示波器可见 4 路不同占空比方波。

常见问题

  1. 引脚没波形?

    • 确认 MSP 里已把 CHx 引脚复用为 TIM1 并按 Alternate 配置;
    • 确认已调用 HAL_TIM_PWM_Start() 对应通道。
  2. 想改频率?

    • Period(ARR)或 Prescaler:频率与两者成反比。例:要 1kHz,可设 PSC=800-1, ARR=10-1(8MHz/800/10=1kHz)。
  3. 想做呼吸灯?

    • 在主循环或定时器中断里周期性改变 CCRx__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_x, newVal);
  4. 占空比算不对?

    • 注意是 CCRx / (ARR+1),且受 OCModeOCPolarity 影响有效区间。

小结

  • PWM = 定时器在 ARR 范围内循环计数,用 CCR 决定高电平占比。
  • 关键三参数:PSC(分频)、ARR(周期)、CCR(占空比)
  • HAL_TIM_PWM_InitHAL_TIM_PWM_ConfigChannelHAL_TIM_PWM_Start 三步即可输出。

拓展应用

  • LED 调光 / 呼吸灯(__HAL_TIM_SET_COMPARE 动态调占空比)。
  • 舵机控制(50Hz PWM,0.52.5ms 脉宽对应 0180°)。
  • 直流电机调速(配合 MOSFET/驱动芯片)。
  • 蜂鸣器发声(不同频率 PWM 出不同音调);多路 PWM 做音乐。
  • 高级用法:互补 PWM + 死区驱动半桥(见 TIM1_ComplementarySignals 系列)。
世界是你们
使用 Hugo 构建
主题 StackJimmy 设计