【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

联系方式:897503845@qq.com

香瓜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:            897503845@qq.com         
//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:            897503845@qq.com       
//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:            897503845@qq.com       
//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:            897503845@qq.com                  
//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:            897503845@qq.com                  
//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:            897503845@qq.com                  
//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:            897503845@qq.com         
//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


4)在MDK设置中添加驱动源文件路径


2、添加库的驱动

1)添加库的驱动文件



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

初始化时设置了26us的周期,启动PWM前设置了50%的占空比。因此使能PWM之后直接输出了波形。
低电平13us、高电平13us、一个周期26us,因此占空比为13/26=50%。

2、设置30%占空比

低电平7.75us、高电平18.25us、一个周期26us,因此占空比为7.75/26=29.8%。

3、设置60%占空比

低电平15.75us、高电平10.25us、一个周期26us,因此占空比为15.75/26=60.6%。

4、设置0%占空比

0%时一直为高电平。

5、设置100%占空比


100%时可见低电平有许多0.25us的毛刺脉冲,这是PWM的死区
0~100%的占空比中一定会有一个死区,解决死区脉冲的方法:在死区时配置为IO置位为相应的电平。
PS:香瓜在本PWM驱动中没有解决此问题,因为项目中只使用到50%的占空比。

6、关闭PWM

关闭PWM后,在代码中有设置为IO拉高,因此抓到的波形为高电平。

7、设置50%占空比+使能PWM

再次使能PWM之前,先配置了50%的占空比。
低电平13us、高电平13us、一个周期26us,因此占空比为13/26=50%。

因此,实验成功。

### STM32F103C8T6 PB3 Pin Configuration and Functionality In the context of STM32 microcontrollers, each GPIO pin can be configured to serve multiple functions depending on the requirements of the application. For the STM32F103C8T6 specifically, the PB3 pin is a general-purpose input/output (GPIO) pin that supports various alternate functions. The PB3 pin can operate as an analog input or digital I/O with several possible configurations such as push-pull output, open-drain output, or input mode with pull-up/pull-down resistors enabled[^4]. Additionally, this pin may also support specific peripheral functionalities when set to its alternate function modes. These include but are not limited to: - **Timer Channels**: It could act as one of the channels for timers like TIM2_CH2. - **USART/UART Signals**: Depending upon how it's defined within your project setup files through appropriate register settings via software libraries provided by STMicroelectronics or custom code written directly manipulating registers at low level assembly language instructions if necessary[^5]. To configure the functionality of PB3 in any given role mentioned above requires setting up corresponding bits inside certain control/status registers associated particularly with Port B which includes MODER(GPIOx_MODER), OTYPER(GPIOx_OTYPER), OSPEEDR(GPIOx_OSPEEDR), PUPDR(GPIOx_PUPDR). Here’s an example demonstrating configuring PB3 as Output Push-Pull Mode using HAL Library from STMCubeMX tool-generated initialization codes: ```c __HAL_RCC_GPIOB_CLK_ENABLE(); // Enable clock access to GPIOB port // Configure PB3 as OUTPUT PUSH_PULL MODE WITH MEDIUM SPEED AND NO INTERNAL RESISTORS ENABLED GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL ; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; HAL_GPIO_Init(GPIOB,&GPIO_InitStruct); ``` When considering power management techniques involving sleep modes where execution halts until some event occurs causing wake-up conditions met then resuming operation afterward without losing state information about variables etc., remember what was stated earlier regarding WFI/WFE instruction usage leading into entering these lower-power states while preserving context so once interrupted appropriately handled accordingly before continuing normal processing flow again after exiting them successfully restored back fully operational status quo ante bellum manner speaking metaphorically here obviously since no actual warfare involved just electronics stuff happening behind scenes silently yet effectively doing their jobs well designed architectures indeed they do!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甜甜的大香瓜

谢谢你的支持^_^

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值