使用STM32F103输出PWM波形

一、PWM的介绍

PWM(脉冲宽度调制)控制技术
通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值)。
PWM 控制的基本原理
冲量相等而开头不同的窄脉冲加在具有惯性的环节上时,其效果基本相同。其中冲量指窄脉冲的面积;效果相同指环节输出响应波形基本相同。
参考例子
在这里插入图片描述
用一系列等幅不等宽的脉冲来代替一个正弦半波

:
其划分方式是将正弦半波分成 N 等分,可看成 N 个彼此相连的脉冲序列,宽度相等,但幅值不等;接下来使用矩形脉冲代替,而各个矩形脉冲等幅,不等宽,中点与脉冲序列重合,脉冲宽度按正弦规律变化,脉冲的总面积(冲量)与正弦半波相等。这个脉冲波形被称为 SPWM 波形,是一种极其典型的PWM波形。

二、了解定时器实现PWM波形输出

1.PWM工作过程
在这里插入图片描述
寄存器的值从0开始到ARR值的过程中,当其比CCRx中的值小的时候,输出低电平(0),当其值大于CCRx值时,输出高电平(1)。从图中可以看出周期是由ARR决定的,跟定时器的时钟有关系,而占空比则跟CCRx有关。
2.PWM的通道
在这里插入图片描述
①CCR1寄存器:捕获/比较值寄存器:设置比较值;
②CCMR1寄存器:OC1M[2:0]位:对于PWM方式下,用于设置PWM模式1或者PWM模式2;
③CCER寄存器:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。
④CCER寄存器:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。

PWM输出的模式区别
通过设置寄存器TIMx_CCMR1的OC1M[2:0]位来确定PWM的输出模式:
PWM模式1:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
PWM模式2:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
注意:并未说明1就表示有效电平

3.定时器3的输出通道引脚
TIM3_CH1:PA6,完全重映像PC6
TIM3_CH2:PA7,完全重映像PC7
TIM3_CH3:PB0,完全重映像PC8
TIM3_CH4:PB1,完全重映像PC9

更多详细信息,请参考STM32芯片手册。

三、相关配置

1.捕获/比较模式寄存器1(TIMx_CCMR1)
在PWM输出模式下,确定PWM的模式、使能相应的预装载寄存器等操作。
2.捕获/比较使能寄存器(TIMx_CCER)
在PWM输出模式下,确定PWM的输出极性和输出使能。
3.捕获/比较寄存器1(TIMx_CCR1)
在PWM输出模式下,确定比较的值。

具体配置方式,请参考STM32的中文手册

四、实现输出PWM

1.定时器TIM1的初始化

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

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能
	                                                                     	

   //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1,引脚是PA8
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

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

 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

  TIM_CtrlPWMOutputs(TIM1,ENABLE);	//MOE 主输出使能	

	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH1预装载使能	 
	
	TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM1, ENABLE);  //使能TIM1
 
   
}

2.main函数

int main(void)
 {
    
    	
	u16 led0pwmval=0;    
	u8 dir=1;	
	delay_init();	    	 //延时函数初始化	  
	LED_Init();		  	//初始化与LED连接的硬件接口
	TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz 
   	while(1)
	{
    
    
 		delay_ms(10);	 
		if(dir)led0pwmval++;
		else led0pwmval--;	 
 		if(led0pwmval>300)dir=0;
		if(led0pwmval==0)dir=1;	   					 
		TIM_SetCompare1(TIM1,led0pwmval);//设置不同的占空比	   
	} 
}

3.最终效果
烧录后,可以看到LED灯由亮变暗的过程。
利用keil仿真查看输出的波形如下
在这里插入图片描述

从图中可以发现该过程的占空比是逐渐在发送变化。

通过示波器可以观察到其波形如下
在这里插入图片描述

五、小结

通过输出的波形,可以认为输出的占空比是发生变化。当然也可以利用库函数提供的函数,实现改变频率。仿真得到的波形,不像示波器给出的那么明显,实现动态改变。

六、参考资料

1.【STM32】通用定时器的PWM输出(实例:PWM输出)
2.STM32学习笔记一一PWM 输出
3.KEIL里如何实现仿真 查看输出波形
4.PWM输出实验

猜你喜欢

转载自blog.csdn.net/qq_43279579/article/details/111941341