下面是我根据网上的别人的方法修改后的用PWM控制电机的程序。
他的例子里PWM是固定频率的,只能改变脉冲数,这样就没法控制电机快慢了。
我工作中控制电机加减速,是用固定周期打不同频率的脉冲,实现电机的加减速、快慢控制,
下面是我的方法:
TIM3 TIM2级联,主计数器TIM3的周期定位2ms,TIM3的使能信号作为TIM2的触发信号,单发模式。
TIM2作为从计数器以gate模式受TIM3控制,在2ms周期内以不同频率不同个数发出PWM脉冲。
现在有两个问题我没法解决:
1 、程序在我把断点设到中断里时,工作很正常,能在指定周期内完美的输出脉冲波形,但是去掉断点连续跑,
TIM3直接就不进中断去了。
2 、中断里的TIM2->CR1&=(uint16_t)~TIM_CR1_CEN;TIM2->CR1|=1; 两个语句是我自己加的,
原来的例子里没有。如果没有手动清除TIM2 CEN,则中断断点后TIM2还在计数,TIM2->CNT = 0; 这句就无效,pwm乱套。
我奇怪GATE MODE下, TIM2不是要跟着TIM3一起启动和停止的吗?可是断点时发现TIM2的CEN位根本没清除
进入中断后观察过TIM2 ->SMCR值是0XA5 TIM3->SMCR是0X80 CR2 OPM是1 ,也就是说设置都没错。
这个模式在来源的例子中是能工作正常的,可是我一改变TIM2的设置,就不能正常工作了?why?
又,查手册说TRGI信号有delay,才促发,可是我找来找去找不着delay在哪里,怎么设置的!
第一次用STM32做设计,眼看似乎就好了,结果掉这坑里!求指点?
代码如下:
//---------------------------------------------------------------------------
[mw_shl_code=c,true]
#define PWM_BASE 18000
void pwm_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* TIM2 clock enable */
RCC_PCLK1Config(RCC_HCLK_Div16);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM2 CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
GPIO_Init(GPIOA, &GPIO_InitStructure);
//TIM_Cmd(TIM2,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PB0 TIM3 CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* TIM2 Main Output Enable */
//-------------------------------------------------------------------
/* Setup timer2 channel 2, Timer2 is slave timer
This timer is used to output waveforms */
{
//TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_DeInit(TIM2);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = PWM_BASE;//PWM_Period;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
/* Timer2 Channel 2 Configuration in PWM2 mode, this is used for enable Recive clcok */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = PWM_BASE/2;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM2,&TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM2, ENABLE);
}
//-----------------------------------------------------------------------
/* Setup Timer3 channel 3, Timer3 is master timer
This timer is used to control the waveform count of timer1 */
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_DeInit(TIM3);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_TimeBaseStructure.TIM_Prescaler =0;//PWM_BASE/8 - 1;;//PWM_BASE/2 - 1; //PWM_Period/2 - 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period =PWM_BASE ;//waveNumber*8 - 1;//waveNumber*2;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse =PWM_BASE/2;// waveNumber*8 - 2;//waveNumber*2 - 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM3,&TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM3, ENABLE);
TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Single);
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn ; //选择定时器TIM3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //选择抢先式优先级(与中断嵌套级别有关)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //选择子优先级(同抢先式优先级的响应顺序)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //选择使能中断源
NVIC_Init(&NVIC_InitStructure);
TIM_ClearFlag(TIM3,TIM_FLAG_CC3); //中断标志位清零
TIM_ITConfig(TIM3,TIM_IT_CC3,ENABLE); //允许更新中断
}
}
//--------------------------------------------------------------------------
/* Create relationship between timer1 and timer3, timer3 is master, timer1 is slave
timer2 is work under gate control mode, and controled by timer3
timer3's channel 3 is used as the control signal
*/
/* Enable timer's master/slave work mode */
TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);
/* timer3's channel 4 is used as the control signal */
//TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_OC3Ref );
TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Enable);
/* Check the master/slave is valid or not */
compile_assert((u16)GetInternalTrigger(TIM2,TIM3) != (U16)-1);
/* Config timer1's external clock */
TIM_ITRxExternalClockConfig(TIM2, GetInternalTrigger(TIM2,TIM3));
TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Gated);
/* Enable the slave tiemr*/
TIM_Cmd(TIM2,ENABLE);
//-----------------------------------------------------------------------------
TIM3->CR1|=1;
}
void TIM3_IRQHandler(void)
{
static U32 ct;
U16 capture;
/* enter interrupt */
rt_interrupt_enter();
//set pluse here
TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
TIM2->CR1&=(uint16_t)~TIM_CR1_CEN; //add by myself
TIM2->CNT = 0;
/* update waveform number */
if(waveNumber == 4){
waveNumber = 2;
}else{
waveNumber=4;
}
TIM2->ARR = PWM_BASE/waveNumber;
TIM2->CCR2 = (PWM_BASE/waveNumber)/2;
TIM3->CR1|=1; /* Re-enable the timer */
TIM2->CR1|=1;
/* leave interrupt */
rt_interrupt_leave();
rt_hw_interrupt_thread_switch();
}[/mw_shl_code]
|