第28章 通用定时器-4路PWM输出
第二十八章 通用定时器-4路PWM输出
1. 硬件设计
无硬件设计
2. 软件设计
2.1 编程大纲
-
TIM GPIO和CHx相关参数宏定义
-
输出通道GPIO配置
-
TIM四路输出PWM模式配置
-
主函数测试
2.2 代码分析
2.2.1 TIM3相关参数和四个通道宏定义
#ifndef __GENERAL_TIM_H
#define __GENERAL_TIM_H
#include "stm32f10x.h"
/* TIM相关参数宏定义 */
#define TIMx TIM3
#define TIM_APBxClock RCC_APB1PeriphClockCmd
#define TIMx_CLK RCC_APB1Periph_TIM3
#define TIMx_Period 9
#define TIMx_Prescaler 71
/* 四路输出通道宏定义 */
#define TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA // TIM3_CH1 PA6
#define TIM_CH1_GPIO_PORT GPIOA
#define TIM_CH1_GPIO_PIN GPIO_Pin_6
#define TIM_CH2_GPIO_CLK RCC_APB2Periph_GPIOA // TIM3_CH2 PA7
#define TIM_CH2_GPIO_PORT GPIOA
#define TIM_CH2_GPIO_PIN GPIO_Pin_7
#define TIM_CH3_GPIO_CLK RCC_APB2Periph_GPIOB // TIM3_CH3 PB0
#define TIM_CH3_GPIO_PORT GPIOB
#define TIM_CH3_GPIO_PIN GPIO_Pin_0
#define TIM_CH4_GPIO_CLK RCC_APB2Periph_GPIOB // TIM3_CH4 PB1
#define TIM_CH4_GPIO_PORT GPIOB
#define TIM_CH4_GPIO_PIN GPIO_Pin_1
void GeneralTim_Init(void);
#endif /* __GENERAL_TIM_H */
2.2.2 GPIO配置
// 输出比较通道GPIO配置
static void TIM_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = TIM_CH1_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TIM_CH1_GPIO_PORT, &GPIO_InitStructure); // TIM_CH1 GPIO初始化
RCC_APB2PeriphClockCmd(TIM_CH2_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = TIM_CH2_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TIM_CH2_GPIO_PORT, &GPIO_InitStructure); // TIM_CH2 GPIO初始化
RCC_APB2PeriphClockCmd(TIM_CH3_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = TIM_CH3_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TIM_CH3_GPIO_PORT, &GPIO_InitStructure); // TIM_CH3 GPIO初始化
RCC_APB2PeriphClockCmd(TIM_CH4_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = TIM_CH4_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TIM_CH4_GPIO_PORT, &GPIO_InitStructure); // TIM_CH4 GPIO初始化
}
2.2.3 TIM配置四路PWM输出
// TIM Mode配置
static void TIM_Mode_Init(void)
{
TIM_APBxClock(TIMx_CLK, ENABLE);
/*-------------------------时基配置-------------------------*/
// 计数器时钟 = 系统时钟 / (分频系数 + 1) = 72M / (71 + 1) = 1MHz
// PWM信号周期 = (ARR+1)*(PSC+1)/CNTxCLK = (ARR+1)*1
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = TIMx_Period; // 时钟周期9
TIM_TimeBaseStructure.TIM_Prescaler = TIMx_Prescaler; // 分频系数71
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分频系数1
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure); // TIMx时基初始化
/*----------------------输出比较通道配置----------------------*/
uint16_t CCR1_Val = 5; // 通道1的占空比50%
uint16_t CCR2_Val = 4; // 通道2的占空比40%
uint16_t CCR3_Val = 3; // 通道3的占空比30%
uint16_t CCR4_Val = 2; // 通道4的占空比20%
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 极性高
// 配置TIM3_CH1
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OC1Init(TIMx, &TIM_OCInitStructure);
TIM_OC1PolarityConfig(TIMx, TIM_OCPreload_Enable); // 使能预装载
// 配置TIM3_CH2
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIMx, &TIM_OCInitStructure);
TIM_OC2PolarityConfig(TIMx, TIM_OCPreload_Enable);
// 配置TIM3_CH3
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(TIMx, &TIM_OCInitStructure);
TIM_OC3PolarityConfig(TIMx, TIM_OCPreload_Enable);
// 配置TIM3_CH4
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(TIMx, &TIM_OCInitStructure);
TIM_OC4PolarityConfig(TIMx, TIM_OCPreload_Enable);
TIM_Cmd(TIMx, ENABLE);
}
其中一个新的库函数我们需要解释一下:
TIM_OC1PreloadConfig
是 STM32 微控制器中用于配置定时器输出比较通道的函数。其原型如下:
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
TIMx
: 指定定时器实例,如TIM1
,TIM2
等。TIM_OCPreload
: 预装载使能状态,取值为TIM_OCPreload_Enable
或TIM_OCPreload_Disable
。
功能: 启用或禁用通道1的预装载寄存器。启用预装载使得在更新事件发生时,比较寄存器的值可以被预装载寄存器的值替代,从而避免在运行中改变比较值。
示例:
// 启用通道1的预装载
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
// 这将确保在定时器更新事件时,新的比较值会被加载。
2.2.4 主函数
// TIM—通用定时器-4路PWM输出应用
#include "stm32f10x.h"
#include "led.h"
#include "GeneralTim.h"
int main(void)
{
LED_Init();
LED_BLUE();
GeneralTim_Init();
while(1)
{
}
}
3. 小结
如何利用通用定时器进行4路PWM输出,我们简化一下流程:
- 初始化 GPIO:配置对应的 GPIO 引脚为定时器输出模式。
- 初始化定时器:设置定时器的计数周期、预分频器等。
- 配置输出比较通道:设置每个通道的 PWM 参数。
- 启动定时器:启动定时器并开始输出 PWM 信号。
下面是一个简单的示例代码,使用 TIM2 定时器产生 4 路 PWM 输出信号。假设你使用的是 STM32F103 系列的微控制器,通道配置如下:
- 通道 1: GPIOA Pin 0
- 通道 2: GPIOA Pin 1
- 通道 3: GPIOA Pin 2
- 通道 4: GPIOA Pin 3
#include "stm32f10x.h"
// 初始化 GPIO
void GPIO_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 启用 GPIOA 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置 GPIOA 的四个引脚为定时器输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// 初始化定时器
void TIM_Config(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 启用 TIM2 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 配置定时器基准时间
TIM_TimeBaseStructure.TIM_Period = 999; // 自动重装载寄存器值
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 预分频器,APB1 时钟 / (71 + 1)
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 配置通道 1 PWM 输出
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM 模式 1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 499; // PWM 占空比的脉冲宽度 (50% 的占空比)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 极性高
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能通道 1 的预装载
// 配置通道 2 PWM 输出
TIM_OCInitStructure.TIM_Pulse = 249; // 不同的占空比
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能通道 2 的预装载
// 配置通道 3 PWM 输出
TIM_OCInitStructure.TIM_Pulse = 749; // 不同的占空比
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能通道 3 的预装载
// 配置通道 4 PWM 输出
TIM_OCInitStructure.TIM_Pulse = 999; // 不同的占空比
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能通道 4 的预装载
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
}
// 主函数
int main(void) {
// 配置 GPIO
GPIO_Config();
// 配置定时器
TIM_Config();
while (1) {
// 主循环中可以进行其他操作
}
}
代码解释
- GPIO_Config:
- 启用 GPIOA 的时钟。
- 配置 GPIOA 的四个引脚为推挽输出模式,用于输出 PWM 信号。
- TIM_Config:
- 启用 TIM2 的时钟。
- 配置定时器 TIM2 的基准时间,包括周期(
TIM_Period
)、预分频器(TIM_Prescaler
)、计数模式等。 - 配置 TIM2 的四个通道为 PWM 输出模式,并设置各通道的占空比。
- 启动 TIM2 定时器。
- 主函数:
- 调用配置函数初始化 GPIO 和定时器。
- 进入无限循环,持续运行主程序。
该示例代码中,PWM 信号的占空比是通过调整 TIM_OCInitStructure.TIM_Pulse
来设置的。
2024.9.12 第一次修订,后期不再维护
2025.1.26 优化代码
本文作者:hazy1k
本文链接:https://www.cnblogs.com/hazy1k/p/18410541
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具