【STM32】STM32之timer3产生PWM

本篇博文最后修改时间:2017年01月14日,23:50。


一、简介

本文介绍STM32系列如何使用timer3的第3通道(PB0)产生38K频率的PWM。


二、实验平台

库版本:STM32F10x_StdPeriph_Lib_V3.5.0

编译软件:MDK4.53

硬件平台:STM32开发板(主芯片stm32f103c8t6)

仿真器:JLINK


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:[email protected]

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、 实验前提
1、在进行本文步骤前,请先 阅读 以下博文:

2、在进行本文步骤前,请先 实现以下博文:
暂无


五、基础知识

暂无

六、实验步骤

1、编写并添加PWM驱动

1)编写驱动GUA_Timer3_PWM.c(存放在“……\HARDWARE”)

//******************************************************************************                            
//name:             GUA_Timer3_PWM.c               
//introduce:        定时器3的PWM驱动        
//author:           甜甜的大香瓜                     
//email:            [email protected]         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14      
//******************************************************************************    
#include "stm32f10x.h" 
#include "GUA_Timer3_PWM.h"  
  
/*********************宏定义************************/    
//引脚宏  
#define GUA_TIMER3_PWM_PORT             GPIOB  
#define GUA_TIMER3_PWM_PIN              GPIO_Pin_0  
#define GUA_TIMER3_PWM_MODE             GPIO_Mode_AF_PP 
#define GUA_TIMER3_PWM_GPIO_CLOCK				RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO 
#define GUA_TIMER3_PWM_PERIPH_CLOCK			RCC_APB1Periph_TIM3  

//计数值  
#define GUA_TIMER3_PWM_PERIOD						(72 - 1)  

/*********************内部函数声明************************/   
static void GUA_Timer3_PWM_IO_Init(void);
static void GUA_Timer3_PWM_Config_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler);

//******************************************************************************              
//name:             GUA_Timer3_PWM_IO_Init             
//introduce:        定时器3的PWM的IO初始化           
//parameter:        none                   
//return:           none           
//author:           甜甜的大香瓜                   
//email:            [email protected]       
//QQ group          香瓜单片机之STM8/STM32(164311667)                    
//changetime:       2017.01.14                        
//******************************************************************************  
static void GUA_Timer3_PWM_IO_Init(void)  
{      
	//IO结构体  
	GPIO_InitTypeDef GPIO_InitStructure;  

	//时钟配置 
	RCC_APB2PeriphClockCmd(GUA_TIMER3_PWM_GPIO_CLOCK, ENABLE);	

	//IO初始化
	GPIO_InitStructure.GPIO_Pin = GUA_TIMER3_PWM_PIN;
	GPIO_InitStructure.GPIO_Mode = GUA_TIMER3_PWM_MODE;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GUA_TIMER3_PWM_PORT, &GPIO_InitStructure);				
}

//******************************************************************************              
//name:             GUA_Timer3_PWM_Config_Init             
//introduce:        定时器3的PWM的配置初始化           
//parameter:        nGUA_Timer3_PWM_Prescaler:预分频数值,如100则表示1000000/100=10000Hz 
//return:           none           
//author:           甜甜的大香瓜                   
//email:            [email protected]       
//QQ group          香瓜单片机之STM8/STM32(164311667)                    
//changetime:       2017.01.14                        
//******************************************************************************  
static void GUA_Timer3_PWM_Config_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler)  
{      
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
	TIM_OCInitTypeDef  TIM_OCInitStructure;  
  
	//时钟配置
	RCC_APB1PeriphClockCmd(GUA_TIMER3_PWM_PERIPH_CLOCK, ENABLE);  
	
	//定时器配置
	TIM_TimeBaseStructure.TIM_Period = GUA_TIMER3_PWM_PERIOD;								//设置计数值  
	TIM_TimeBaseStructure.TIM_Prescaler = nGUA_Timer3_PWM_Prescaler - 1;		//设置预分频 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;														//设置时钟分频系数:不分频  
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;							//向上计数溢出模式  
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  
	
	//PWM配置
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;												//配置为PWM模式1(小于计数值时为有效电平)  
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;						//比较输出使能                
	TIM_OCInitStructure.TIM_Pulse = 0;																			//设置待装入捕获比较寄存器的脉冲值  
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;								//有效电平为低电平  
	TIM_OC3Init(TIM3, &TIM_OCInitStructure);																//使能通道3      

	//默认关闭PWM		
	GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_OFF);	
	
	//使能	
	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);												//CH3预装载使能  
	TIM_ARRPreloadConfig(TIM3, ENABLE);																			//使能TIM3重载寄存器ARR  	
	TIM_Cmd(TIM3, ENABLE);																									//使能定时器3  
}

