寒假学习之stm32(8)-----定时器输出PWM

既然我们要用定时器输出PWM波,那么我们不妨做一个小的PWM知识的介绍
(wiki中对pwm的介绍):
https://zh.wikipedia.org/wiki/%E8%84%88%E8%A1%9D%E5%AF%AC%E5%BA%A6%E8%AA%BF%E8%AE%8A

PWM应用:

1.伺服:
脉冲宽度调制可以用于控制伺服机构。

2. 电信

寒假学习之stm32(8)-----定时器输出PWM_第1张图片

时间信号不一定要被包含脉冲宽度调制的传递上,事实上资料的领先端可以被当成一个计时器使用,如果有一个小的偏移量被加在资料值之上,去避免资料值有一个长度为零的脉冲波。

寒假学习之stm32(8)-----定时器输出PWM_第2张图片

3. 能量的传递
脉冲宽度调制可以被用来控制对于一个载流子能量传递的多寡,而不会产生由阻抗所造成的线性能量传递损失。此方法所需要付出的代价是,载流子所流失的能量并非一个常数且是不连续的(如降压式变换器),载流子上传递的能量也不是连续的。然而,由于载流子可能是具有高频电感性的,这时就必须要外加一个被动的电子滤波器,让这些脉冲波变为平滑且能复原平均的模拟波型,能量流入载流子才会是连续的。而从供应端流出的能量则不是连续的,因此大部分情况下需要额外的能量储存空间。(比方说在一个电路下,一个电容会吸收储存于供应端电感的能量。)

—————————————————————————————————————————————————————————————————————————————

STM32下的PWM输出

1. PWM每个定时器有四个通道可选(除了基本定时器)
通道:定时器产生的PWM波的输出引脚

定时器种类 位数 计数器模式 产生DMA请求 捕获/比较通道 互补输出 应用场景
高级定时器(TIM1,TIM8) 16 向上/向下/向上向下 可以 4 带死区控制盒紧急刹车,可应用于PWM电机控制
通用定时器(TIM2~5) 16 向上,向下,向上/下 可以 4 通用。定时计数,PWM输出,输入捕获,输出比较
基本定时器(TIM6,TIM7) 16 向上/向下/向上向下 可以 0 主要应用于驱动DAC

而且,有的通道还支持端口的重映射功能,参照中文参考手册可以很有效的看出这些通道的配置:

这里写图片描述

寒假学习之stm32(8)-----定时器输出PWM_第3张图片

寒假学习之stm32(8)-----定时器输出PWM_第4张图片

寒假学习之stm32(8)-----定时器输出PWM_第5张图片

寒假学习之stm32(8)-----定时器输出PWM_第6张图片

PS:TIM4,TIM5不存在部分重映射


· 看完了这些端口重映射我们可以大致总结一下,在PWM的输出中,每一个通用/高级定时器总是有着四个端口可以选择,在考虑的PCB布线的合理性的选择中,我们可以使用端口重映射让单片机产生的PWM波输出到其他的引脚去,然而,这写引脚是固定的,所以,要通过查找中文参考手册来查表选择

· 端口重映射的时候,作为GPIO输出应该选择 GPIO_Mode_AF_PP,复用推挽输出模式

· 端口复用所用到的函数:
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //其中PartialRemap表示部分重映射,我们可以通过查找相应的库函数来找出这些功能的定义

2. PWM的输出模式,占空比详解

寒假学习之stm32(8)-----定时器输出PWM_第7张图片

我们这里选取的计数模式:TIM_CounterMode_Up; //TIM向上计数模式
CNT:表示计数的数量
ARR:寄存器设置的计数上界
CCRx:表示比较的值

1. 周期:还记得我们上一讲讲解的 Tout=(arr+1)(psc+1)/Tclk
        也就是说,在psc确定的情况下,一个pwm的周期(Tout)是由arr来决定的,通常,我们要让变化显得更加平滑,就要把psc设置为0,以方便让频率达到36Mhz

2. 占空比: 由图看出,CRRx(x是PWM通道序号)
           TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器

3.   PWM的输出模式(TIM_OCMode_PWM2): 
            a. PWM模式1:CNTCCRx通道为有效,否则为无效

寒假学习之stm32(8)-----定时器输出PWM_第8张图片

PWM的输出配置:

1.  使能时钟及IO口
    GPIO : RCC_APB2PeriphClockCmd();
    定时器:RCC_APB1PeirphClockCmd();

2.  GPIO初始化:GPIO_Init()

3. *端口的重映射
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    GPIO_PinRemap(GPIO_PartialRemap_TIM3,ENABLE);

4.  初始化定时器
    TIM_TimeBaseInit();

5. 初始化比较定参数:
    TIM_OC2Init();

6.  使能预装载值寄存器:
    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); 

7.  使能定时器:
    TIM_Cmd();

8.  改变占空比:
    TIM_SetCompareX();//X是通道的序号
#include "led.h"
#include "delay.h"
#include "sys.h"






//TIM3 PWM部分初始化 
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void PWM3_init(short arr,short psc)
{ 
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;


    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);    //使能定时器3时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟

    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5    

   //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形    GPIOB.5
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO

   //初始化TIM3
    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

    //初始化TIM3 Channel2 PWM模式     
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
    TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器

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


}



 int main(void)
 {      
    u16 led0pwmval=0;
    u8 dir=1;   
    delay_init();            //延时函数初始化    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    led_init();              //LED端口初始化
    PWM3_init(899,0);    //不分频。PWM频率=72000000/900=80Khz
    while(1)
    {
        delay_ms(10);    
        if(dir)led0pwmval++;
        else led0pwmval--;

        if(led0pwmval>300)dir=0;
        if(led0pwmval==0)dir=1;                                      
        TIM_SetCompare2(TIM3,led0pwmval);          
    }    
 }

你可能感兴趣的:(stm32)