pwm波_pwm波形 - CSDN
  • PWM的原理和PWM波的产生

    千次阅读 2020-05-20 16:12:10
    如图,正弦波是输入信号,三角波是载波信号,在两者的交点之间输出高电平,因为三角波周期一定,所以输出的就是周期一定,占空比改变的PWM波,电路的实现需要一个三角波发生器,一个电压比较器就能实现。 3.SPWM ...

    1.定义

    脉冲宽度调制(Pulse width modulation,PWM),简单来说就是通过调节方波占空比达到代替其他波形的效果。因为是数字信号,不易受干扰。

    2.电路实现

    在这里插入图片描述
    如图,正弦波是输入信号,三角波是载波信号,在两者的交点之间输出高电平,因为三角波周期一定,所以输出的就是周期一定,占空比改变的PWM波,电路的实现需要一个三角波发生器,一个电压比较器就能实现。

    3.SPWM

    SPWM:正弦波脉宽调制。
    SPWM波形定义是把正弦半波分成N等分,每等分和横坐标包围的面积用和它面积相等的等高矩形代替,可得到N个矩形脉冲,如下:
    在这里插入图片描述
    在SPWM法交-直-交变频调速中,SPWM法相比六拍阶梯波能输出更接近正弦波的电压,使高次谐波成分减少,且电网功率因数接近1,大大提高系统性能。

    展开全文
  • PWM波的介绍

    万次阅读 多人点赞 2018-07-16 09:28:39
    PWM(Pulse Width Modulation)控制——脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值).PWM控制技术在逆变电路中应用最广,应用的逆变电路绝大部分是PWM型,PWM控制...

    PWM(Pulse Width Modulation)控制——脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值).PWM控制技术在逆变电路中应用最广,应用的逆变电路绝大部分是PWM型,PWM控制技术正是有赖于在逆 变电路中的应用,才确定了它在电力电子技术中的重要地位。

    1 PWM相关概念

    占空比:就是输出的PWM中,高电平保持的时间 与 该PWM的时钟周期的时间 之比

    如,一个PWM的频率是1000Hz,那么它的时钟周期就是1ms,就是1000us,如果高电平出现的时间是200us,那么低电平的时间肯定是800us,那么占空比就是200:1000,也就是说PWM的占空比就是1:5。

    分辨率也就是占空比最小能达到多少,如8位的PWM,理论的分辨率就是1:255(单斜率), 16位的的PWM理论就是1:65535(单斜率)。

    频率就是这样的,如16位的PWM,它的分辨率达到了1:65535,要达到这个分辨率,T/C就必须从0计数到65535才能达到,如果计数从0计到80之后又从0开始计到80.......,那么它的分辨率最小就是1:80了,但是,它也快了,也就是说PWM的输出频率高了。

    双斜率 / 单斜率

    假设一个PWM从0计数到80,之后又从0计数到80.......   这个就是单斜率。

    假设一个PWM从0计数到80,之后是从80计数到0.......   这个就是双斜率。

    可见,双斜率的计数时间多了一倍,所以输出的PWM频率就慢了一半,但是分辨率却是1:(80+80) =1:160,就是提高了一倍。

    假设PWM是单斜率,设定最高计数是80,我们再设定一个比较值是10,那么T/C从0计数到10时(这时计数器还是一直往上计数,直到计数到设定值80),单片机就会根据你的设定,控制某个IO口在这个时候是输出1还是输出0还是端口取反,这样,就是PWM的最基本的原理了。


    2 PWM控制的基本原理
    理论基础:
    冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同。冲量指窄脉冲的面积。效果基本相同,是指环节的输出响应波形基本相同。低频段非常接近,仅在高频段略有差异。

                                         图1 形状不同而冲量相同的各种窄脉冲
    面积等效原理:
    分别将如图1所示的电压窄脉冲加在一阶惯性环节(R-L电路)上,如图2a所示。其输出电流i(t)对不同窄脉冲时的响应波形如图2b所示。从波形可以看出,在i(t)的上升段,i(t)的形状也略有不同,但其下降段则几乎完全相同。脉冲越窄,各i(t)响应波形的差异也越小。如果周期性地施加上述脉冲,则响应i(t)也是周期性的。用傅里叶级数分解后将可看出,各i(t)在低频段的特性将非常接近,仅在高频段有所不同。

                                      图2 冲量相同的各种窄脉冲的响应波形
    用一系列等幅不等宽的脉冲来代替一个正弦半波,正弦半波N等分,看成N个相连的脉冲序列,宽度相等,但幅值不等;用矩形脉冲代替,等幅,不等宽,中点重合,面积(冲量)相等,宽度按正弦规律变化。SPWM波形——脉冲宽度按正弦规律变化而和正弦波等效的PWM波形。

                                    图3 用PWM波代替正弦半波
     

    要改变等效输出正弦波幅值,按同一比例改变各脉冲宽度即可。 PWM电流波: 电流型逆变电路进行PWM控制,得到的就是PWM电流波。 PWM波形可等效的各种波形: 直流斩波电路:等效直流波形
    SPWM波:等效正弦波形,还可以等效成其他所需波形,如等效所需非正弦交流波形等,其基本原理和SPWM控制相同,也基于等效面积原理。
    模拟信号的值可以连续变化,其时间和幅度的分辨率都没有限制。9V电池就是一种模拟器件,因为它的输出电压并不精确地等于9V,而是随时间发生变化,并可取任何实数值。与此类似,从电池吸收的电流也不限定在一组可能的取值范围之内。模拟信号与数字信号的区别在于后者的取值通常只能属于预先确定的可能取值集合之内,例如在{0V, 5V}这一集合中取值。
    模拟电压和电流可直接用来进行控制,如对汽车收音机的音量进行控制。在简单的模拟收音机中,音量旋钮被连接到一个可变电阻。拧动旋钮时,电阻值变大或变小;流经这个电阻的电流也随之增加或减少,从而改变了驱动扬声器的电流值,使音量相应变大或变小。与收音机一样,模拟电路的输出与输入成线性比例。
    尽管模拟控制看起来可能直观而简单,但它并不总是非常经济或可行的。其中一点就是,模拟电路容易随时间漂移,因而难以调节。能够解决这个问题的精密模拟电路可能非常庞大、笨重(如老式的家庭立体声设备)和昂贵。模拟电路还有可能严重发热,其功耗相对于工作元件两端电压与电流的乘积成正比。模拟电路还可能对噪声很敏感,任何扰动或噪声都肯定会改变电流值的大小。
    通过以数字方式控制模拟电路,可以大幅度降低系统的成本和功耗。此外,许多微控制器和DSP已经在芯片上包含了PWM控制器,这使数字控制的实现变得更加容易了。

     简而言之,PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。


           图1显示了三种不同的PWM信号。图1a是一个占空比为10%的PWM输出,即在信号周期中,10%的时间通,其余90%的时间断。图1b和图1c显示的分别是占空比为50%和90%的PWM输出。这三种PWM输出编码的分别是强度为满度值的10%、50%和90%的三种不同模拟信号值。例如,假设供电电源为9V,占空比为10%,则对应的是一个幅度为0.9V的模拟信号。

           图2是一个可以使用PWM进行驱动的简单电路。图中使用9V电池来给一个白炽灯泡供电。如果将连接电池和灯泡的开关闭合50ms,灯泡在这段时间中将得到9V供电。如果在下一个50ms中将开关断开,灯泡得到的供电将为0V。如果在1秒钟内将此过程重复10次,灯泡将会点亮并象连接到了一个4.5V电池(9V的50%)上一样。这种情况下,占空比为50%,调制频率为10Hz。

           大多数负载(无论是电感性负载还是电容性负载)需要的调制频率高于10Hz。设想一下如果灯泡先接通5秒再断开5秒,然后再接通、再断开……。占空比仍然是50%,但灯泡在头5秒钟内将点亮,在下一个5秒钟内将熄灭。要让灯泡取得4.5V电压的供电效果,通断循环周期与负载对开关状态变化的响应时间相比必须足够短。要想取得调光灯(但保持点亮)的效果,必须提高调制频率。在其他PWM应用场合也有同样的要求。通常调制频率为1kHz到200kHz之间。

    展开全文
  • STM32F103单片机输出相位可调PWM波

    千次阅读 2020-06-05 10:08:59
    通常使用的是PWM模式,可以通过PWM功能可以生成频率和占空比可调的方信号,有时候需要生成初始相位可调的方PWM功能就就不能满足要求了。可以通过输出比较模式来实现。 输出比较模式是将计数器CNT的值和捕获...

        STM32定时器功能如下

    通常使用的是PWM模式,可以通过PWM功能可以生成频率和占空比可调的方波信号,有时候需要生成初始相位可调的方波,PWM功能就就不能满足要求了。可以通过输出比较模式来实现。

    输出比较模式是将计数器CNT的值和捕获比较寄存器CCR的对比,当CNT值等于CCR的值时,翻转输出电平。

    通过捕获比较寄存器CCMR模式设置位的描述可以看出,输出比较模式只有当 CCR = CNT时,输出电平才会翻转。而PWM模式下 CNT < CCR 时输出一个电平,CNT > CCR时输出相反的电平。

    通过一个示意图来看看PWM输出模式

    上图中是PWM输出的示意图,可以看出CNT的值从变化范围是 0---ARR,之间,CNT的值在CCR值左边时输出一个电平,CNT值在CCR右边时,输出相反电平。这样改变CCR值就可以改变输出PWM的占空比。

    下面在看看输出比较模式

    输出比较模式下不关心CNT比 CCR值大还是小,只关心CNT和CCR值什么时候相等,两个值相等时,就翻转输出电平。在PWM模式下,CNT值从0增加到ARR一个周期内输出电平有两次变化,而在输出比较模式下时CNT值从0增加到ARR一个周期内输出电平只有一次变化。所以输出比较模式下,定时器输出方波的频率为PWM模式下定时器输出方波频率的一半。

    下面就看看代码如何实现

    // arr 自动装载值  psc 分频系数
    void TIM3_CMP_Init( u16 arr, u16 psc )
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        TIM_OCInitTypeDef TIM_OCInitStructure;
    
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );	//使能定时器3时钟  36M 
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB , ENABLE );	//使能GPIOC时钟
    
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        //初始化TIM3
        TIM_TimeBaseInitStructure.TIM_Period = arr;
        TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
        TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStructure );
    
        //初始化TIM3 比较 模式  输出比较翻转触发模式(当计数值与比较/捕获寄存器值相同时,翻转输出引脚的电平)   
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    
        TIM_OC1Init( TIM3, &TIM_OCInitStructure );
        TIM_OC2Init( TIM3, &TIM_OCInitStructure );
        TIM_OC3Init( TIM3, &TIM_OCInitStructure );
        TIM_OC4Init( TIM3, &TIM_OCInitStructure );
    
        TIM_OC1PreloadConfig( TIM3, TIM_OCPreload_Enable );
        TIM_OC2PreloadConfig( TIM3, TIM_OCPreload_Enable );
        TIM_OC3PreloadConfig( TIM3, TIM_OCPreload_Enable );
        TIM_OC4PreloadConfig( TIM3, TIM_OCPreload_Enable );
    
        //使能TIM3
        TIM_Cmd( TIM3, ENABLE );
    }
    
    

    这里用的是定时器3,定时器3的4个通道全部设置为输出比较模式。

    定时器初始化代码,输出比较模式设置方法和PWM模式设置方法只有模式设置这一行代码不同。

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;

    将输出模式由TIM_OCMode_PWM1 改为  TIM_OCMode_Toggle 就可以了。

    下面看主函数代码

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h"
    #include "pwm.h"
    // LED0  PA8  LED1 PD2
    int main( void )
    {
        u16 led_pwm_val = 0;
        u8 dir = 1;
        delay_init();       //延时函数初始化
        NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );
        LED_Init();
    
        LED0 = 1;
        LED1 = 1;
        delay_ms( 500 );
        LED0 = 0;
        LED1 = 0;
        //比较输出模式下:  ARR 决定输出频率  CCRx 决定每个通道的初始相位
        //PWM模式:		   ARR 决定输出频率  CCRx 决定输出 的高电平时长
    
        //比较翻转模式,一个周期只翻转一次,所以频率为 1/2
        TIM3_CMP_Init( 1000 - 1, 36 - 1 );			//1K
        TIM_SetCompare1( TIM3, 0 );
        TIM_SetCompare2( TIM3, 200 );
        TIM_SetCompare3( TIM3, 400 );
        TIM_SetCompare4( TIM3, 600 );
        while( 1 )
        {
            delay_ms( 200 );
            LED0 = !LED0;
        }
    }

            定时器3时钟为72MHz,36分频后为2MHz,自动装载值为1000-1,输出频率为 2M / 1000 = 2KHz。输出比较模式的频率要在减一半,所以输出方波信号频率为 2K / 2 = 1KHz.

            下来分别设置4个通道输出的初始相位,通道1相位设置为0,通道2延迟1/5周期,通道3延迟2/5周期,通道4延迟3/5周期。

    4个通道的输出频率都是1KHz,周期为1000us。

    通过输出波形可以看出来,起始相位依次滞后,通道1为0起点的话,通道2滞后100us,通道3滞后200us,通道4滞后300us。

    上面计算的通道2滞后1/5周期,周期为1000us,1/5周期应该为200us,实际测出来为100us,说明相位计算的理论值也要减半。

    这样利用定时器输出比较模式,通过设置改变定时器CCR寄存器的值,就可以控制输出方波的起始相位了。

    展开全文
  • STM32之PWM波

    千次阅读 多人点赞 2018-07-28 11:10:08
    说起PWM波,做过智能小车的人肯定都很清楚了,其实他就是一种脉宽调制。在智能小车上,我们一般用PWM波来控制小车的速度,通过控制方波中高低电平的比例,来达到控制小车转速的目的。而32的芯片他提供了专门的PWM波...

    说起PWM波,做过智能小车的人肯定都很清楚了,其实他就是一种脉宽调制。在智能小车上,我们一般用PWM波来控制小车的速度,通过控制方波中高低电平的比例,来达到控制小车转速的目的。而32的芯片他提供了专门的PWM波输出通道,我们只需要进行相应的配置就可以调用32的PWM波的输出,今天我们就用定时器3的通道2产生PWM波来控制LED灯的亮度,以实现呼吸灯的效果。

    我先来讲一下32的PWM波输出的大概工作原理。首先我们还是需要用定时器,(其实用的是计数器,因为定时器的本质就是计数器)假如说我们让计数器从0开始计数,一直计到100,然后我们在0到100中间再设定一个数,假如说我们设定为30,那么当计数器中的计数值小于30的时候,PWM输出的引脚会输出一个电平(具体是高电平还是低电平,是可以设置的),然后如果计数器的值大于了30,那么PWM波的输出引脚会输出和刚才相反的电平,然后计数到100之后,再返回到0,重新开始下一轮计数,然后我们通过控制中间这个数值(就是刚才那个例子中的30),我们就可以控制PWM波的占空比了,然后通过控制计数的最大值(就是刚才那个例子中100)就可以控制PWM波输出的周期了。这就是32中PWM波输出的基本原理。

    今天我们还是用到了LED和定时器,按照老套路还是先建两个空白的文件,分别命名为time.c和time.h,然后根据前两篇博客的步骤给添加到工程中去,具体步骤在这我就不再赘述了。这次我们把所有的初始化函数都放在time.c文件里面,也就是说不用再建led.c和led.h文件了。
    首先我们对定时器3进行基本的配置,代码如下

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//注意结构体的声明必须在函数的开头
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period=arr;
    TIM_TimeBaseStructure.TIM_Prescaler=psc;
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

    这些代码和上篇博客中的一样,我就不再多讲,不懂的可以去翻看上篇博客(利用定时器中断控制LED)。

    然后我们来配置定时器3通道2的PWM输出的工作方式。代码如下

        //配置TIM3 Channel2 PWM
        TIM_OCInitTypeDef TIM_OCInitStructure;
        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
        TIM_OC2Init(TIM3,&TIM_OCInitStructure);//注意此处的函数名字以及函数的入口参数

    大家看,这还是结构体,32里面基本所有的配置都是使用的结构体。我们首先来看这个结构体中的第一个成员变量 TIM_OCMode,这个变量是设置PWM的工作模式,关于PWM的工作模式有好几种,如下

    #define TIM_OCMode_Timing                  ((uint16_t)0x0000)
    #define TIM_OCMode_Active                  ((uint16_t)0x0010)
    #define TIM_OCMode_Inactive                ((uint16_t)0x0020)
    #define TIM_OCMode_Toggle                  ((uint16_t)0x0030)
    #define TIM_OCMode_PWM1                    ((uint16_t)0x0060)
    #define TIM_OCMode_PWM2                    ((uint16_t)0x0070)

    我们这里选择模式2,其他的模式我也不清楚,我知道模式2和模式1的区别就是,他俩的有效电平是相反的,关于有效电平的概念我一会就会提到。

    关于PWM输出
    PWM Mode 1:
    向上计数:TIMx_CNT<TIMx_CCR1 active ;TIMx_CNT>=TIMx_CCR1 inactive
    向下计数:TIMx_CNT>TIMx_CCR1 inactive ;TIMx_CNT<=TIMx_CCR1 active
    PWM Mode 2:
    向上计数:TIMx_CNT<TIMx_CCR1 inactive ;TIMx_CNT>=TIMx_CCR1 active
    向下计数:TIMx_CNT>TIMx_CCR1 active ;TIMx_CNT<=TIMx_CCR1 inactive

    这里我们选择模式2,那么代码就是

    TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;

    然后这个结构体的第二个成员就是设置输出极性,也就是有效电平。假如说我们设置输出极性(有效电平)是高电平,对于模式2来说,当计数器的值小于你设定的阈值(上面那个例子中的30)的时候,PWM波对应的输出引脚就会输出无效电平,也就是低电平,当计数器的值大于你设定的阈值的时候,PWM波就会输出有效电平,也就是高电平;而对于模式1来说,则正好相反,当计数器的值小于你设定的阈值(上面那个例子中的30)的时候,PWM波对应的输出引脚就会输出有效电平,也就是高电平,当计数器的值大于你设定的阈值的时候,PWM波就会输出无效电平,也就是低电平;
    这里我们选择输出极性(有效电平)为高电平,代码如下

    TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;

    然后这个结构体的第三个成员就是选择输出状态是使能或者不使能,我们选择使能,代码如下

    TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;

    到这就把PWM波的工作方式配置完了,然后就是把这些成员利用下面这个函数给导入到相应的寄存器中,代码如下

    TIM_OC2Init(TIM3,&TIM_OCInitStructure);//注意此处的函数名字以及函数的入口参数

    在这我们需要注意一下这个函数的名字TIM_OC2Init,它里面的2就代表着配置的是定时器的第二个通道,然后第一个参数就代表着配置的是定时器3,第二个参数就是刚才配置的结构体,总的来说就是配置了定时器3的第二个通道,如果要用到定时器3的其他通道,则把这个函数名字中的2改成对应的通道数就行。
    定时器配置完了,接下来我们就要开始配置这次所用到的GPIO口了,代码如下

    GPIO_InitTypeDef GPIO_InitStructure;//注意结构体声明必须放在函数的开头
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);

    程序的第一行同样是定义一个结构体,然后第二行是开启GPIOB的时钟,然后第三行是开启复用功能的时钟,关于复用功能我简单说一下。我们今天想实现的是用定时器3的通道2来控制LED的亮度,在我使用的开发板上,今天用到的LED是接在PB5上,然而定时器3的通道2所产生的的PWM波却不是通过PB5引脚来输出的,所以说我们就需要开启32的复用功能,我么可以把定时器3的通道2 的PWM波输出给映射到PB5引脚上,这就可以实现让PWM波从PB5引脚上输出了,(重映射的引脚不是随意的,只能映射到固定的引脚)关于复用功能具体的大家可以百度查询。
    然后程序的第四行就是配置GPIO口的工作模式,我们这里选择复用推挽输出模式。然后程序的第五、六、七行就不多说了。

    这些都配置完之后,我们要再调用一个函数,如下

        //把TIM3部分重映射到PB5
        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);

    这个函数就是实现了把定时器3给重映射到了PB5引脚上。

    然后我们用到了定时器3,所以就需要开启定时器3的时钟,代码如下

        //使能TIM3时钟
        TIM_Cmd(TIM3,ENABLE);

    我们今天没有用到定时器中断,所以就不用再使能定时器中断的时钟了。
    到此为止,我们time.c文件的程序都已经写好了,完整代码如下

    #include "time.h"
    void time3_PWM_init(u16 arr,u16 psc)
    {
        //配置TIM3
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//注意结构体的声明必须在函数的开头
        TIM_OCInitTypeDef TIM_OCInitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
        TIM_TimeBaseStructure.TIM_Period=arr;
        TIM_TimeBaseStructure.TIM_Prescaler=psc;
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
    
        //配置TIM3 Channel2 PWM
    
        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
        TIM_OC2Init(TIM3,&TIM_OCInitStructure);//注意此处的函数名字以及函数的入口参数
    
        //配置GPIO口,并且设置成复用功能
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);
    
        //把TIM3部分重映射到PB5
        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);
    
        //使能TIM3时钟
        TIM_Cmd(TIM3,ENABLE);
    }
    
    
    

    接下来开始写time.h文件,还是只需要把time.c文件中所定义的函数给声明一下就行,代码如下

    #ifndef __TIME_H
    #define __TIME_H
    
    #include "sys.h"
    
    void time3_PWM_init(u16 arr,u16 psc);
    
    
    #endif
    
    

    然后我们就开始写main.c文件中的程序了。先把全部代码贴出来

    #include "sys.h"
    #include "delay.h"
    #include "time.h"
    
    int main(void)
    {
        u16 led0pwm=0;
        u8 dir=1;
        delay_init();
        time3_PWM_init(899,0);
        while(1)
        {
            delay_ms(10);
            if(dir)
                led0pwm++;
            else if(!dir)
                led0pwm--;
            if(led0pwm>=300)
                dir=0;
            else if(led0pwm==0)
                dir=1;
            TIM_SetCompare2(TIM3,led0pwm);
        }
    }
    
    
    

    在main.c文件的刚开始我们还是先写需要调用的头文件,因为我们今天主函数里面用到了延时函数,所以要添加头文件”delay.h”,调用的头文件如下

    #include "sys.h"
    #include "delay.h"
    #include "time.h"

    然后我们在主函数中定义了两个变量:led0pwm和dir,其中led0pwm是当做PWM波输出的那个阈值(就是前面举的例子中的那个30)的,然后变量dir是用来控制led0pwm的增长方向,以便实现呼吸灯的效果。然后我们还用到了另外一个重要的函数

    TIM_SetCompare2(TIM3,led0pwm);

    这个函数有两个入口参数,第一个参数就是选择对哪个定时器进行操作,第二个参数就是设置PWM波输出的那个阈值,我们在主函数中每隔10ms对led0pwm改变一次数值,也就是PWM波的那个阈值一直的在变化(每隔10ms变化一次),而每一个阈值对应的LED的发光亮度都会不一样,对于我们今天设定的工作方式来说,阈值越大,LED亮度越大,阈值越小,LED亮度越小。(因为我们刚才配置的PWM波工作模式为模式2,然后输出有效电平是高电平,而对于本人使用的开发板来说,给PB5引脚高电平,LED熄灭,给PB5引脚低电平,LED点亮,所以说当计数器的值小于led0pwm的时候,PWM波输出为无效电平,也就是低电平,这个时候LED点亮,而当计数器的值大于led0pwm的时候,PWM波输出有效电平,也就是高电平,这个时候LED熄灭,所以说我们的led0pwm的值越小,PWM波输出低电平的时间就越短,LED的亮度就越小,led0pwm的值越大,PWM波输出低电平的时间就越长,LED的亮度就越大)
    综上所述,一直改变led0pwm的值,就可以一直改变LED的亮度,LED就会实现从暗到亮,然后从亮到暗,然后再从暗到亮,这样一直循环下去,就实现了呼吸灯的效果。
    至此,本次用定时器3输出PWM波控制LED灯的实验就结束了,把代码烧录到开发板中,就可以看到正点原子精英版的开发板上DS0的亮度一直的在变化。
    注意主函数中的那一条延时语句 delay_ms(10) 不能省略,否则我们将看不到LED的亮度变化,即我们不能让led0pwm的值变化的太快。

    展开全文
  • PWM波详解

    千次阅读 2019-03-11 23:21:54
    PWM波能做什么? 智能小车的电机控制:我们可以利用pwm来控制我们的智能小车的车速 机器人:给“机器人关节”舵机周期一定pwm波就可以控制舵机的转动角度 呼吸灯:输入不同的pwm波就可以达到明暗渐明渐暗的效果 ...
  • 2019.4.1: 调试超声波传感器时候,最先使用的是中断来判断是方法配置成功,结果一直报错,才发现是忘记添加中断配置库文件了…愚人节快乐…具体内容...PWM的脉宽、周期准不准确,差了几毫秒或者几微妙是为什么,还...
  • 比较器应用三:占空比可调的PWM波

    千次阅读 2019-01-20 13:13:49
    本文章产生占空比可调的PWM波主要原理是直流波和三角波通过比较器比较,从而比较器输出端输出PWM波,通过图1来说明。 假设三角波接入比较器的负输入端,直流波接入比较器的正输入端,即当直流波大于三角波时,比较...
  • PWM波发生器

    千次阅读 2018-06-07 10:27:32
    PWM波发生器赶着做了一波本人单片机课程的实验考试题目,配合proteus仿真。因为仿真用了许多芯片,还挺有意思的,所以分享一下。PWM波发生器一、 任务在硬件电路PWM.DSN中实现P1.7输出PWM波。周期T=100ms,初始...
  • 实现的时候使用TIM1的CH1和TIM2的CH1,使用TIM15的中断,每100个ms来一次中断,在中断服务函数中以中断的方式打开PWM波的输出,在输出一个PWM波之后会进入PWM的中断服务函数,在中断服务函数中计数PWM波的个数,当...
  • 通过两个不同的程序分别实现指定频率的PWM波和占空比可以呈周期变化的PWM波。 1.PWM波产生原理 简述 PWM,完整的名称应该是脉冲宽度调制,是一个由定时器产生、由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定...
  • STM32——TIM死区互补PWM波输出

    千次阅读 热门讨论 2018-10-22 16:44:53
    pwm波的输出实验老早之前就学了,一直拖到现在才写,,,。由于之前接触过32的高级定时器所以是先从死区pwm波开始学的,后面才学的pwm波。其实会发出死区pwm波了也就会发pwm波了。在学习32的某个功能时要先去看32...
  • 本次实验将采用定时器2的通道2产生两路频率和占空比均可调的PWM信号,然后使用定时器3的通道1来捕获其中的一路PWM波的频率和占空比。 1、首先来看下产生PWM波的程序,也就是和上篇博客是一样的,只不过换了个定时器...
  • 测量PWM波频率PWM模式输入基本原理实验(PWM输入部分代码) PWM模式输入 该方式是在STM32输入捕获模式基础上扩展升级的功能,可以测量PWM波的频率及占空比,需要多加一个输入捕获寄存器 基本原理 (1)实现PWM输入...
  • 使用定时器来产生PWM波大家应该都很熟悉,但是如何使用定时器产生频率可调的PWM波呢?这就需要使用定时器的输出比较翻转模式TIM_OCMode_Toggle。 先大概介绍一些这个模式是如何工作的: 输出比较翻转,顾名思义,...
  • 2、PWM(Pulse Width Modulation)波是脉宽可调波,假如一个机器周期是10 MHz,PWM波周期为5 MHz,那么占空比就可以有0,50%,100%三种情况。假如PWM波周期为5 kHz,那么有占空比不为0的情况下,最小占空比可以为1/...
  • stm32的TIM1定时器四路PWM波输出-舵机控制 因为我做的一个小机械臂中需要四路的等周期PWM波,所以在研究了STM32的例程之后改了一下程序,实现了四路PWM波输出。只是没有用到函数封装,大家不习惯的可以复制粘贴重新...
  • 原创哦,CSDN首发 用51单片机的两定时器产生更精准的正弦PWM波,还带有Proteus仿真文件
  • stm32 pwm波工作原理

    千次阅读 2018-08-15 17:16:24
    20180812带女朋友搬家新家条件不好,累到女朋友了,让女朋友受苦了,特此明志:每天学习,明年这个时候(20190812)让女朋友住上... pwm波简介:脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称...
  • 一,动态更改PWM波频率:1,定时器时钟使能(主,从)2,正常配置产生PWM波。3,使能事件更新。TIM-&gt;CR1的UDIS=04,使能影子寄存器TIM-&gt;CR1的ARPE=1这样就可以直接更改TIM-&gt;ARR和CCR的值,当...
  • 良好的通过50M分频实现PWM波的产生,波形良好可调。
1 2 3 4 5 ... 20
收藏数 8,563
精华内容 3,425
关键字:

pwm波