//******************************************************************************          
//name:             GUA_Timer3_PWM_Status          
//introduce:        定时器3的PWM开关      
//parameter:        nGUA_Timer3_PWM_Status: GUA_TIMER3_PWM_STATUS_ON or GUA_TIMER3_PWM_STATUS_OFF        
//return:           none        
//author:           甜甜的大香瓜               
//email:            [email protected]                  
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14                        
//******************************************************************************    
void GUA_Timer3_PWM_Status(GUA_U8 nGUA_Timer3_PWM_Status)  
{  
  //打开PWM  
  if(nGUA_Timer3_PWM_Status == GUA_TIMER3_PWM_STATUS_ON)  
  {   
		TIM_SetCounter(TIM3, 0);		
		TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Enable);		
  }  
  //关闭PWM
  else  
  {  
		TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Disable);			 	
  }  
}  
  
//******************************************************************************          
//name:             GUA_Timer3_PWM_SetDutyCycle          
//introduce:        定时器3的PWM设置占空比      
//parameter:        nGUA_Timer3_PWM_DutyCycle: 0~100为0%~100%        
//return:           none        
//author:           甜甜的大香瓜               
//email:            [email protected]                  
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14                         
//******************************************************************************    
void GUA_Timer3_PWM_SetDutyCycle(GUA_U8 nGUA_Timer3_PWM_DutyCycle)  
{  
  TIM_SetCompare3(TIM3, GUA_TIMER3_PWM_PERIOD*nGUA_Timer3_PWM_DutyCycle/100);   
}  
  
//******************************************************************************          
//name:             GUA_Timer3_PWM_Init          
//introduce:        定时器3的PWM初始化       
//parameter:        nGUA_Timer3_PWM_Prescaler:预分频数值,如100则表示1000000/100=10000Hz        
//return:           none        
//author:           甜甜的大香瓜               
//email:            [email protected]                  
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14                         
//******************************************************************************    
void GUA_Timer3_PWM_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler)   
{  	
	//初始化IO  
	GUA_Timer3_PWM_IO_Init();  

	//初始化定时器配置 
	GUA_Timer3_PWM_Config_Init(nGUA_Timer3_PWM_Prescaler);
}  
初始化后PWM默认是关闭的。

2)编写驱动头文件GUA_Timer3_PWM.h(存放在“……\HARDWARE”)
//******************************************************************************                            
//name:             GUA_Timer3_PWM.h               
//introduce:        定时器3的PWM驱动的头文件        
//author:           甜甜的大香瓜                     
//email:            [email protected]         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14      
//******************************************************************************    
#ifndef _GUA_TIMER3_PWM_H_  
#define _GUA_TIMER3_PWM_H_  
   
/*********************宏定义************************/
//类型宏
#ifndef GUA_U8        
typedef unsigned char GUA_U8;        
#endif    

#ifndef GUA_8        
typedef signed char GUA_8;        
#endif      
      
#ifndef GUA_U16        
typedef unsigned short GUA_U16;        
#endif 

#ifndef GUA_16        
typedef signed short GUA_16;        
#endif         
      
#ifndef GUA_U32        
typedef unsigned long GUA_U32;        
#endif 

#ifndef GUA_32        
typedef signed long GUA_32;       
#endif

#ifndef GUA_U64    
typedef unsigned long long GUA_U64;  
#endif

#ifndef GUA_64    
typedef signed long long GUA_64;  
#endif

