STM32笔记 (十二)利用高级定时器产生PWM

PWM原理简介

脉冲宽度调制(PWM),是英文“Pulse Width Modulation” 的缩写,简称脉宽调制,是利用
微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽
度的控制,脉宽调制也叫占空比
在这里插入图片描述
这个图中阐述了利用高级定时器产生PWM的原理,其中

  • ARR是自动重装载寄存器(TIMx_ARR)的值
  • CNT是定时器计数器当前的值
  • CCRx是捕获/比较寄存器 x(TIMx_CCRx)的值
    每经过一次定时器时钟周期就会+1,通过设置定时器的输出模式,可以实现,当计数器的值CNT,小于设定的CCRx的值时,输出低电平大于时就输出高电平

PWM波的占空比和周期

在这里插入图片描述
可以通过改变CCRx的值来改变占空比,改变ARR的值来改变周期

  • CCRx 》占空比
  • ARR 》周期,也就是溢出时间
    计算公式为:Tout= ((arr+1)*(psc+1))/Tclk;
    Tclk为时钟周期,psc为时钟分频因子

PWM波形时间计算

向上计数时,如果此时设置的模式为当计数器的值小于CCRx的值时,输出高电平,也是PWM1模式(可以通过TIMx_CCMR1的OCxM位来配置PWM模式)

  • 假设psc分频设置成71,arr的值设置成4999,由公式Tout= ((arr+1)*(psc+1))/Tclk得Tout=5ms
  • 这时候我们又能知道计数器每一次计数的时间为1us
    (相当于把公式Tout= ((arr+1)*(psc+1))/Tclk里的arr的值取0所算出来的时间)
  • 如果要使PWM输出高电平的时间为2.5ms的话,经过计算这时候CCRx的值就要设置成2500

PWM程序

编程步骤:

在这里插入图片描述代码:

#include "stm32f10x.h"
#include "bsp_systick.h"

void TIM8_PWM_Config(uint16_t Arr, uint16_t Psc)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);  //使能TIM8的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能 GPIO 的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

	//配置GPIO
	//设置该引脚为复用输出功能,输出 TIM8 CH1 的 PWM 脉冲波形
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	//初始化TIM8
	TIM_TimeBaseStructure.TIM_Period = Arr;						//设置自动重装载的值
	TIM_TimeBaseStructure.TIM_Prescaler = Psc;					//设置预分频系数
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数(累加)计数模式
	//至此,定时器就能正常工作了,此时的溢出时间也就是周期为:Tout= ((arr+1)*(psc+1))/Tclk 这里的Tclk为72MHz

	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟的分频因子,仅对电路的稳定性有影响
	TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);			//初始化TIM8

	//初始化 TIM8 Channel2 PWM 模式
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // 选择PWM模式2,
	/*在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为
    有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,
    否则为无效电平。*/
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;	  //设置极性,输出有效电平为:高电平
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能
	TIM_OC1Init(TIM8, &TIM_OCInitStructure);					  //初始化外设 TIM8 OC1

	TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable); //使能预装载寄存器

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

	TIM_CtrlPWMOutputs(TIM8, ENABLE); //主输出使能,当使用的是通用定时器时,这句不需要
}

int main(void)
{
	uint16_t val=0;//必须16位
	uint8_t dir=1;
	TIM8_PWM_Config(999,71);

	while (1)
	{
		delay_ms(10);
		if(dir)
			val++;
		else
			val--;
		if(val>399)
			dir=0;
		if(val<=0)
			dir=1;
		TIM_SetCompare1(TIM8,val);//设置的是CCRx的值,也就是设置占空比
	}
}

原创文章 12 获赞 0 访问量 1084

猜你喜欢

转载自blog.csdn.net/zcy_cyril/article/details/106095968