目录
PWM知识概要
PWM简介:
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制。就是调制一个周期内高低电平占比时间,这里一个周期就是定时计数器记一次数的时间,该周期由ARR寄存器和PSC寄存器共同决定。
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达7路的 PWM 输出。而通用定时器也能同时产生多达 4 路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM输出!
PWM输出原理
通过TIMx_CCR1值与TIMx_CNT值比较大小,输出不同极性的电平。TIMx_CCR1值/ARR值 就是占空比。比如ARR为100,CCR1为50,那么占空比就是1/2.。
PWM相关寄存器简介
在此之前先介绍一下TIMx_CNT与TIMx_ARR寄存器的区别。TIMx_CNT是定时计数器,该计数器不断累加,当累加到ARR值时溢出,重新重0开始计数,所以说CNT值<=ARR值,ARR值是计数器的一个周期。
1)捕获/比较模式寄存器(TIMx_CCMR1/2)。该寄存器用来设置PWM模式。该寄存器一共有两个,TIMx_CCMR1控制CH1和2,TIMx_CCMR2控制CH3和4。
模式设置位 OCxM,此部分由 3 位组成。总共可以配置成 7 种模式,我们使用的是 PWM 模式,所以这 3 位必须设置为 110/111。
- 110:PWM模式1- 无论向上还是向下计数,只有当TIMx_CNT<TIMx_CCR1时,输出有效电平(有效电电平可以是高电平,也可以是低电平,)。TIMx_CNT就是定时计数器当前计数值(该值最大为ARR值),TIMx_CCR1是自己设置的值。TIMx_CCR1/ARR值 就是占空比。
111:PWM模式2- 无论向上还是向下计数,只有当TIMx_CNT>TIMx_CCR1时,输出有效电平(有效电电平可以是高电平,也可以是低电平,)。
举例:比如我们设置PWM模式1 ,有效电平为高电平。
2)捕获/比较使能寄存器(TIMx_CCER)。不难理解,该寄存器控制刻个通道的开关以及输出有效电平(就是上个寄存器讲到的有效电平)。
比如我要设置通道2输出PWM,并且2通道的有效电平为高电平。CC2P设置为0,CC2E设置成1。
3)捕获/比较寄存器(TIMx_CCR1~4),该寄存器总共有4个,对应 4个输通道 CH1~4
这是一个16位寄存器,用来存放捕获/比较寄存器值。通过该值与CNT值比较,控制高低电平输出,实现PWM输出,该寄存器用来实现控制占空比。
PWM相关库函数
#include "stm32f10x.h"
void timer3_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStr;//时基单元结构体
TIM_OCInitTypeDef TIM_OCInitStructure; //输出初始化结构体
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟3使能
TIM_TimeBaseInitStr.TIM_ClockDivision = TIM_CKD_DIV1;//默认值
TIM_TimeBaseInitStr.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInitStr.TIM_Period = 499; //2000hz 5ms
TIM_TimeBaseInitStr.TIM_Prescaler = 71; // 72分频
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStr); //配置时基单元
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
TIM_OCInitStructure.TIM_Pulse = 100; //占空比 = pulse/ARR
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC2
TIM_Cmd(TIM3, ENABLE);//开启定时器
}
Void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
举例:TIM_OC2Init(TIM3, &TIM_OCInitStructure);
该函数用来初始化PWM输出通道,该函数有TIM_OC1Init~ TIM_OC4Init 4个函数,分别对应通道1~4。
TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。
TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。
TIM_OCPolarity 用来设置有效电平是高还是低。
TIM_SetCompare2(TIM3,pwm_pulse);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
举例:TIM_SetCompare2(TIM3,pwm_pulse);
该函数用来设置TIMx_CCR1寄存器数值,该值和ARR值比较就是占空比。
PWM输出重映射
为了节约引脚,将一些复用功能重映射到其他引脚,使得PWM输出不会固定在某一引脚。
本章只介绍PWM重映射引脚,详细知识不过多介绍。在重映射前需要使能AFIO时钟。
GPIO_InitTypeDef GPIO_InitStr; //定义GPIO初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能gpio外部时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//复用
GPIO_InitStr.GPIO_Mode= GPIO_Mode_AF_PP;
GPIO_InitStr.GPIO_Pin=GPIO_Pin_5; // 设置pin5引脚
GPIO_InitStr.GPIO_Speed=GPIO_Speed_50MHz; //设置输出速度
GPIO_Init(GPIOB,&GPIO_InitStr); //初始化gpio_pin5
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
通过上述代码,将Timer3 CH2通道 PWM输出重映射到PB5引脚。
PWM多路输出
在pwm初始化函数中,添加TIM_OCxInit()函数即可输出通道x(x为1~4) PWM。但是同一定时器产生的PWM频率都相同,各个通道占空比可以不同。
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC1
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC2
TIM_OC3Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC3
TIM_OC4Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC4
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC1
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC2
TIM_OC3Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC3
TIM_OC4Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC4