PWM的介绍与使用--学习笔记

PWM是什么?

PWM(Pulse Width Modulation)脉冲宽度调制。
在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,利用数字输出来对模拟电路进行控制来等效地获取所需要的模拟参量(脉冲波形对连续参考波形进行等效的变换通过伏秒平衡来实现),常用于电机控速等领域。
相关参数:频率即为一秒内完成的周期数量,频率=1/Ts ;占空比指高电平时间和整个周期的比值,占空比=Ton/Ts ;分辨率为占空比变化步距。比如说,整个周期的时间为10毫秒,高电平的时间为6毫秒,则占空比为60%.

相关知识点

PWM的原理
比如STM32单片机的IO接口只能输出高低电平。假设高电平为5V,低电平为0V,那么如何输出高低电平范围内其他想要的电压?
要输出不同的模拟电压就要用到PWM,通过改变IO口输出的方波的占空比,从而获得使用数字信号模拟成的模拟电压信号。电压是以一种脉冲序列被加到模拟负载上去的,接通时是高电平1,断开时是低电平0。接通时直流供电输出,断开时直流供电断开。通过对接通和断开时间的控制,理论上可以输出任意不大于最大电压值5V的模拟电压。占空比为50%那就是高电平时间一半,低电平时间一半。在一定的频率下,就可以得到模拟的2.5V输出电压。那么20%的占空比,得到的电压就是1V,如下图所示
在这里插入图片描述
关于上边以一点的解释需要用到“面积等效原理”:冲量相等而形状不同的窄脉冲施加在惯性环节上时,其效果基本相同。换而言之,如若干组的脉冲图形在单位时间内的积分相同,平均功率相同,则电路中可以看作相同脉冲。

在单片机内的工作机制

在单片机内部是如何实现输出PWM波形的呢?
得益于输出比较模式,OC(Output Compare)输出比较,输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形,每个高级定时器和通用定时器都拥有四个输出比较通道;高级定时器的前三个通道额外拥有死区生成和互补输出的功能
在这里插入图片描述
当该模式工作时,CNT计数器与捕获比较寄存器(CCR)进行比较,得出的结果传到输出控制单元,最后通过TIM_CHx输出到GPIO引脚上。
输出比较通道(通用)
在这里插入图片描述
上图对应定时器的输出控制电路,让我们来看一下输出比较的工作流向,当CNT>CCR1或CNT=CCR1时,就会给输出模式控制器,输出模式控制器就会改变它输出OC1ref(Reference-参考信号)的高低电平,高低电平可以发送至主模式控制器或者下方的极性选择,在这里可以选择是否将高低电平翻转,然后到输出使能电路(选择是否输出),最后给到通道引脚。(ETRF是定时器的一个小功能一般不用)
输出模式控制器的工作模式
在这里插入图片描述
实现PWM的基本结构
在这里插入图片描述
从上图我们能看到在单片机内部完成PWM需要时基单元(PSC、ARR、CNT)、输出比较单元(CCR、输出模式控制器、输出使能)、GPIO引脚。
一、RCC开启时钟、把需要用到的TIM外设和GPIO外设的时钟打开;
二、配置时基单元、包括时钟源选择;
三、配置输出比较单元、包括CCR的值、输出比较模式、极性选择、输出使能参数;
四、配置GPIO,将PWM对应的GPIO口,初始化为复用推挽输出的配置(参考引脚定义表);
五、启动计数器、输出PWM;
进行PWM参数控制的一些库函数可以从stm32f10x_tim.h文件中查找。

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);//初始化输出比较单元
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);//高级定时器中输出PWM需要调用此函数使能主输出
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);//了解即可
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);//配置快速使能
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);//修改输出极性
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);//单独修改输出使能函数
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);
void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);//选择输出比较模式
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);//单独修改CCR寄存器的值,均较为重要
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

进行PWM设置需要的参数计算
在这里插入图片描述
在这里插入图片描述
上图为高级定时器的捕获/比较通道输出部分,可以从图中看出,比通用定时器的捕获/比较通道多出了一个死区发生器和一条输出通道,当该部分工作时,通常会在外部来连接推挽电路,并且两条输出通道的高低电平应该相反,这样的话在工作时可能会出现两条通道都导通的情况,为了避免这种情况设置了死区发生器,通过添加延迟来实现两条通道的高低电平不相同。

PWM的应用与代码实现

呼吸灯

人眼对80Hz以上的刷新频率毫无闪烁感,平时看到的LED灯的频率大于50Hz时,则人眼产生视觉暂留效果,无法看到闪烁,而误以为LED常亮。将频率调高时人眼将看不到闪烁,占空比越大则模拟电压越大,LED越亮,反之占空比越小LED越暗。所以,在频率一定时,通过改变占空比来调节ED灯的亮度,使其达到呼吸灯的效果。
呼吸灯代码实现

#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "PWM.h"


uint8_t i;
int main(void)
{
    OLED_Init();
    PWM_Init();
    while(1)
    {
     for(i=0;i<=100;i++)
        {
        PWM_SetComparel(i);
        Delay_ms(10);
        }
     for(i=0;i<=100;i++)
        {
        PWM_SetComparel(100-i);
        Delay_ms(10);
        }
    }

PWM外设函数

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    TIM_InternalClockConfig(TIM2);              ///添加内部时钟,可加可不加,默认使用
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef    GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    
    TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStructure;      ///定时器的初始化
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period=100-1;///ARR设定
    TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;///预分频设置--psc
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
    
    
    TIM_OCInitTypeDef   TIM_OCInitStruct;
    TIM_OCStructInit(&TIM_OCInitStruct);//给所有赋初始值
    
    
    TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;
    TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
    TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
    TIM_OCInitStruct.TIM_Pulse=0;//设置CCR寄存器的值
    TIM_OC1Init(TIM2,&TIM_OCInitStruct);
    
    TIM_Cmd(TIM2,ENABLE);运行控制?


}

void PWM_SetComparel(uint16_t Compare)
{
   TIM_SetCompare1(TIM2,Compare);
}

控制电机转速

通过调整占空比来改变输出电压来实现对电机转速的调节。
直流电机的工作原理:赋给电机输出端引脚高电平驱动电机,输出端为高电平,电机转动,以逐渐递增的趋势提速,当高电平突然降为低电平时,电机由于内部有防止电流突变的电感,不会立即停止,会保持这原有的转速,以此往复,电机的转速就取决于周期内输出的平均电压值。实质上,PWM调速是将电机处于一种“似停非停”,“似全速转动又非全速转动”的状态,那么在该周期的平均速度就是我们占空比调出来的速度。在电机控制中,电压越大,电机转速越快,而通过PWM输出不同的模拟电压,便可以使电机达到不同的输出转速。

PWM对舵机的控制

舵机的控制在固定频率下,调整不同的占空比来控制舵机不同的转角。
假设舵机的频率为50HZ,需要输入周期为20ms左右的时基脉冲,而脉冲的高电平部分一般为0.5ms-2.5ms范围,来控制舵机不同的转角。
500-2500us的PWM高电平部分对应控制180度舵机的0-180度。
以180度角度伺服为例,那么对应的控制关系是这样的:
0.5ms-------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;

关于引脚重映射

在这里插入图片描述
这篇学习笔记是在学习江协科技的视频时做的学习笔记,作为小白来讲,学长的讲解深入浅出,对我很受用,在此特别感谢。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值