STM32(7)-定时器输出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波的占空比。

猜你喜欢

转载自blog.csdn.net/qq_53092944/article/details/130703311