利用STM32的TIM1/TIM8输出可以移相的互补PWM

前言:TIM1、TIM8是STM32的高级定时器,在高容量的STM32芯片中含有TIM8,低容量芯片只有TIM1。这两个定时器是完全独立工作的。在实际工作中,我们希望他们有时间上的联系。比如做全桥移相的时候,需要两个PWM之间有一个相位差,并且可以调整相位宽度。这点STM32是可以做到的。
思路:TIM1作为主定时器,TIM8作为从定时器。TIM1_CH1/CH1N、TIM8_CH1/CH1N互补输出。另取通道TIM1_CH2产生的OC2REF作为触发源TRGO。设置TIM1_CH2的比较寄存器TIM1_CCR2,设定延时时间。当TIM1_CH2比较溢出,产生OC2REF上升沿,TIM8作为从模式收到TRGI上升沿,产生复位,从头产生PWM。从而实现TIM1/TIM8双路PWM产生时间差,即移相。
重点

  • MMS@TIM1_CR2设置为“101” 【主模式,OC2REF用作触发输出TRGO】

  • TS@TIM8_SMCR设置为“000” 【TIM8触发输入TRGI选择内部触发0(ITR0),也就是对应TIM1】
    在这里插入图片描述

  • SMS@TIM8_SMCR设置为“100” 【TIM8从模式选择复位模式】

开整:

  • TIM1模式设置
void TIM1_Mode_Config(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_DeInit(TIM1);	
	TIM_TimeBaseStructure.TIM_Period =_PWM_PeriodVal;      	             /*1.设置定时时间ARR*/
	TIM_TimeBaseStructure.TIM_Prescaler = 0;	                         /*2.设置预分频:不预分频,即为72MHz  */
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;	         /*3.设置时钟分频因子[TIMx_CR1:CKD]:不分频。采样输入时有效*/
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;          /*向上计数模式*/
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;						 /*不使用重复计数器*/
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);						 /*初始化结构体*/
    TIM_InternalClockConfig(TIM1); 										 /*关闭从模式,即预分频器使用内部时钟驱动*/
	TIM_Cmd(TIM1,ENABLE);												 /*使能TIM1*/

}

  • TIM1输出设置。包括通道1和通道2,通道1产生互补PWM,通道2不输出信号,只产生触发源
/*********************************************
 *函数名:TIM1_OC_Config
 *函数描述:TIM1输出设置
 *输入参数:无
 *输出结果:无
 *返回值:无
***********************************************/
void	TIM1_OC_Config(void)
{	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;						 /*TIM1_OC1的模式为PWM1*/
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;			 /*允许输出*/
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;			 /*允许输出*/
	TIM_OCInitStructure.TIM_Pulse = (_PWM_PeriodVal)/2;						 /*CCR1=ARR*50%*/
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;				 /*CC1P:输出极性高为有效*/
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;				 /*CC1PN*/
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);		
	//----------------------------------------------
	/*TIM_OC2设置,作为触发信号,来复位TIM8*/
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active; /*TIM1_OC2REF的模式为高电平有效*/
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;  /*输出关闭*/
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;/*输出关闭*/
	TIM_OCInitStructure.TIM_Pulse = _PHASE_TimeVal;                /*相位差*/
	TIM_OC2Init(TIM1,&TIM_OCInitStructure);
	TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC2Ref);  /*TIM1_OC2REF作为主模式TRGO输出*/
	//----------------------------------------------	
	/*预装载使能*/
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);						 /*TIM_OCPreload_Enable     TIM_OCPreload_Disable	 */
	TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);						 /*TIM_OCPreload_Enable  */  
	//----------------------------------------------			
	/*使能TIM1重载寄存器ARR*/
	TIM_ARRPreloadConfig(TIM1, ENABLE);		
	//-----------------------------------------------
	TIM_BDTRStructInit(&TIM_BDTRInitStructure);								 /*BDTR初始化,默认初始值*/
	//------------------------------------------------
	/*运行模式下定时器不工作时,输出无效电平*/
	TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Disable;			 
	/*空闲模式下定时器不工作时,禁止OC/OCN输出	 */  
	TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Disable; 			 /*锁定级别LEVEL1*/
	/*设置死区时间1us*/
	TIM_BDTRInitStructure.TIM_DeadTime = 72;								 /*0~0xFF 	 1us*72M*/																										
	/*刹车除能*/
	TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;					 
	//	TIM_BDTRInitStructure.TIM_TIM_BreakPolarity =TIM_BreakPolarity_High;	 /*TIM_BreakPolarity_High
	//	                                                                           TIM_BreakPolarity_Low */
	/*自动输出除能 AOE只能被软件置1*/
	TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Disable;	 /*TIM_AutomaticOutput_Disable
																																				 TIM_AutomaticOutput_Enable */

	TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);							 /*更改BDTR寄存器值*/
}

