跳到主要内容

PWM 控制

PWM(Pulse Width Modulation,脉宽调制)是一种利用数字信号控制模拟电路的技术,通过改变脉冲信号的占空比来控制输出功率。STM32 的定时器外设能够输出多路 PWM 信号,广泛应用于电机控制、LED 调光、电源管理、音频输出等领域。本文档详细介绍 PWM 的工作原理、参数配置、STM32 定时器 PWM 模式以及实际应用。

PWM 原理

什么是 PWM

PWM 是一种周期固定、脉冲宽度可变的信号:

         ┌──────────┐          ┌──────────┐
│ │ │ │
─────┘ └──────────┘ └────
────────────────────────────────────────────
|<──── T ────>|
|<─ Ton ──>|

T = 周期(固定)
Ton = 高电平时间(可变)
Toff = T - Ton = 低电平时间

占空比(Duty Cycle)

占空比是 PWM 信号中高电平时间占整个周期的比例:

占空比 (%) = (Ton / T) × 100%

示例

TonT占空比平均电压(3.3V)
0.3ms1ms30%0.99V
0.5ms1ms50%1.65V
0.8ms1ms80%2.64V

平均电压计算

PWM 信号的平均电压与占空比成正比:

Vavg = Vcc × 占空比

对于 3.3V 系统:

  • 0% 占空比 → 0V
  • 50% 占空比 → 1.65V
  • 100% 占空比 → 3.3V

PWM 的应用

应用场景说明
LED 调光控制 LED 的亮度,通过改变占空比实现
电机控制控制直流电机的转速,PWM 频率决定响应特性
舵机控制舵机通常使用 50Hz PWM,脉宽 0.5ms~2.5ms 对应角度
音频输出PWM 输出经过滤波后可以播放音频
电源管理开关电源中用 PWM 控制输出电压

PWM 参数

频率(Frequency)

PWM 周期 T 的倒数决定频率:

f = 1 / T

常见 PWM 频率:

应用典型频率
LED 调光100Hz~1kHz(避免闪烁)
电机控制1kHz~20kHz(避免噪声)
舵机控制50Hz(20ms 周期)
开关电源100kHz~1MHz

占空比(Duty Cycle)

占空比决定了输出功率或信号的有效值。

分辨率(Resolution)

PWM 分辨率决定了占空比调节的精细程度:

定时器位数最大计数值分辨率(频率 1kHz 时)
8 位2550.39%(1/255)
16 位655350.0015%(1/65535)

STM32 定时器为 16 位,因此具有很高的分辨率。

极性(Polarity)

PWM 输出极性决定有效电平:

  • 高极性:占空比越大,有效输出越高
  • 低极性:占空比越大,有效输出越低

STM32 定时器 PWM 模式

定时器 PWM 输出原理

STM32 定时器的 PWM 输出基于定时器的比较匹配机制:

         ┌────────────────────────────────────────┐
│ 定时器计数器 (CNT) │
│ 0 ──────────────────────────────────► ARR
└────────────────────────────────────────┘


┌──────────────┴───────────────┐
│ 自动重装载寄存器 │
│ (ARR) │
└─────────────────────────────┘

┌────────────────────────────┐
│ 比较寄存器 (CCR) │
│ 可通过软件设置 │
└────────────────────────────┘

│ CCR │
└──────┴────────────► 比较输出

PWM 模式 1 和模式 2

模式计数器方向输出模式
PWM 模式 1递增CNT < CCR 时输出有效电平
PWM 模式 2递增CNT < CCR 时输出无效电平

PWM 模式 1(最常用):

  • 当 CNT < CCR 时,输出高电平(有效电平)
  • 当 CNT >= CCR 时,输出低电平(无效电平)

PWM 输出引脚

STM32F1 定时器 PWM 输出引脚:

