7. PWM 输出
📝本节您将了解 PWM(脉宽调制)的工作原理,学习如何通过定时器的捕获/比较功能生成频率和占空比可调的 PWM 信号,并驱动天巧星板载蜂鸣器。
🏆本章目标
1️⃣ 理解 PWM 信号的频率、占空比等关键参数
2️⃣ 了解 MSPM0G3519 定时器的 PWM 输出机制
3️⃣ 通过 SysConfig 配置 PWM 输出
4️⃣ 实现可变占空比的 PWM 输出,驱动蜂鸣器发声
7.1 PWM 基本概念
PWM(Pulse Width Modulation,脉宽调制)是一种用数字信号(只有 0 和 1)来传递信息的调制方式。它不改变信号的电压和频率,而是通过改变每个周期内高电平的持续时长——也就是占空比——来实现不同的控制效果。
打个比方:手电筒的开关只有"开"和"关",但如果按固定节奏快速拨动开关、并控制每次"开"的时长,从远处看手电筒就会呈现出不同的亮度。

核心参数
| 参数 | 定义 | 举例 |
|---|---|---|
| 周期(Period) | 一个完整的开→关→开循环的时间 | 蜂鸣器 1ms 周期 = 1000Hz 音调 |
| 频率(Frequency) | 每秒钟完成多少个周期 | LED 调光用 1kHz(人眼看不出闪烁) |
| 占空比(Duty Cycle) | 每个周期中"开"的时间占比 | 50% = 半开半关,亮度约一半 |

