STM32——TIM死区互补PWM波输出

于pwm波的输出实验老早之前就学了,一直拖到现在才写,,,。由于之前接触过32的高级定时器所以是先从死区pwm波开始学的,后面才学的pwm波。其实会发出死区pwm波了也就会发pwm波了。在学习32的某个功能时要先去看32的数据参考手册了解它的功能然后看它有哪些寄存器,对你需要用到的寄存器深入了解,最后看库函数进行编程。
要发出死区pwm波就要用到32的高级定时器TIM1或TIM8,这两个定时器才有死区寄存器才能发出死区pwm波,对于它们的介绍网上资料有很多这里就不重复啰嗦了,但需要看几个重要的寄存器:
● 控制寄存器(TIMx_CRx)
● 模式控制寄存器(TIMx_SMCR)
● 状态寄存器(TIMx_SR)
● 计数器寄存器(TIMx_CNT)
● 预分频器寄存器(TIMx_PSC)
● 自动装载寄存器(TIMx_ARR)
● 重复次数寄存器(TIMx_RCR)
● 刹车和死区寄存器(TIMx_BDTR)
前面几个寄存器是在配置TIM1/TIM8是要用到的基本设置。自动装载寄存器是预先装载的,写或读自动重装载寄存器将访问预装载寄存器。根据在TIMx_CR1寄存器中的自动装载预装载使能位(ARPE)的设置,预装载寄存器的内容被立即或在每次的更新事件UEV时传送到影子寄存器。当计数器达到溢出条件(向下计数时的下溢条件)并当TIMx_CR1寄存器中的UDIS位等于0时,产生更新事件。更新事件也可以由软件产生。计数器由预分频器的时钟输出CK_CNT驱动,仅当设置了计数器TIMx_CR1寄存器中的计数器使能位(CEN)时,CK_CNT才有效。(更多有关使能计数器的细节,请参见控制器的从模式描述)。注意,在设置了TIMx_CR寄存器的CEN位的一个时钟周期后,计数器开始计数。最后来看一下死区寄存器:它是用来设置两个互补pwm波的死区时间的
在这里插入图片描述
在这里插入图片描述
上面的位都是在配置死区寄存器要用到的基本配置,下面是它的死区时间配置位[7:0]
在这里插入图片描述
DT表示的是死区时间,分了有四种情况位[7:5]为0xx、10x、110、111(x表示0或1)。32的主频是72M,它每走一下的时间为1/72000000=13.89ns。表中64的由来是2^6,由此32是2的5次方。因为UTG是有8个位。
知道这些应该差不多了,接着就去看它的库函数吧,32定时器的库函数有两页之多,需仔细的看,死区寄存器的配置要注意两路波的极性,不能搞错了。


#include "pwm.h"
#include "sys.h"
//FUNCTION:TIM1初始化函数
//AUTHOR:BiggerPast
//DATE:20181010
void TIM1_Init(u16 arr,u16 psc,u16 dead_time)
{
	float T_TDS=13.89;//13.89ns
	u16 death_time;                                                                                         
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_BDTRInitTypeDef TIM_BDTRInitStructure;         //死区设置 
	//dead_time--->255,以下计算按死区寄存器UTG位而得
	if(dead_time >=0 && dead_time <=1764)//公式1
		death_time = dead_time/T_TDS;
	else if(dead_time>=1778 && dead_time<=3529)//公式2
		death_time=dead_time/(T_TDS*2)+64;
	else if(dead_time>=3556 && dead_time<=7001)//公式3
		death_time=dead_time/(T_TDS*8)+160;
	else if(dead_time>=7112 && dead_time<=14001)//公式4
    death_time=dead_time/(T_TDS*16) + 192;
  else
    death_time=death_time;
	
	//IO口初始化
	RCC->APB2ENR|=(1<<2)|(1<<3)|(1<<11);//使能PA PB TIM1时钟
	GPIOA->CRH&=0XFFFFF000;//清除设置
	GPIOB->CRH&=0X000FFFFF;
	GPIOA->CRH|=0X0000000A;//PA8复用推挽输出 2M
	GPIOB->CRH|=0X00A00000;//B13复用推挽输出 2M
	
	//定时器配置
	TIM_TimeBaseStructure.TIM_Period = arr;//在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler = psc;//TIM1时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;//时钟分频可为1,2,4
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;// 计数模式Up为向上计数,Down向下
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;//重复计数
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
	
	//输出波形配置 CH1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//定时器模式为PWM模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出比较使能	
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//输出比较N使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//空闲输出极性高
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;//空闲输出高
	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;//空闲输出低
	TIM_OCInitStructure.TIM_Pulse = duty;
	TIM_OC1Init(TIM1,&TIM_OCInitStructure);
	
		/*高级定时器死区配置*/
	TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;//MOE主输出使能 
	TIM_BDTRInitStructure.TIM_Break=TIM_Break_Disable;//刹车功能禁止
	TIM_BDTRInitStructure.TIM_BreakPolarity=TIM_BreakPolarity_High;       
	TIM_BDTRInitStructure.TIM_DeadTime=death_time;//死区时间
	TIM_BDTRInitStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF;//锁定关闭,寄存器无写保护
	TIM_BDTRInitStructure.TIM_OSSRState=TIM_OSSRState_Disable;
	TIM_BDTRInitStructure.TIM_OSSIState=TIM_OSSIState_Disable;
	TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

	TIM_CtrlPWMOutputs(TIM1,ENABLE);//MOE主输出使能  高级定时器必须
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);//CH1预装载使能
	TIM_ARRPreloadConfig(TIM1,ENABLE);//使能TIM1在ARR上的预装载寄存器
	TIM_Cmd(TIM1,ENABLE);
}

总结:波形的输出端口有个映射的问题:映射就像是功能复制,把一个IO口的功能复制到另一个IO口,当一个IO口的功能重复时通过映射就可以实现一个IO口实现不同的功能了。需要特别注意,不然输出波形不正常!

猜你喜欢

转载自blog.csdn.net/qq_41421591/article/details/83274846