前言: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输出*/
1
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);
上一篇:STM32之多通道AD使用DMA采集数据
下一篇:STM32调试,无法进入main函数 LDR r0,[pc,#0]
推荐阅读最新更新时间:2024-11-08 19:21