PWM互补输出,以及死区时间计算

本文基于野火例程进行解说

实验内容

本次实验输出一对互补的pwm波,且进行死区时间的计算说明。

代码

互补输出对应的定时器初始化代码:
bsp_advance_tim.c

/**
  ******************************************************************************
  * @file    bsp_advance_tim.c
  * @author  STMicroelectronics
  * @version V1.0
  * @date    2015-xx-xx
  * @brief   高级控制定时器互补输出范例
  ******************************************************************************
  * @attention
  *
  * 实验平台:野火  STM32 F407 开发板  
  * 论坛    :http://www.firebbs.cn
  * 淘宝    :http://firestm32.taobao.com
  *
  ******************************************************************************
  */
  
#include "./tim/bsp_advance_tim.h"

TIM_HandleTypeDef  TIM_TimeBaseStructure;
TIM_OC_InitTypeDef TIM_OCInitStructure;

__IO uint16_t ChannelPulse = 500;

/**
  * @brief  配置TIM复用输出PWM时用到的I/O
  * @param  无
  * @retval 无
  */
static void TIMx_GPIO_Config(void) 
{
	/*定义一个GPIO_InitTypeDef类型的结构体*/
	GPIO_InitTypeDef GPIO_InitStructure;

	/*开启定时器相关的GPIO外设时钟*/
	ADVANCE_OCPWM_GPIO_CLK_ENABLE();
	ADVANCE_OCNPWM_GPIO_CLK_ENABLE();
	ADVANCE_BKIN_GPIO_CLK_ENABLE(); 

	/* 定时器功能引脚初始化 */															   
	GPIO_InitStructure.Pin = ADVANCE_OCPWM_PIN;	
	GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;    
	GPIO_InitStructure.Pull = GPIO_NOPULL;
	GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; 	
	GPIO_InitStructure.Alternate = ADVANCE_OCPWM_AF;
	HAL_GPIO_Init(ADVANCE_OCPWM_GPIO_PORT, &GPIO_InitStructure);	

	GPIO_InitStructure.Pin = ADVANCE_OCNPWM_PIN;	
	GPIO_InitStructure.Alternate = ADVANCE_OCNPWM_AF;	
	HAL_GPIO_Init(ADVANCE_OCNPWM_GPIO_PORT, &GPIO_InitStructure);
	
	GPIO_InitStructure.Pin = ADVANCE_BKIN_PIN;	
	GPIO_InitStructure.Alternate = ADVANCE_BKIN_AF;	
	HAL_GPIO_Init(ADVANCE_BKIN_GPIO_PORT, &GPIO_InitStructure);
}

/*
 * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
 * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
 * 另外三个成员是通用定时器和高级定时器才有.
 *-----------------------------------------------------------------------------
 * TIM_Prescaler         都有
 * TIM_CounterMode			 TIMx,x[6,7]没有,其他都有(基本定时器)
 * TIM_Period            都有
 * TIM_ClockDivision     TIMx,x[6,7]没有,其他都有(基本定时器)
 * TIM_RepetitionCounter TIMx,x[1,8]才有(高级定时器)
 *-----------------------------------------------------------------------------
 */
static void TIM_Mode_Config(void)
{
	TIM_BreakDeadTimeConfigTypeDef TIM_BDTRInitStructure;
	// 开启TIMx_CLK,x[1,8] 
	ADVANCE_TIM_CLK_ENABLE(); 
	/* 定义定时器的句柄即确定定时器寄存器的基地址*/
	TIM_TimeBaseStructure.Instance = ADVANCE_TIM;
	/* 累计 TIM_Period个后产生一个更新或者中断*/		
	//当定时器从0计数到999,即为1000次,为一个定时周期
	TIM_TimeBaseStructure.Init.Period = 1000-1;
	// 高级控制定时器时钟源TIMxCLK = HCLK=168MHz 
	// 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=1MHz
	TIM_TimeBaseStructure.Init.Prescaler = 168-1;	
	// 采样时钟分频
	TIM_TimeBaseStructure.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
	// 计数方式
	TIM_TimeBaseStructure.Init.CounterMode=TIM_COUNTERMODE_UP;
	// 重复计数器
	TIM_TimeBaseStructure.Init.RepetitionCounter=0;	
	// 初始化定时器TIMx, x[1,8]
	HAL_TIM_PWM_Init(&TIM_TimeBaseStructure);

	/*PWM模式配置*/
	//配置为PWM模式1
	TIM_OCInitStructure.OCMode = TIM_OCMODE_PWM1;
	TIM_OCInitStructure.Pulse = ChannelPulse;
	TIM_OCInitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;
	TIM_OCInitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH;
	TIM_OCInitStructure.OCIdleState = TIM_OCIDLESTATE_SET;
	TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;
	//初始化通道1输出PWM 
	HAL_TIM_PWM_ConfigChannel(&TIM_TimeBaseStructure,&TIM_OCInitStructure,TIM_CHANNEL_1);

	/* 自动输出使能,断路、死区时间和锁定配置 */
	TIM_BDTRInitStructure.OffStateRunMode = TIM_OSSR_ENABLE;
	TIM_BDTRInitStructure.OffStateIDLEMode = TIM_OSSI_ENABLE;
	TIM_BDTRInitStructure.LockLevel = TIM_LOCKLEVEL_1;
	TIM_BDTRInitStructure.DeadTime = 0xff;
	TIM_BDTRInitStructure.BreakState = TIM_BREAK_ENABLE;
	TIM_BDTRInitStructure.BreakPolarity = TIM_BREAKPOLARITY_LOW;
	TIM_BDTRInitStructure.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
	HAL_TIMEx_ConfigBreakDeadTime(&TIM_TimeBaseStructure, &TIM_BDTRInitStructure);

	/* 定时器通道1输出PWM */
	HAL_TIM_PWM_Start(&TIM_TimeBaseStructure,TIM_CHANNEL_1);
	/* 定时器通道1互补输出PWM */
	HAL_TIMEx_PWMN_Start(&TIM_TimeBaseStructure,TIM_CHANNEL_1);
}