定时器通道GPIO重映射
TIM1CH1PA8
TIM1CH2PA9
TIM1CH3PA10
TIM1CH4PA11
TIM2CH1PA0
TIM2CH2PA1
TIM2CH3PA2
TIM2CH4PA3
TIM3CH1PA6
TIM3CH2PA7
TIM3CH3PB0
TIM3CH4PB1
TIM4CH1PB6
TIM4CH2PB7
TIM4CH3PB8
TIM4CH4PB9

注意:TIM1 是高级定时器,输出引脚在通道设为 PWM 时自动使能互补输出(需要配置)。

定时器寄存器详解

TIMx_CRR - 计数器寄存器

存储当前计数器的值,16 位。

TIMx_ARR - 自动重装载寄存器

决定 PWM 周期:

PWM 周期 = (ARR + 1) × 定时器时钟周期

TIMx_CCRx - 比较寄存器(x = 1~4)

决定 PWM 的占空比:

占空比 = CCR / (ARR + 1) × 100%

TIMx_CCMRx - 捕获/比较模式寄存器

配置 PWM 模式:

名称说明
6:3OCxM[2:0]输出比较模式
2OCxPE输出比较预装载使能
1OCxFE输出比较快速使能

OCxM 位设置

模式
110PWM 模式 1
111PWM 模式 2

TIMx_CCER - 捕获/比较使能寄存器

名称说明
0CC1ECH1 输出使能
1CC1PCH1 极性(0=高有效,1=低有效)
4CC2ECH2 输出使能
5CC2PCH2 极性

TIMx_BDTR - 死区控制和刹车寄存器

名称说明
15MOE主输出使能(高级定时器)
14AOE自动输出使能
12:8DTG[7:0]死区发生器设置
7BKE刹车功能使能
6BKP刹车极性

标准库 PWM 配置

GPIO 配置

void TIM3_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

// 使能 GPIO 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);

// 配置 TIM3 CH1 (PA6), CH2 (PA7) 为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// 配置 TIM3 CH3 (PB0), CH4 (PB1)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

TIM3 PWM 初始化

void TIM3_PWM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

// 使能 TIM3 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

// 配置时基
// PWM 频率 = 72MHz / (预分频 + 1) / (ARR + 1)
// 例如:72MHz / 720 / 100 = 1kHz
TIM_TimeBaseStructure.TIM_Period = 999; // ARR = 999(周期 = 1000)
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 预分频 = 72-1 = 71
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 递增计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

// 配置 PWM 输出
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM 模式 1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_Pulse = 500; // 初始占空比 50%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 高极性
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

// 初始化 TIM3 的 4 个通道
TIM_OC1Init(TIM3, &TIM_OCInitStructure); // CH1
TIM_OC2Init(TIM3, &TIM_OCInitStructure); // CH2
TIM_OC3Init(TIM3, &TIM_OCInitStructure); // CH3
TIM_OC4Init(TIM3, &TIM_OCInitStructure); // CH4

// 使能 CCR 预装载(避免 PWM 抖动)
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

// 使能 TIM3
TIM_Cmd(TIM3, ENABLE);
}

完整初始化

void TIM3_PWM_Init(void)
{
TIM3_GPIO_Config();
TIM3_PWM_Config();
}

PWM 函数

设置占空比

// 设置通道 1 占空比 (0-100%)
void TIM3_SetDutyCycle_CH1(uint16_t duty)
{
uint32_t pulse = (duty * (TIM3->ARR + 1)) / 100;
TIM3->CCR1 = pulse;
}

// 设置通道 2 占空比
void TIM3_SetDutyCycle_CH2(uint16_t duty)
{
uint32_t pulse = (duty * (TIM3->ARR + 1)) / 100;
TIM3->CCR2 = pulse;
}

// 使用标准库函数
void TIM3_SetCompare1(uint16_t compare)
{
TIM_SetCompare1(TIM3, compare);
}

void TIM3_SetCompare2(uint16_t compare)
{
TIM_SetCompare2(TIM3, compare);
}

设置频率

