【STM32】STM32之timer1产生PWM(互补通道)

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


一、简介

本文介绍STM32系列如何使用timer1的第TIM1_CH2N通道(PB14)产生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、在进行本文步骤前,请先 阅读 以下博文:
1)《STM32之timer3产生PWM》:http://blog.csdn.net/feilusia/article/details/53634882

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


五、基础知识

1、什么是互补通道?
答: TIM1_CH2N 通道就是TIM1_CH2的互补通道,它们的波形完全反向。有些引脚上是互补通道,我们同样可用于PWM输出。

六、实验步骤

1、编写并添加PWM驱动

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

//******************************************************************************                            
//name:             GUA_Timer1_PWM.c               
//introduce:        定时器1的PWM驱动        
//author:           甜甜的大香瓜                     
//email:            897503845@qq.com         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14      
//******************************************************************************    
#include "stm32f10x.h" 
#include "GUA_Timer1_PWM.h"  
  
/*********************宏定义************************/    
//引脚宏  
#define GUA_TIMER1_PWM_PORT             GPIOB  
#define GUA_TIMER1_PWM_PIN              GPIO_Pin_14  
#define GUA_TIMER1_PWM_MODE             GPIO_Mode_AF_PP 
#define GUA_TIMER1_PWM_GPIO_CLOCK				RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO 
#define GUA_TIMER1_PWM_PERIPH_CLOCK			RCC_APB2Periph_TIM1 

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

/*********************内部函数声明************************/  
static void GUA_Timer1_PWM_IO_Init(void);
static void GUA_Timer1_PWM_Config_Init(GUA_U16 nGUA_Timer3_PWM_Prescaler);

//******************************************************************************              
//name:             GUA_Timer1_PWM_IO_Init             
//introduce:        定时器1的PWM的IO初始化           
//parameter:        none                   
//return:           none           
//author:           甜甜的大香瓜                   
//email:            897503845@qq.com       
//QQ group          香瓜单片机之STM8/STM32(164311667)                    
//changetime:       2017.01.14                      
//******************************************************************************  
static void GUA_Timer1_PWM_IO_Init(void)  
{      
	//IO结构体  
	GPIO_InitTypeDef GPIO_InitStructure;  

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

	//IO初始化
	GPIO_InitStructure.GPIO_Pin = GUA_TIMER1_PWM_PIN;
	GPIO_InitStructure.GPIO_Mode = GUA_TIMER1_PWM_MODE;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GUA_TIMER1_PWM_PORT, &GPIO_InitStructure);		
}

//******************************************************************************              
//name:             GUA_Timer1_PWM_Config_Init             
//introduce:        定时器1的PWM的配置初始化           
//parameter:        nGUA_Timer1_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_Timer1_PWM_Config_Init(GUA_U16 nGUA_Timer1_PWM_Prescaler)  
{      
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
	TIM_OCInitTypeDef  TIM_OCInitStructure;  
  
	//时钟配置
	RCC_APB2PeriphClockCmd(GUA_TIMER1_PWM_PERIPH_CLOCK, ENABLE);  
	
	//定时器配置
	TIM_TimeBaseStructure.TIM_Period = GUA_TIMER1_PWM_PERIOD;								//设置计数值  
	TIM_TimeBaseStructure.TIM_Prescaler = nGUA_Timer1_PWM_Prescaler - 1;		//设置预分频
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;														//设置时钟分频系数:不分频  
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;							//向上计数溢出模式  
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);  
	
	//PWM配置
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;												//配置为PWM模式1(小于计数值时为有效电平)    
	//TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;					//比较输出使能 
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;					//比较输出的互补输出使能 		
	TIM_OCInitStructure.TIM_Pulse = 0;																			//设置待装入捕获比较寄存器的脉冲值  
	//TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;							//当定时器计数值小于CCR1时为低电平  
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;							//当定时器计数值小于CCR1时互补输出为低电平 
	//TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;						//当MOE=0时,如果实现了OC*N,则死区后OC*=1	
	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;						//当MOE=0时,如果实现了OC*N,则死区后OC*=1
	TIM_OC2Init(TIM1, &TIM_OCInitStructure);																//使能通道2      

	//默认关闭PWM		
	GUA_Timer1_PWM_Status(GUA_TIMER1_PWM_STATUS_OFF);	
	
	//使能	
	TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);												//CH2预装载使能  
	TIM_ARRPreloadConfig(TIM1, ENABLE);																			//使能TIM1重载寄存器ARR  	
	TIM_Cmd(TIM1, ENABLE);																									//使能定时器1  
}

//******************************************************************************          
//name:             GUA_Timer1_PWM_Status          
//introduce:        定时器1的PWM开关      
//parameter:        nGUA_Timer1_PWM_Status: GUA_TIMER1_PWM_STATUS_ON or GUA_TIMER1_PWM_STATUS_OFF        
//return:           none        
//author:           甜甜的大香瓜               
//email:            897503845@qq.com                  
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14                       
//******************************************************************************    
void GUA_Timer1_PWM_Status(GUA_U8 nGUA_Timer1_PWM_Status)  
{  
  //打开PWM  
  if(nGUA_Timer1_PWM_Status == GUA_TIMER1_PWM_STATUS_ON)  
  {   
		TIM_SetCounter(TIM1, 0);		
		TIM_CtrlPWMOutputs(TIM1, ENABLE);			
  }  
  //关闭PWM 
  else  
  {  
		TIM_CtrlPWMOutputs(TIM1, DISABLE);	 	
  }  
}  
  
