PWM - 脉冲宽度调制–一种模拟控制方式
文章目录
PWM 概述
工作单元
工作过程
以向上计数举例,0->ARR(自动重装载值),与输入捕获寄存器中的值CCRRx进行比较,高便产生一个高电平(无效电平),低便产生一个低电平(有效电平),向下计数也一样,即产生一个PWM波。
内部实现
CCR1:捕获比较寄存器,设置比较值
OC1M[2:0]位:
对于PWM方式下,用于设置PWM模式1【110】或者模式2【111】
CC1P位:输入捕获1输出极性。0:高电平有效,1:低电平有效。
CC1E位:输入捕获1输出使能。0:关闭,1:打开。
向上计数->PWM 示意图
可知PWM(脉冲宽度调制)模式下产生的信号频率由TIMx_ARR寄存器确定、占空比由TIMx_CCRx寄存器确定。
配置寄存器库函数
使能预装载寄存器
ARPE位为0,ARR下个周期生效。
ARPE位为1,ARR本周期生效。
常用寄存器和库函数配置
void TIM_OCxInit(TIM_TypeDef*Timx,TIM_OCInitTypeDef*TIM_OCInitStruct);
typedef struct
{
uint16_t TIM_OCMode;//PWM模式一或者模式二
uint16_t TIM_OutputState//输出使能或者失能
uint16_t TIM_Pulse;//比较值,写CCRx
uint16_t TIM_OCPolarity;//比较输出极性
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_ Pulse = 100;
TIM_OCInitStructure.TIM_ OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIm3,&TIM_OCInitStructure);
void TIM_SetCompareX(TIM_TypeDef*TIMx,unit16_t Comparex);//设置比较值函数
void TIM_OCxPreloadConfig(TIM_TypeDef*TIMx,uint16_t TIM_OCPreload);//使能输出比较预装载
void TIM_ARRPreloadConfig(TIM_TypeDef*TIMx,FunctionalState NewState);//使能自动重装载的预装载寄存器允许位
PWM输出实验
要求
PWM功能->占空比可变PWM波->驱动LED灯->亮暗循环
输出配置步骤
①使能定时器14和相关IO口时钟
RCC_APB1PeriphClockCmd();//使能定时器14时钟
RCC_AHB1PeriphClockCmd();//使能GPIOF时钟
②初始化IO口为复用功能输出。
GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
③GPIOF9复用映射到定时器14
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
④初始化定时器
TIM_TimeBaseInit();
⑤初始化输出比较参数
TIM_OC1Init();
⑥使能预装载寄存器:
TIM_OC1PreloadConfig(TIM14,TIM_OCPreload_ENable);
⑦使能定时器。
TIM_ARRPreloadConfig(TIM14,ENABLE);
⑧不断改变比较值CCRx,达到不同的占空比效果
TIM_SetCompare1();
代码
#include "pwm.h"
#include "led.h"
#include "usart.h"
// TIM14 pwm部分初始化
//pwm输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM14_PWM_Init(u32 arr,u32 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); // TIM14时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //PORTF时钟使能
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9复用为定时器14
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOF9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF9
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);//初始化定时器14
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
TIM_OC1Init(TIM14, &TIM_OCInitStructure); //初始化外设TIM1 4OC1
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //使能TIM14在CCR1上的预装载寄存器
TIM_ARRPreloadConfig(TIM14,ENABLE);//APRE使能
TIM_Cmd(TIM14, ENABLE); //使能TIM14
}
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "pwm.h"
int main(void)
{
u16 led0pwmval=0;
u8 dir=1;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级
delay_init(168); //初始化延时函数
uart_init(115200);//初始化串口波特率115200
TIM14_PWM_Init(500-1,84-1); // 84M/84 = 1MHz的计时频率,重装载值500,pwm频率为1M/500 = 2khz
while(1) //实现比较值从0-300递增,到300后从300-0递减,循环
{
delay_ms(10);
if(dir)led0pwmval++;//递增
else led0pwmval--; //递减 if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
TIM_SetCompare1(TIM14,led0pwmval);//修改比较值,修改占空比
}
}```