前面介绍了定时器的基础知识以及更新中断,本次我们将一起探讨利用定时器的输出pwm。
如果对定时器不了解的先观看这个帖子:https://blog.csdn.net/zj490044512/article/details/83718775
本次的pwm输出是基于定时器中断来输出的。
首先还是要从结构框图开始:
圈出部分就是我们要探讨的部分。
首先介绍下pwm输出过程:启动定时器计数---设定输出比较的值---将定时器当前计数值和输出比较值作比较---由比较的大小从而控制输出不同占空比的pwm。
图中CNT为当前计数值CCR1为设置的比较值。而CC1P实际上就是控制PWM模式的有效电平(1有效还是0有效)
pwm的两种模式:
有图可得到改变CCRx的值就是改变pwm的占空比,改变ARR的值就是改变pwm的频率。
说点单一点就是:当ARPE=1时,当还没有达到溢出值(之前设定的ARR值),的时候我们人为改变了ARR的值那么这个值就会立即生效。反之ARPE=0时,我们改变ARR的值时本次ARR中的值还是原来的值等到下个周期才会改变为新写入的值。
对于IO口输出pwm由于IO默认为输入输出功能当我们要用到pwm输出那么就要用到IO口的复用输出这需要在初始化IO时配置为复用输出模式。
甚至通道一在没有从映射的情况下是PA6我们可以重映射到其他引脚例如:部分从印象到PB4关于通道重映射到某个引脚的查询数据手册。
PWM输出配置步骤:
① 使能定时器和相关IO口时钟(注意IO的复用输出)。
② 初始化IO口为复用功能输出。函数:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
③如果IO口需要从映射的则设置从映射
例如:这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,
所以需要开启AFIO时钟。同时设置重映射。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //重映射函数
④ 初始化定时器:ARR,PSC等:TIM_TimeBaseInit();
⑤ 初始化输出比较参数:TIM_OC2Init();
⑥ 使能预装载寄存器: TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
⑦ 使能定时器。TIM_Cmd();
⑧ 不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare2();
注:
设置比较值函数:void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Compare2);
使能输出比较预装载:void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
使能自动重装载的预装载寄存器允许位:void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
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