/**
  * @brief  初始化高级控制定时器定时,1s产生一次中断
  * @param  无
  * @retval 无
  */
void TIMx_Configuration(void)
{
	TIMx_GPIO_Config();	

	TIM_Mode_Config();
}

/*********************************************END OF FILE**********************/

头文件:
bsp_advance_tim.h

#ifndef __ADVANCE_TIM_H
#define	__ADVANCE_TIM_H

#include "stm32f4xx.h"

/* 定时器 */
#define ADVANCE_TIM           				    TIM8
#define ADVANCE_TIM_CLK_ENABLE()  			  __TIM8_CLK_ENABLE()
 
/* TIM8通道1输出引脚 */
#define ADVANCE_OCPWM_PIN           		  GPIO_PIN_6              
#define ADVANCE_OCPWM_GPIO_PORT     		  GPIOC                      
#define ADVANCE_OCPWM_GPIO_CLK_ENABLE() 	__GPIOC_CLK_ENABLE()
#define ADVANCE_OCPWM_AF					        GPIO_AF3_TIM8

/* TIM8通道1互补输出引脚 */
#define ADVANCE_OCNPWM_PIN            		GPIO_PIN_5              
#define ADVANCE_OCNPWM_GPIO_PORT      		GPIOA                      
#define ADVANCE_OCNPWM_GPIO_CLK_ENABLE()	__GPIOA_CLK_ENABLE()
#define ADVANCE_OCNPWM_AF					        GPIO_AF3_TIM8

/* TIM8断路输入引脚 */
#define ADVANCE_BKIN_PIN              		GPIO_PIN_6              
#define ADVANCE_BKIN_GPIO_PORT        		GPIOA                      
#define ADVANCE_BKIN_GPIO_CLK_ENABLE()  	__GPIOA_CLK_ENABLE()
#define ADVANCE_BKIN_AF						        GPIO_AF3_TIM8


extern TIM_HandleTypeDef TIM_TimeBaseStructure;

void TIMx_Configuration(void);

#endif /* __ADVANCE_TIM_H */

代码讲解

断路功能

//在初始化文件里这几句代码配置了断路功能的模式


TIM_OCInitStructure.OCIdleState = TIM_OCIDLESTATE_SET;//当空闲状态下PWM通道置高电平
TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;//当空闲模状态下PWM互补通道置低电平
TIM_BDTRInitStructure.BreakState = TIM_BREAK_ENABLE;//开启断路功能
TIM_BDTRInitStructure.BreakPolarity = TIM_BREAKPOLARITY_LOW;//低电平断路
TIM_BDTRInitStructure.AutomaticOutput=TIM_AUTOMATICOUTPUT_ENABLE;//断路状态消失后,自动恢复输出

以上语句表示当断路功能对应的引脚输入变为低电平时,互补输出的功能就被禁止,此时变为空闲状态,而pwm对应的通道输出高电平,互补对应的通道变为低电平,而当断路功能对应的引脚变为高电平时,互补输出又再次出现。

死区时间计算PWM互补输出,以及死区时间计算_第1张图片

PWM互补输出,以及死区时间计算_第2张图片
通过上面两张图,就可以知道死区时间的计算公式了

下面列举出配置死区时间的代码

TIM_TimeBaseStructure.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//设置分频系数,详细看第一张图。

TIM_BDTRInitStructure.DeadTime = 0xff;//配置死区时间,具体计算看第二章图



开始计算,假设定时器的频率为165Mhz,且配置语句TIM_BDTRInitStructure.DeadTime = 0xff,则DTG[7:0]被写入11111111,则对应第四个计算方式,TIM_TimeBaseStructure.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1表示对定时器频率1分频,则此时tDTS=1*Tck_int = (1/165000000)s,此时代码计算公式
DT=(32+DTG[4:0])*Tdtg=(32+31)16(1/165000000)*1000000us=6us

你可能感兴趣的:(单片机,stm32,嵌入式硬件)