PWM输出原理
假定定时器工作在向上计数 PWM 模式,且当 CNT=CCRx 时输出 1。当 CNT 值小于 CCRx 的时候,IO 输出低电平(0),当 CNT 值大于等于 CCRx 的时候, IO 输出高电平(1),当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。 改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的频率。
CCR1:捕获比较(值)寄存器(x=1,2,3,4):设置比较值。
CCMR1: OC1M[2:0]位:对于PWM方式下,用于设置PWM模式1(110)或者PWM模式2(111)
CCER:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。
CCER:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。
自动重载的预装载寄存器
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
简单的说,ARPE=1,ARR立即生效;APRE=0,ARR下个比较周期生效。
void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
typedef struct
{
uint16_t TIM_OCMode; //PWM模式1或者模式2
uint16_t TIM_OutputState; //输出使能 OR失能
uint16_t TIM_OutputNState;
uint16_t TIM_Pulse; //比较值,写CCRx
uint16_t TIM_OCPolarity; //比较输出极性
uint16_t TIM_OCNPolarity;
uint16_t TIM_OCIdleState;
uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure. TIM_Pulse=100;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2
void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Comparex);
void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
使能定时器14时钟:RCC_APB1PeriphClockCmd();
使能GPIOF时钟:RCC_AHB1PeriphClockCmd ();
②初始化IO口为复用功能输出。函数:GPIO_Init();
③ GPIOF9复用映射到定时器14
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
④初始化定时器:ARR,PSC等:TIM_TimeBaseInit();
⑤初始化输出比较参数:TIM_OC1Init();
⑥使能预装载寄存器: TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
⑦使能自动重装载的预装载寄存器允许位TIM_ARRPreloadConfig(TIM14,ENABLE);
⑧使能定时器TIM_Cmd();
⑨不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare1();
程序
使用定时器14的PWM功能,输出占空比可变的PWM波,用来驱动LED灯,从而达到LED(PF9)亮度由暗变亮,又从亮变暗,如此循环。
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
void PWm_Init(u32 arr,u32 psc)
{
GPIO_InitTypeDef GPIO_Initer;
TIM_TimeBaseInitTypeDef TIM_TimeBaseIniter;
TIM_OCInitTypeDef TIM_OCIniter;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOF,ENABLE);
GPIO_Initer.GPIO_Mode=GPIO_Mode_AF;
GPIO_Initer.GPIO_OType=GPIO_OType_PP;
GPIO_Initer.GPIO_Pin=GPIO_Pin_9;
GPIO_Initer.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_Initer.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOF,&GPIO_Initer);
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
TIM_TimeBaseIniter.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseIniter.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseIniter.TIM_Period=arr;//自动装载
TIM_TimeBaseIniter.TIM_RepetitionCounter=psc;//定时器分频
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseIniter);
TIM_OCIniter.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCIniter.TIM_OutputState=ENABLE;
TIM_OCIniter.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OC1Init(TIM14,&TIM_OCIniter);
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM14,ENABLE);
TIM_Cmd(TIM14,ENABLE);
}
int main(void)
{
int a=1;
u16 b=0;
delay_init(168);
LED_Init();
PWm_Init(499,83);
while(1)
{
delay_ms(10);
if(a)
b++;
else
b--;
if(b>100)
a=0;
if(b==0)
a=1;
TIM_SetCompare1(TIM14,b);
}
}
运行结果
PWM输出实验