STM32定时器输出PWM原理深入解析

概念+代码

文章目录

  • 一、输出比较
  • 二、PWM原理
  • 三、输出PWM
  • 1.PWM初始化
  • 2.输出指定频率PWM波
  • 3.输出占空比可变的PWM波

  • 一、输出比较

    OC(Output Compare)输出比较
    输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
    每个高级定时器和通用定时器都拥有4个输出比较通道
    高级定时器的前3个通道额外拥有死区生成和互补输出的功能

    二、PWM原理

    PWM(Pulse Width Modulation)脉冲宽度调制
    在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域
    PWM参数:
    频率 = 1 / TS
    占空比 = TON / TS(高电平占总时间的比率),如占空比为50%,高电平=5V,低电平=0V,则模拟电压为2.5V.
    分辨率 = 占空比变化步距,即精度。

    PWM基本结构:


    当CNT计数小于CCR时,置高电平,当CNT大于CCR时,置低电平,当CNT=ARR时触发事件,计数值归零,又开始新的一轮周期,这样就可以不断的输出PWM信号。因此,可以看出,CCR值的设置与占空比密切相关。
    PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1)
    CK_PSC是预分频频率,一般是系统频率。PSC是分频系数,ARR是自动重装载寄存器最大计数值。
    PWM占空比: Duty = CCR / (ARR + 1)
    CCR是输出比较输出PWM的一个限定比较值。
    PWM分辨率: Reso = 1 / (ARR + 1)

    三、输出PWM

    以正点原子PWM实验为例:使用TIM3的CH2通道,在PB5端口输出PWM波。

    1.PWM初始化

    void TIM3_PWM_Init(u16 arr,u16 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
        //溢出时间time=(arr+1)*(psc+1)/144000000
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = 1; //设置时钟分割: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_OCInitStructure.TIM_Pulse = 50;
        TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
    
        TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
        TIM_Cmd(TIM3, ENABLE);  //使能TIM3
    }
    

    这里最重要的是:
    1.该函数的参数为 arr 和 psc,分别表示自动重载寄存器的值和预分频系数。根据这两个参数,可以计算出 PWM 的频率和占空比。

    2.在函数中,首先使能了定时器 TIM3 和 GPIOB 外设的时钟,以及 GPIO 的复用功能模块时钟。然后,通过 GPIO_PinRemapConfig 函数将 TIM3_CH2 信号映射到 GPIOB.5 引脚上。
    这里有一个问题:为什么要配置AFIO复用功能模块时钟?如下图:

    可以看到:PB5的默认复用功能是I2C1_SMBA/ SPI3_MOSI,I2S3_SD,而其重定义功能才是TIM3_CH2,所以不能简单直接的复用它,必须要配置重映射。

    3.通过 TIM_OCInitTypeDef 结构体对 TIM3 的通道 2 进行初始化,选择定时器模式为 PWM2,使能比较输出,设置输出极性为高电平,设置占空比为 50%。
    最后,通过 TIM_OC2PreloadConfig 函数使能 TIM3 在 CCR2 上的预装载寄存器,并通过TIM_Cmd 函数使能 TIM3。

    2.输出指定频率PWM波

       TIM3_Int_Init(5999,0);
       //TIM3_PWM_Init(5999,0);//不分频。PWM 频率=96000/(5999+1)=16KHz
    

    参考PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1),这里我的芯片系统频率是96MHz,对应CK_PSC,ARR是计数值,PSC是预分频值,代入公式,得:频率F=16000Hz=16KHz。
    因此,这个代码输出了一个频率固定为16KHz的PWM波。

    3.输出占空比可变的PWM波

    TIM3_Int_Init(5999,0);
    u16 pulse=400;
    TIM_SetCompare2(TIM3,pulse);
    

    对于定时器 TIM3,CCR2 寄存器的取值范围是 0 到 ARR,即比较寄存器的值不能大于自动重载寄存器的值。因此,在设置占空比时,输入的占空比值需要通过计算转换为相应的比较寄存器的值。也就是说,pulse的值只能在0-5999之间设置,并且注意,这里调用的函数是TIM_SetCompare2()函数,是比较寄存器CCR2对应通道2,如果是ch3,则要调用TIM_SetCompare3()函数。如此,便实现了修改PWM波的占空比。

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32定时器输出PWM原理深入解析

    发表评论