// 设置 PWM 频率(单位 Hz)
void TIM3_SetFrequency(uint32_t freq)
{
uint32_t period = 72000000 / freq - 1;
TIM3->ARR = period;
}

// 例如:设置 20kHz PWM
TIM3_SetFrequency(20000);

启动/停止 PWM

// 启动 PWM 输出
void TIM3_PWM_Start(void)
{
TIM_Cmd(TIM3, ENABLE);
}

// 停止 PWM 输出
void TIM3_PWM_Stop(void)
{
TIM_Cmd(TIM3, DISABLE);
}

// 单独使能/禁止通道
void TIM3_CH1_Enable(void)
{
TIM_CCPreloadConfig(TIM3, TIM_CCPreload_Enable);
}

void TIM3_CH1_Disable(void)
{
TIM_CCxCmd(TIM3, TIM_Channel_1, TIM_CCx_Disable);
}

占空比计算工具函数

/**
* 计算给定频率和占空比的 CCR 值
*/
uint16_t CalculateCCR(uint32_t freq, uint8_t duty_percent)
{
// 系统时钟 72MHz,APB1 定时器时钟 72MHz
uint32_t arr = 72000000 / freq - 1;
return (duty_percent * (arr + 1)) / 100;
}

/**
* 设置 PWM 参数
*/
void TIM3_SetPWM(uint32_t freq, uint8_t duty_percent)
{
// 设置频率
TIM3->ARR = 72000000 / freq - 1;

// 设置占空比
uint16_t ccr = (duty_percent * (TIM3->ARR + 1)) / 100;
TIM3->CCR1 = ccr;
TIM3->CCR2 = ccr;
TIM3->CCR3 = ccr;
TIM3->CCR4 = ccr;
}

高级定时器 PWM

TIM1 是高级定时器,支持互补输出和死区控制,常用于电机控制:

TIM1 PWM 配置

void TIM1_PWM_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

// 使能 GPIO 和 TIM1 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

// 配置 GPIO:CH1 (PA8), CH1N (PA7), CH2 (PA9), CH2N (PB0)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOB, &GPIO_InitStructure);

// 配置时基
TIM_TimeBaseStructure.TIM_Period = 7199; // 10kHz PWM
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

// 配置 PWM 输出
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 使能互补输出
TIM_OCInitStructure.TIM_Pulse = 3600; // 50% 占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);

// 配置死区和刹车
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM_BDTRInitStructure.TIM_DeadTime = 0xFF; // 死区时间
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

// 使能预装载
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

// 使能 TIM1
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE); // 必须使能主输出
}

舵机控制 PWM

舵机通常使用 50Hz PWM 信号(周期 20ms),通过改变脉冲宽度控制角度:

脉宽占空比(ARR=19999)角度
0.5ms999
1.0ms199945°
1.5ms299990°
2.0ms3999135°
2.5ms4999180°

舵机初始化

#define SERVO_ARR    19999   // 20ms 周期 (50Hz)
#define SERVO_MIN 999 // 0.5ms (0°)
#define SERVO_MAX 4999 // 2.5ms (180°)
#define SERVO_MID 2999 // 1.5ms (90°)

void Servo_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

// 使用 TIM2 CH1 (PA0)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

// GPIO 配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// TIM2 配置:72MHz / 72 / 20000 = 50Hz
TIM_TimeBaseStructure.TIM_Period = SERVO_ARR;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

// PWM 配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = SERVO_MID; // 默认中间位置
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_Cmd(TIM2, ENABLE);
}

舵机角度控制

/**
* 控制舵机角度
* @param angle: 角度值 0~180
*/
void Servo_SetAngle(uint16_t angle)
{
if (angle > 180) angle = 180;

uint32_t pulse = SERVO_MIN + (angle * (SERVO_MAX - SERVO_MIN) / 180);
TIM_SetCompare1(TIM2, pulse);
}

/**
* 将舵机转到中间位置 (90°)
*/
void Servo_Center(void)
{
TIM_SetCompare1(TIM2, SERVO_MID);
}

