stm32学习之旅 定时器PWM的使用(呼吸灯)
PWM,学名:脉冲宽度调制,是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。通俗点说:一个周期间,调制一个高电平的时间和低电平的时间比,比如一个周期10s,你想高电平8s,低电平2s,下一个周期你又想高电平和低电平各5s,这就是PWM(纯属个人理解)。PWM应用也很广泛,比如说电机调速,灯光调亮,电功率调节可能回用到。怎么来配置PWM呢,先来看看工作原理图:ARR:自动重装值,相当于峰值,一旦计数器加到峰值,便会重新清零开始计数
CCRx:比较值,用来和计数器比较
在PWM的一个周期(0-t2),此时为向上计数
0-t1,计数器的值<CCRx,输出低电平
t1-t2,计数器的值>CCRx,输出高电平
再来看一下他的工作原理图,以通道1(OC1)为例:
这个图就很明显了,要配置的地方便是这四个,首先配置的是OC1M的【2:0】这三位,配置为PWM模式1还是模式2,这俩个模式的区别不大,再来是CC1P位,这个位是决定了OC1的极性,1为高电平有效,0为低电平有效。接着是CC1E位,这个决定了通道是否有输出,0为禁止输出,1为开启输出。贴上代码:
TIME.c:
#include "Time.h"
void Time_Init()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitTypeDef gpio;
gpio.GPIO_Pin=GPIO_Pin_5;
gpio.GPIO_Mode=GPIO_Mode_AF_PP;
gpio.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&gpio);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);//重映射脚
TIM_TimeBaseInitTypeDef time;
time.TIM_Period=899; //重载值设为899(最大)
time.TIM_CounterMode=TIM_CounterMode_Up;
time.TIM_Prescaler=0; //预分频系数设为0
TIM_TimeBaseInit(TIM3,&time);
TIM_OCInitTypeDef oc_init;
oc_init.TIM_OCMode=TIM_OCMode_PWM2; //PWM模式2
oc_init.TIM_OutputState=TIM_OutputState_Enable; //是否开启输出通道
oc_init.TIM_Pulse=TIM_OCPolarity_High; //OC1输出的极性,高电平有效
TIM_OC2Init(TIM3,&oc_init);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能预装载寄存器
TIM_Cmd(TIM3,ENABLE);
}
配置好PWM后,这样还不算是成功的,我们说过了,PWM是让高低电平的时间所占的周期不同,所以CCR的值需要发生变化,也就是比较值要发生变化才行, 所以要用到
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)这个函数,它是用来
改变CCR的值,在main函数有:
int main()
{
int ledpwm=0;
Time_Init();
while(1)
{
Delayms(10);
if(ledpwm == 0) ledpwm++;
if(ledpwm>100) ledpwm–; //,这个值不能超过定时器的ARR,按照原子哥的说法,超过300就显得不明显,我用100
TIM_SetCompare2(TIM3,ledpwm);
}
}
代码就是那么多了,实验的效果为重复的:灯慢慢变亮,接着慢慢变暗。至于灯为什么会是这样的效果,是因为一个周期间高电平和低电平的占比不一样,高电平的时间高,灯就更加亮。