//******************************************************************************          
//name:             GUA_Timer1_PWM_SetDutyCycle          
//introduce:        定时器1的PWM设置占空比      
//parameter:        nGUA_Timer1_PWM_DutyCycle: 0~100为0%~100%        
//return:           none        
//author:           甜甜的大香瓜               
//email:            897503845@qq.com                  
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14                         
//******************************************************************************    
void GUA_Timer1_PWM_SetDutyCycle(GUA_U8 nGUA_Timer1_PWM_DutyCycle)  
{  
  TIM_SetCompare2(TIM1, GUA_TIMER1_PWM_PERIOD*nGUA_Timer1_PWM_DutyCycle/100);   
}  
  
//******************************************************************************          
//name:             GUA_Timer1_PWM_Init          
//introduce:        定时器1的PWM初始化       
//parameter:        nGUA_Timer1_PWM_Prescaler:预分频数值,如100则表示1000000/100=10000Hz        
//return:           none        
//author:           甜甜的大香瓜               
//email:            897503845@qq.com                  
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14                        
//******************************************************************************    
void GUA_Timer1_PWM_Init(GUA_U16 nGUA_Timer1_PWM_Prescaler)   
{  	
	//初始化IO  
	GUA_Timer1_PWM_IO_Init();  

	//初始化定时器配置 
	GUA_Timer1_PWM_Config_Init(nGUA_Timer1_PWM_Prescaler);
}  

2) 编写驱动头文件 GUA_Timer1_PWM.h (存放在“ …… \HARDWARE ”)

//******************************************************************************                            
//name:             GUA_Timer1_PWM.h               
//introduce:        定时器1的PWM驱动的头文件        
//author:           甜甜的大香瓜                     
//email:            897503845@qq.com         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2017.01.14     
//******************************************************************************    
#ifndef _GUA_TIMER1_PWM_H_  
#define _GUA_TIMER1_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_TIMER1_PWM_STATUS_ON                0       //PWM打开  
#define GUA_TIMER1_PWM_STATUS_OFF               1       //PWM关闭  

/*********************外部函数声明************************/   
void GUA_Timer1_PWM_Status(GUA_U8 nGUA_Timer1_PWM_Status);  
void GUA_Timer1_PWM_SetDutyCycle(GUA_U8 nGUA_Timer1_PWM_DutyCycle);  
void GUA_Timer1_PWM_Init(GUA_U16 nGUA_Timer1_PWM_Prescaler);  
  
#endif  

3) 工程中添加GUA_Timer1_PWM.c



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



2、添加库的驱动

1)添加库的驱动文件



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

#include "stm32f10x_tim.h" 

3、在应用层中调用

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

#include "GUA_Timer1_PWM.h" 

2) 添加初始化代码(main.c的main函数中)

	GUA_Timer1_PWM_Init(26);														//设置PWM频率为1000000/26=38000Hz=38KHz  
	GUA_Timer1_PWM_SetDutyCycle(50);										//设置PWM占空比为50%  
	GUA_Timer1_PWM_Status(GUA_TIMER3_PWM_STATUS_ON);    //使能PWM   

七、注意事项
1、在初始化PWM的配置之后,需要调用使能PWM的函数才会有PWM的波形。
2、PWM会有死区。
3、如果仅使用PWM的互补通道,记得不要把另一个普通的PWM通道也初始化了。

八、实验结果

设置仿真断点在测试代码,仿真并全速运行至断点,单步执行测试代码后的PB14波形如下图:
1、使能PWM


因此,实验成功。


  • 5
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32 HAL库中,使用TIM(定时器)模块实现互补输出,可以在同一时钟周期内生成两个相互补PWM信号。以下是一些步骤: 1. 初始化TIM模块,并配置TIM的参数,如时钟源、时钟分频系数、计数模式等。 2. 配置TIM通道1和通道2的输出模式为PWM模式,并使能通道1和通道2的互补输出。 3. 配置TIM通道1和通道2的占空比,可以使用HAL库提供的函数如HAL_TIM_PWM_Start()和HAL_TIM_PWM_Stop()等。 下面是一个简单的示例代码: ```c #include "stm32f4xx_hal.h" TIM_HandleTypeDef htim; void TIM_PWM_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim.Instance = TIM2; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 2000; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 1000; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); sConfigOC.OCMode = TIM_OCMODE_PWM2; sConfigOC.Pulse = 1000; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&htim, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim, TIM_CHANNEL_2); } ``` 在上面的示例中,我们初始化了TIM2模块,并配置了通道1和通道2为PWM模式,使能了互补输出。然后,我们将占空比设置为50%(即通道1和通道2的脉冲宽度均为1000),并启动PWM输出。 需要注意的是,互补输出需要使用一个定时器的两个通道,因此必须确保定时器的两个通道不被其他外设占用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值