不同场景下,PWM 控制的"是什么"
PWM 不是只有一个套路——参数怎么调,取决于你控制的是什么东西:
| 场景 | 调什么 | 为什么 | 本章实验 |
|---|---|---|---|
| LED 呼吸灯 | 只调占空比 | 频率固定(>100Hz 人眼看不出闪烁),占空比越大灯越亮 | 实验一 |
| 蜂鸣器发声 | 调频率,占空比锁 50% | 频率决定音调高低,占空比 50% 达到最大音量 | 实验二 |
| 舵机控制 | 调脉宽(绝对时间) | 0.5ms~2.5ms 的脉宽对应 0°~180°,频率固定 50Hz | 后续章节 |
| 电机调速 | 只调占空比 | 频率一般在 10kHz 以上(超出人耳,不啸叫) | 后续章节 |
占空比与效果对照
| 占空比 | 波形特征 | 等效电压(3.3V) | 典型效果 | 应用场景 |
|---|---|---|---|---|
| 0% | 始终低电平 | 0V | 完全关闭 | 待机、停止 |
| 25% | 窄脉冲 | 0.83V | LED 微亮 | LED 调光 |
| 50% | 对称方波 | 1.65V | 最大音量 | 蜂鸣器驱动 |
| 75% | 宽脉冲 | 2.48V | 中高速 | 电机调速 |
| 100% | 始终高电平 | 3.3V | 全速运行 | 全功率 |
7.2 MSPM0G3519 的 PWM 实现
PWM 输出是定时器捕获/比较(CC)通道的功能之一。工作原理:
- 定时器按设定周期循环计数
- 捕获/比较寄存器存储一个比较值
- 当计数值 < 比较值时输出高电平,≥ 比较值时输出低电平(或反之)
- 修改比较值即可改变占空比,修改周期值即可改变频率
┌───────┐ ┌───────┐
│ │ │ │
─────┘ └──────────┘ └─────
|← t_h →|← t_l →|
|← Period T →|
占空比 = t_h / T × 100%2
3
4
5
6
7
PWM 频率和占空比计算
PWM频率 = 时钟源频率 / (预分频 × 周期值)
占空比 = 比较值 / 周期值 × 100%2
例如:时钟 32MHz,预分频 32,周期值 1000:
- PWM 频率 = 32000000 / (32 × 1000) = 1000Hz = 1kHz
- 比较值设为 500 → 占空比 = 500/1000 = 50%
天巧星可用 PWM 引脚
| 定时器通道 | 引脚 | 板载用途 |
|---|---|---|
| TIMA1 CCP0 | PB26 | WS2812 RGB LED |
| TIMG6 CCP1 | PB27 | 蜂鸣器 |
| TIMG8 CCP0 | PA29 | 编码器 A |
| TIMG8 CCP1 | PA30 | 编码器 B |
| 其他通道 | 见数据手册 | 自由分配 |
本实验使用 TIMG7 输出 PWM,驱动空闲引脚上的 LED 呼吸灯效果。蜂鸣器实验使用 TIMG6 CCP1(PB27)。
7.3 SysConfig 配置 PWM 输出
7.3.1 基础 PWM 配置
- 打开
.syscfg文件 - 左侧面板找到 PWM 选项卡(或在 TIMER 中选择 PWM 模式)
- 点击 ADD 添加 PWM 实例
配置参数:
| 参数 | 设置值 | 说明 |
|---|---|---|
| Name | PWM_0 | 实例名称 |
| Timer Module | TIMG7 | 选择定时器 |
| PWM Clock Source | BUSCLK | 32MHz |
| PWM Clock Prescaler | 32 | 预分频(计数频率 1MHz) |
| PWM Period | 1000 | 周期计数值(PWM 频率 = 1kHz) |
| PWM Channel 0 Duty | 500 | 初始占空比 50% |
| PWM Channel 0 Pin | 选择目标引脚 | 根据需求选择空闲引脚 |
保存并编译。
PWM 频率选择指南
| 应用 | 推荐频率 | 原因 |
|---|---|---|
| LED 调光 | 1kHz ~ 10kHz | 高于人眼闪烁感知阈值(>100Hz) |
| 蜂鸣器 | 500Hz ~ 5kHz | 人耳可听范围内的音调 |
| 电机驱动 | 10kHz ~ 20kHz | 超出人耳听觉,减少电磁噪音 |
| 舵机控制 | 50Hz(20ms 周期) | 舵机协议要求 |
7.4 PWM 相关函数
常用 PWM DriverLib 函数
设置占空比(比较值):
void DL_TimerG_setCaptureCompareValue(TIMER_Regs *timer, uint32_t value, DL_TIMER_CC_INDEX index);修改比较值即改变占空比。value 范围 0 ~ 周期值。
启动定时器:
void DL_TimerG_startCounter(TIMER_Regs *timer);获取当前周期值:
uint32_t DL_TimerG_getLoadValue(TIMER_Regs *timer);返回当前配置的周期值,用于计算占空比比例。
7.5 实验一:LED 呼吸灯
利用 PWM 占空比渐变实现 LED 亮度的平滑过渡(呼吸效果)。
#include "ti_msp_dl_config.h"
int main(void)
{
SYSCFG_DL_init();
DL_TimerG_startCounter(PWM_0_INST);
uint32_t duty = 0;
int8_t direction = 1; // 1:递增, -1:递减
while (1) {
// 更新占空比
DL_TimerG_setCaptureCompareValue(PWM_0_INST, duty, DL_TIMER_CC_0_INDEX);
// 占空比递增/递减
duty += direction * 10;
// 到达边界则反向
if (duty >= 1000) {
duty = 1000;
direction = -1;
} else if (duty == 0) {
direction = 1;
}
delay_cycles(320000); // 约 10ms,控制呼吸速度
}
}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
运行效果:LED 亮度从暗到亮再从亮到暗循环变化,呈现呼吸灯效果。
原理说明
- 占空比从 0% 到 100% 渐变 → LED 从灭到最亮
- 占空比从 100% 到 0% 渐变 → LED 从最亮到灭
- 每 10ms 改变一次占空比,100 步完成一次渐变 → 单向渐变时间约 1 秒
7.6 实验二:蜂鸣器驱动
天巧星板载无源蜂鸣器接在 PB27(TIMG6 CCP1)。无源蜂鸣器需要外部提供方波驱动,改变频率即改变音调,占空比固定 50% 即可获得最大音量。
SysConfig 配置蜂鸣器 PWM
| 参数 | 设置值 | 说明 |
|---|---|---|
| Name | PWM_BUZZER | 实例名称 |
| Timer Module | TIMG6 | 蜂鸣器对应定时器 |
| PWM Clock Source | BUSCLK | 32MHz |
| PWM Clock Prescaler | 32 | 预分频(计数频率 1MHz) |
| PWM Period | 2273 | 频率 ≈ 440Hz(标准音 A4) |
| PWM Channel 1 Duty | 1136 | 50% 占空比 |
| PWM Channel 1 Pin | PB27 | 蜂鸣器引脚 |
音调频率参考
| 音名 | 频率(Hz) | PWM Period(1MHz 计数频率) |
|---|---|---|
| C4(Do) | 262 | 3817 |
| D4(Re) | 294 | 3401 |
| E4(Mi) | 330 | 3030 |
| F4(Fa) | 349 | 2865 |
| G4(Sol) | 392 | 2551 |
| A4(La) | 440 | 2273 |
| B4(Si) | 494 | 2024 |
| C5(高Do) | 523 | 1912 |
播放简单音调序列
#include "ti_msp_dl_config.h"
// 音调频率对应的周期值(1MHz 计数频率)
#define NOTE_C4 3817
#define NOTE_D4 3401
#define NOTE_E4 3030
#define NOTE_F4 2865
#define NOTE_G4 2551
#define NOTE_A4 2273
#define NOTE_B4 2024
#define NOTE_C5 1912
#define NOTE_REST 0 // 休止符
// 设置蜂鸣器频率
void buzzer_set_freq(uint32_t period)
{
if (period == 0) {
// 休止:停止 PWM
DL_TimerG_stopCounter(PWM_BUZZER_INST);
} else {
DL_TimerG_setLoadValue(PWM_BUZZER_INST, period);
DL_TimerG_setCaptureCompareValue(PWM_BUZZER_INST, period / 2, DL_TIMER_CC_1_INDEX);
DL_TimerG_startCounter(PWM_BUZZER_INST);
}
}
// 播放音符(duration 单位 ms)
void buzzer_play_note(uint32_t period, uint32_t duration_ms)
{
buzzer_set_freq(period);
delay_cycles((uint32_t)(CPUCLK_FREQ / 1000) * duration_ms);
buzzer_set_freq(0); // 音符间短暂静音
delay_cycles((uint32_t)(CPUCLK_FREQ / 1000) * 50);
}
int main(void)
{
SYSCFG_DL_init();
// 播放 C 大调音阶
uint32_t melody[] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4,
NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5};
uint8_t len = sizeof(melody) / sizeof(melody[0]);
while (1) {
for (uint8_t i = 0; i < len; i++) {
buzzer_play_note(melody[i], 400); // 每个音符 400ms
}
delay_cycles(CPUCLK_FREQ); // 播放完暂停 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
运行效果:蜂鸣器循环播放 C 大调音阶(Do Re Mi Fa Sol La Si Do)。
7.7 动态调节 PWM
PWM 的频率和占空比可在运行时动态修改:
// 修改占空比(不改变频率)
DL_TimerG_setCaptureCompareValue(PWM_0_INST, new_duty, DL_TIMER_CC_0_INDEX);
// 修改频率(需同时更新周期和占空比)
DL_TimerG_stopCounter(PWM_0_INST);
DL_TimerG_setLoadValue(PWM_0_INST, new_period);
DL_TimerG_setCaptureCompareValue(PWM_0_INST, new_period / 2, DL_TIMER_CC_0_INDEX);
DL_TimerG_startCounter(PWM_0_INST);2
3
4
5
6
7
8
注意
修改周期值(频率)时建议先停止定时器再修改,避免在计数过程中出现比较值 > 周期值的异常状态。修改占空比(比较值)可以在运行中直接修改,下个周期生效。
7.8 知识总结
| 内容 | 说明 |
|---|---|
| PWM 本质 | 定时器计数 + 比较输出的高低电平切换 |
| 频率控制 | 修改定时器周期值(Period) |
| 占空比控制 | 修改捕获比较值(Compare Value) |
| LED 调光 | 占空比越大 → LED 越亮 |
| 蜂鸣器 | 频率决定音调,占空比固定 50% |
| 天巧星蜂鸣器 | PB27,TIMG6 CCP1 |
掌握 PWM 输出后,你可以驱动蜂鸣器、实现 LED 调光、控制电机转速等。下一章将学习输入捕获——PWM 的"逆操作",测量外部信号的频率和占空比。