STM32学习笔记——通用定时器的PWM介绍及配置

脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!这里我们仅利用 TIM3的 CH2 产生一路 PWM 输出。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
配置过程
1)开启 TIM3 时钟以及复用功能时钟,配置 PB5 为复用输出。
先开启 TIM3 的时钟,然后配置 PB5 为复用输出,这是因为 TIM3_CH2 通道将重映射到 PB5 上,此时,PB5属于复用功能输出。库函数使能 TIM3 时钟的方法是:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器 3 时钟

库函数设置 AFIO 时钟的方法是:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //复用时钟使能

最后设置 PB5 为复用功能输出
列出 GPIO 初始化的一行代码即可:
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出

2)设置 TIM3_CH2 重映射到 PB5 上。
因为 TIM3_CH2 默认是接在 PA7 上的,所以我们需要设置 TIM3_REMAP 为部分重映射(通过 AFIO_MAPR 配置),让 TIM3_CH2 重映射到 PB5 上面。在库函数函数里面设置重映射的函数是:

void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)

STM32 重映射只能重映射到特定的端口。第一个入口参数可以理解为设置重映射的类型,比如 TIM3 部分重映射入口参数为GPIO_PartialRemap_TIM3。所以 TIM3 部分重映射的库函数实现方法是:

GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); 

3)初始化 TIM3,设置 TIM3 的 ARR 和 PSC。
在开启了 TIM3 的时钟之后,我们要设置ARR 和 PSC 两个寄存器的值来控制输出 PWM 的
周期。当 PWM 周期太慢(低于 50Hz)的时候,我们就会明显感觉到闪烁了。因此,PWM 周期在这里不宜设置的太小。这在库函数是通过 TIM_TimeBaseInit 函数实现的【参考】调用的格式为:

TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的 

4)设置 TIM3_CH2 的 PWM 模式,使能 TIM3 的 CH2 输出。
在库函数中,PWM 通道设置是通过函数TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里我们使用的是通道 2,所以使用的函数是TIM_OC2Init()。

void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)

TIM_OCInitTypeDef的定义:

typedef struct
{
 uint16_t TIM_OCMode;
uint16_t TIM_OutputState; 
 uint16_t TIM_OutputNState; 
 uint16_t TIM_Pulse; 
 uint16_t TIM_OCPolarity; 
 uint16_t TIM_OCNPolarity; 
 uint16_t TIM_OCIdleState; 
 uint16_t TIM_OCNIdleState; 
} TIM_OCInitTypeDef;

这里我们讲解一下与我们要求相关的几个成员变量:
参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。
参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。
参数 TIM_OCPolarity 用来设置极性是高还是低。
其他的参数 TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState 和 TIM_OCNIdleState 是高级定时器 TIM1 和 TIM8 才用到的。
要实现我们上面提到的场景,方法是:

TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC2

5)使能 TIM3。
在完成以上设置了之后,我们需要使能 TIM3。使能 TIM3 的方法前面已经讲解过:

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

6)修改 TIM3_CCR2 来控制占空比。
最后,在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定
的,而我们通过修改 TIM3_CCR2 则可以控制 CH2 的输出占空比。在库函数中,修改 TIM3_CCR2 占空比的函数是:

void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2)

理所当然,对于其他通道,分别有一个函数名字,函数格式为TIM_SetComparex(x=1,2,3,4)。

通过以上 6 个步骤,我们就可以控制 TIM3 的 CH2 输出 PWM 波了。

//TIM3 PWM 部分初始化
//PWM 输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{ 
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①使能定时器 3 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //①使能 GPIO 和 AFIO 复用功能时钟

GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //②重映射 TIM3_CH2->PB5 

//设置该引脚为复用输出功能,输出 TIM3 CH2 的 PWM 脉冲波形 GPIOB.5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //①初始化 GPIO

//初始化 TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //设置在自动重装载周期值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //③初始化 TIMx

//初始化 TIM3 Channel2 PWM 模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //④初始化外设 TIM3 OC2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器

TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3
}
发布了28 篇原创文章 · 获赞 25 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Summertrainxy/article/details/105317449