//PWM的开关宏  
#define GUA_TIMER3_PWM_STATUS_ON                0       //PWM打开  
#define GUA_TIMER3_PWM_STATUS_OFF               1       //PWM关闭  

/*********************外部函数声明************************/   
void GUA_Timer3_PWM_Status(GUA_U8 nGUA_Timer3_PWM_Status);  
void GUA_Timer3_PWM_SetDutyCycle(GUA_U8 nGUA_Timer3_PWM_DutyCycle);  
void GUA_Timer3_PWM_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler);  
  
#endif  

3) 工程中添加GUA_Timer3_PWM.c
【STM32】STM32之timer3产生PWM_第1张图片

4)在MDK设置中添加驱动源文件路径
【STM32】STM32之timer3产生PWM_第2张图片

2、添加库的驱动

1)添加库的驱动文件

【STM32】STM32之timer3产生PWM_第3张图片

2)添加库的驱动头文件(stm32f10x_conf.h 中)
#include "stm32f10x_tim.h"

3、在应用层中调用

1)添加驱动头文件(main.c中)

#include "GUA_Timer3_PWM.h"

2) 添加测试代码(main.c的main函数中)
	GUA_Timer3_PWM_Init(26);													//设置PWM频率为1000000/26=38000Hz=38KHz
	GUA_Timer3_PWM_SetDutyCycle(50);									//设置PWM占空比为50%
	GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_ON);	//使能PWM	
	
	GUA_Timer3_PWM_SetDutyCycle(30);									//设置PWM占空比为30%  
	GUA_Timer3_PWM_SetDutyCycle(60);									//设置PWM占空比为60%  
	GUA_Timer3_PWM_SetDutyCycle(0);										//设置PWM占空比为0%  
	GUA_Timer3_PWM_SetDutyCycle(100);									//设置PWM占空比为100% 	
	
	GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_OFF);	//停止PWM		
	GUA_Timer3_PWM_SetDutyCycle(50);									//设置PWM占空比为50%
	GUA_Timer3_PWM_Status(GUA_TIMER3_PWM_STATUS_ON);	//使能PWM

七、注意事项
1、在初始化PWM的配置之后,需要调用使能PWM的函数才会有PWM的波形。
2、PWM会有死区。

八、实验结果
设置仿真断点在测试代码,仿真并全速运行至断点,单步执行测试代码后的PB0波形如下图:
1、使能PWM
【STM32】STM32之timer3产生PWM_第4张图片
初始化时设置了26us的周期,启动PWM前设置了50%的占空比。因此使能PWM之后直接输出了波形。
低电平13us、高电平13us、一个周期26us,因此占空比为13/26=50%。

2、设置30%占空比
【STM32】STM32之timer3产生PWM_第5张图片
低电平7.75us、高电平18.25us、一个周期26us,因此占空比为7.75/26=29.8%。

3、设置60%占空比
【STM32】STM32之timer3产生PWM_第6张图片
低电平15.75us、高电平10.25us、一个周期26us,因此占空比为15.75/26=60.6%。

4、设置0%占空比
【STM32】STM32之timer3产生PWM_第7张图片
0%时一直为高电平。

5、设置100%占空比
【STM32】STM32之timer3产生PWM_第8张图片
【STM32】STM32之timer3产生PWM_第9张图片
100%时可见低电平有许多0.25us的毛刺脉冲,这是PWM的死区
0~100%的占空比中一定会有一个死区,解决死区脉冲的方法:在死区时配置为IO置位为相应的电平。
PS:香瓜在本PWM驱动中没有解决此问题,因为项目中只使用到50%的占空比。

6、关闭PWM
【STM32】STM32之timer3产生PWM_第10张图片
关闭PWM后,在代码中有设置为IO拉高,因此抓到的波形为高电平。

7、设置50%占空比+使能PWM
【STM32】STM32之timer3产生PWM_第11张图片
再次使能PWM之前,先配置了50%的占空比。
低电平13us、高电平13us、一个周期26us,因此占空比为13/26=50%。

因此,实验成功。

你可能感兴趣的:(STM32)