在上面代码中可以看到对TIM1_CH2通道的设置。主要是设置OC2REF极性,和相位。
TIM_OCInitStructure.TIM_Pulse = _PHASE_TimeVal; /*相位差*/
后面可以直接对TIM1_CCR2操作,来调整相位。
比如使用:

TIM_SetCompare2 (TIM1,PhaseVal);

或者直接操作:

TIM1->CCR2 = PhaseVal;

设置TIM1_CH2为TRGO触发源:

TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC2Ref);  /*TIM1_OC2REF作为主模式TRGO输出*/
  • TIM8 模式设置、输出设置与TIM1相同,不贴代码了。
  • TIM8输入设置
/*********************************************
 *函数名:TIM8_IC_Config
 *函数描述:TIM8输入设置
 *输入参数:无
 *输出结果:无
 *返回值:无
***********************************************/
void TIM8_IC_Config(void)
{
    TIM_SelectSlaveMode(TIM8,TIM_SlaveMode_Reset);             /*从模式 复位模式*/
	TIM_SelectInputTrigger (TIM8,TIM_TS_ITR0);                 /*触发源 TIM_TS_ITR0对应TIM1*/

}
  • 设置完毕,调用即可
	TIM1_Mode_Config();
	TIM1_OC_Config();
	TIM_Cmd(TIM1, ENABLE);                                   /* TIM1 counter enable */
	TIM_CtrlPWMOutputs(TIM1, ENABLE);                        /* TIM1 Main Output Enable */
	TIM8_Mode_Config();
	TIM8_IC_Config();
	TIM8_OC_Config();
	TIM_Cmd(TIM8, ENABLE);                                   /* TIM8 counter enable */
	TIM_CtrlPWMOutputs(TIM8, ENABLE);                        /* TIM8 Main Output Enable */

其他需要注意的地方

在其他程序段修改TIM1->CCR2的值时,可能会出现寄存器值修改了,但是实际输出却没有变化的情况。
因为我们将TIM1_CH2设置成了TIM_OCMode_Active,高逻辑有效。所以在得到高逻辑之后,无法自动回到低逻辑状态,所以需要干预一下。
事实上,我认为将TIM1_CH2设置成PWM1模式比较合适。但是没有调试没有成功,不知道原因。于是选择了这种办法。如下代码。在修改TIM1->CCR2之前将模式强制拉低,然后再改为TIM_OCMode_Active,这样就可以正常工作了。

		TIM_ForcedOC2Config(TIM1,TIM_ForcedAction_InActive);
		TIM_SelectOCxM(TIM1,TIM_Channel_2,TIM_OCMode_Active);
		TIM_SetCompare2(TIM1,50);

		while(TIM_GetFlagStatus(TIM8, TIM_FLAG_Trigger) == RESET);

		Delay(3000);  
		TIM_ForcedOC2Config(TIM1,TIM_ForcedAction_InActive);	
		TIM_SelectOCxM(TIM1,TIM_Channel_2,TIM_OCMode_Active);
		TIM_SetCompare2(TIM1,400);
		while(TIM_GetFlagStatus(TIM8, TIM_FLAG_Trigger) == RESET);	

	  Delay(3000);

猜你喜欢

转载自blog.csdn.net/weixin_43128823/article/details/89406246