TIM — TIM3 PWM 输出(TIM3_PWMOutput)
固件库: CIU32F003_STDLib V1.0.3
芯片: CIU32F003(Cortex-M0)
源文件: CIU32/CIU32F003_STDLib_V1.0.3/Projects/TIM/TIM3_PWMOutput/Source/
一、功能简介
本示例用 TIM3 输出 2 路 PWM 波形:通道 CH1 接 PA5、通道 CH2 接 PA4,
均工作在 16 位计数精度下。两路占空比分别设为约 50% 与 37.5%,
可直接用示波器观察,也可接 LED 看亮度差异、接蜂鸣器听音调。
二、硬件准备
- CIU32F003 开发板
- 示波器 / 逻辑分析仪(观察 PA4、PA5)
- 或把 PA4/PA5 接 LED(串限流电阻)观察亮度
- 引脚映射:
| TIM3 信号 |
引脚 |
复用 |
| CH1 |
PA5 |
AF3_TIM3 |
| CH2 |
PA4 |
AF3_TIM3 |
三、完整代码
3.1 主流程 main.c
1
2
3
4
5
6
7
8
9
10
11
|
#include "main.h"
int main(void)
{
system_clock_config(); /* 系统时钟 RCH 48MHz */
gpio_init(); /* PA4/PA5 映射为 TIM3 复用 */
tim3_init(); /* 配置定时器与 PWM 通道 */
std_tim_enable(TIM3); /* 启动计数,开始输出 PWM */
while (1) { }
}
|
3.2 引脚与定时器初始化 common.c
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
|
#define TIM_PERIOD_VALUE (0xFFFFU) /* ARR = 65535,16 位精度 */
#define TIM_PRESCALER_VALUE (0x03U) /* 预分频值 */
#define TIM_PULSE1_VALUE (uint32_t)(TIM_PERIOD_VALUE / 2) /* CH1 比较值 ≈ 50% */
#define TIM_PULSE2_VALUE (uint32_t)(TIM_PERIOD_VALUE * 37.5 / 100) /* CH2 比较值 ≈ 37.5% */
/* GPIO:PA4/PA5 复用为 TIM3 通道 */
void gpio_init(void)
{
std_gpio_init_t tim3_gpio_init = {0};
std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);
tim3_gpio_init.pin = GPIO_PIN_4 | GPIO_PIN_5;
tim3_gpio_init.mode = GPIO_MODE_ALTERNATE;
tim3_gpio_init.pull = GPIO_NOPULL;
tim3_gpio_init.alternate = GPIO_AF3_TIM3; /* 复用功能 3 = TIM3 */
std_gpio_init(GPIOA, &tim3_gpio_init);
}
/* TIM3 初始化:基础参数 + 两路 PWM 输出 */
void tim3_init(void)
{
std_tim_basic_init_t basic_init_struct = {0};
std_tim_output_compare_init_t oc_config_struct = {0};
std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_TIM3); /* 使能 TIM3 时钟(在 APB1) */
/* ① 基础计数参数 */
basic_init_struct.prescaler = TIM_PRESCALER_VALUE; /* 预分频:分频计数时钟 */
basic_init_struct.period = TIM_PERIOD_VALUE; /* ARR:计数到 0xFFFF 溢出 */
basic_init_struct.clock_div = TIM_CLOCK_DTS_DIV1; /* 时钟分频(死区滤波用) */
std_tim_init(TIM3, &basic_init_struct);
/* ② 通道 1:PWM1 模式,高电平有效,占空比 ≈ 50% */
oc_config_struct.output_compare_mode = TIM_OUTPUT_MODE_PWM1;
oc_config_struct.output_pol = TIM_OUTPUT_POL_HIGH;
oc_config_struct.pulse = TIM_PULSE1_VALUE;
oc_config_struct.output_state = TIM_OUTPUT_ENABLE;
std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_1);
/* ③ 通道 2:同样 PWM1,占空比 ≈ 37.5% */
oc_config_struct.pulse = TIM_PULSE2_VALUE;
std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_2);
}
|
四、代码分段讲解
① 基础计数参数
period(ARR)= 0xFFFF = 65535:计数器从 0 累加到 65535 后归零,决定 PWM 周期;
prescaler:对 TIM3 的输入时钟做分频,得到“计数时钟”。Period 与 Prescaler 共同决定 PWM 频率:
PWM 频率 = TIM3计数时钟 / (ARR + 1)。
② PWM 模式
本例用 PWM1 模式 + 高电平有效(POL_HIGH):
- 计数器 < CCR(比较值)时,输出高;
- 计数器 ≥ CCR 时,输出低。
因此 占空比 ≈ CCR / (ARR + 1)。
③ 两路占空比
- CH1:
pulse = 0xFFFF/2,占空比 ≈ 50%;
- CH2:
pulse = 0xFFFF * 37.5%,占空比 ≈ 37.5%。
想调占空比,只需改 pulse(比较值);想调频率,改 period 或 prescaler。
④ 启动输出
std_tim_enable(TIM3) 让计数器开始跑,PWM 随即从引脚输出,之后主循环空转即可。
五、实验现象
- 用示波器看 PA5:占空比约 50% 的方波;
- 看 PA4:占空比约 37.5% 的方波;
- 两路频率相同,仅高电平时间不同;
- 接 LED 时,PA5 比 PA4 更亮(占空比更大)。
六、常见问题
| 现象 |
可能原因 |
解决办法 |
| 引脚没波形 |
复用功能选错 |
确认 alternate = GPIO_AF3_TIM3(TIM3 对应 AF3) |
| 频率与预期不符 |
没算清预分频 |
频率 = 计数时钟 /(ARR+1),计数时钟受 prescaler 影响 |
| 占空比反了 |
极性设反 |
把 output_pol 改为 TIM_OUTPUT_POL_LOW 反转 |
| 改占空比无效 |
没在使能后更新 |
运行中改 CCR 需配合影子寄存器/事件更新(本例初始化即定) |
七、小结
PWM 输出三要素:ARR 定周期、CCR(pulse) 定占空比、极性定高低电平对应关系。
流程:开 TIM 时钟 → 配引脚为对应 AF → 配基础计数参数 → 配每路 OC 为 PWM → 使能定时器。
记住占空比公式 CCR/(ARR+1),调光调速都靠它。
八、拓展应用
- LED 呼吸灯:在定时器中断/主循环里缓慢改变
pulse;
- 电机调速:PWM 接 MOSFET/驱动芯片控制平均电压;
- 测频率/占空比:用输入捕获(
TIM3_InputCapture / TIM3_PWMInput);
- 无刷电机:TIM1 互补输出 + 死区(
TIM1_ComplementarySignals)。