LED 呼吸灯

PWM 实现 LED 亮度渐变效果:

#define LED_ARR    255
#define LED_TIM TIM2
#define LED_CHANNEL TIM_Channel_3

void LED_Breathing_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

// TIM2 CH3 (PA2)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// 256 级亮度,频率约 280Hz
TIM_TimeBaseStructure.TIM_Period = LED_ARR;
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 72MHz / 256 ≈ 281kHz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);

TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_Cmd(TIM2, ENABLE);
}

// 呼吸灯效果
void LED_Breathing(void)
{
static int16_t direction = 1;
static uint8_t brightness = 0;

brightness += direction;

if (brightness >= 255) direction = -1;
if (brightness == 0) direction = 1;

TIM_SetCompare3(TIM2, brightness);
delay_ms(10);
}

直流电机 PWM 控制

使用 PWM 控制直流电机转速:

#define MOTOR_ARR   19999   // 1kHz PWM
#define MOTOR_TIM TIM4
#define MOTOR_CH1 TIM_Channel_1 // PB6
#define MOTOR_CH2 TIM_Channel_2 // PB7

void Motor_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

// GPIO 配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

// TIM4 配置:72MHz / 72 / 20000 = 50Hz
TIM_TimeBaseStructure.TIM_Period = MOTOR_ARR;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

// CH1 PWM 配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM4, &TIM_OCInitStructure);

// CH2 PWM 配置
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(TIM4, &TIM_OCInitStructure);

TIM_Cmd(TIM4, ENABLE);
}

/**
* 设置电机转速
* @param speed: -100 ~ +100,正值正转,负值反转
*/
void Motor_SetSpeed(int16_t speed)
{
if (speed > 100) speed = 100;
if (speed < -100) speed = -100;

int16_t abs_speed = speed > 0 ? speed : -speed;

if (speed >= 0)
{
TIM_SetCompare1(TIM4, abs_speed * MOTOR_ARR / 100); // CH1 正转
TIM_SetCompare2(TIM4, 0); // CH2 停止
}
else
{
TIM_SetCompare1(TIM4, 0); // CH1 停止
TIM_SetCompare2(TIM4, abs_speed * MOTOR_ARR / 100); // CH2 反转
}
}

常见问题

1. PWM 无输出

排查步骤

  1. 检查 GPIO 配置是否为复用输出
  2. 确认定时器时钟已使能
  3. 检查 CCxE 位是否置 1
  4. 对于高级定时器,检查 MOE 位和 CCxE 位

2. PWM 频率设置错误

检查计算公式

PWM 频率 = TIMxCLK / ((ARR + 1) × (PSC + 1))

例如:72MHz 时钟,ARR=999,PSC=71

频率 = 72000000 / ((999 + 1) × (71 + 1)) = 72000000 / 72000 = 1000Hz

3. 占空比不正确

检查 CCR 和 ARR 的关系

占空比 = CCR / (ARR + 1)

如果期望 50% 占空比:

  • ARR = 999 → CCR = 500
  • ARR = 1999 → CCR = 1000

4. 多通道 PWM 互相干扰

原因:同时修改 ARR 和 CCR 可能导致输出异常

解决:使用影子寄存器(预装载功能)

// 使能 ARR 预装载
TIM_ARRPreloadConfig(TIM3, ENABLE);

// 使能 CCR 预装载
TIM_OCxPreloadConfig(TIM3, TIM_OCPreload_Enable);

总结

PWM 是嵌入式开发中非常重要的技术:

  • 占空比控制:通过改变占空比实现功率/亮度控制
  • 频率选择:不同应用需要不同的 PWM 频率
  • 分辨率:16 位定时器提供高精度控制
  • 死区控制:高级定时器支持互补输出和死区,用于 H 桥驱动
  • 应用广泛:LED 调光、电机控制、舵机控制、电源管理等

掌握 STM32 的 PWM 输出配置对于各种控制应用至关重要。