最近在调试伺服电机,使用主从定时器产生可控脉冲数,调整电机运行,主定时器TIM3,通道CH1,从定时器TIM5。配置好后,使用TIM3产生脉冲,同时驱动从定时器TIM5计数,TIM5产生中断后,在中断中关闭定时器TIM3以达到控制脉冲个数的目的。
一般情况,定时器TIM3能够发送可控的脉冲数,但是会随机出现定时器TIM5,无法进入中断,导致无法关闭TIM3,使得TIM3一直发送脉冲,出现电机一直旋转无法停下来。代码如下
// IO初始
void goio_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); // 复用为普通IO
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 脉冲输出引脚,定时器3 CH1
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 方向
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//从定时器初始化
void TIM5_init(void)
{
TIM_TimeBaseInitTypeDef TIME_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
TIME_InitStruct.TIM_ClockDivision=0;
TIME_InitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIME_InitStruct.TIM_Period=0;
TIME_InitStruct.TIM_Prescaler=0;
TIM_TimeBaseInit(TIM5,&TIME_InitStruct);
TIM_SelectInputTrigger(TIM5, TIM_TS_ITR1);//TIM3主连接TIM1,TIM_TS_ITR2
TIM_SelectSlaveMode (TIM5,TIM_SlaveMode_External1);//
TIM_ITConfig(TIM5,TIM_IT_Update,DISABLE);
NVIC_InitStruct.NVIC_IRQChannel=TIM5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
// 主定时器 脉冲频率为40K
void TIM3_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM5_init(); // 从定时器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_DeInit(TIM3);
TIM_TimeBaseStructure.TIM_Period =25-1; //自动重装载寄存器 40K
TIM_TimeBaseStructure.TIM_Prescaler = 72-1; //预分频器,t=(23999+1)*(2+1)/72M
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器向上计数模式
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //写TIM3各寄存器参数
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输入/捕获2输出允许
TIM_OCInitStructure.TIM_Pulse = 13; //确定占空比,这个值决定了有效电平的时间。
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性,低电平有效
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //配置定时器输出模式,比较参数等
TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
//TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_OC1);
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //通道1使能
TIM_ARRPreloadConfig(TIM3, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器
}
// 从定时器5 中断处理
void TIM5_IRQHandler(void)
{
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM5, TIM_IT_Update );
servoMotor.run=0;
TIM_Cmd(TIM3,DISABLE);
TIM_ITConfig(TIM5,TIM_IT_Update,DISABLE);
TIM_Cmd(TIM5,DISABLE);
}
}
// 伺服电机脉冲输出
void servo_motor_plused(uint16_t pluseNum)
{
if( pluseNum > 1668)
{
pluseNum = 1668;
}
// 设置从定时器 脉冲计数个数
__disable_irq();
TIM5->ARR = pluseNum-1;
__enable_irq();
TIM_Cmd(TIM5,ENABLE);
TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE);
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
TIM_Cmd(TIM3,ENABLE);
servoMotor.run =1; // 标计运行状态
}
//硬件控制 函数SendPluseFromCache 中调用
void servo_motor_run(uint16_t pluseNum,uint8_t dir)
{
servo_motor_set_dir(dir);
servo_motor_plused(pluseNum);
}
// 发送缓存池的脉冲数量,定时1MS调用,pluseCacheNum在上位机发送电机控制时++,最快85ms一次,脉冲数随机
void SendPluseFromCache(void)
{
uint16_t temp_pluse=0;
uint8_t temp_dir=0;
if (!pluseCacheNum) // 内存池没有命令了
{
return;
}
if (servoMotor.run ==1)
{
return;
}
__disable_irq();
pluseCacheNum--; // 命令数-1
__enable_irq();
if (pluseCacheIndex>0) // 发送上装填完成的数据,下标前移进入装填
{
pluseCacheIndex --;
}
temp_dir =pluseCacheArray[pluseCacheIndex][0];
temp_pluse =pluseCacheArray[pluseCacheIndex][1];
pluseCacheArray[pluseCacheIndex][0] =0;
pluseCacheArray[pluseCacheIndex][1] =0;
servo_motor_run(temp_pluse,temp_dir); // 加载伺服电机
}
代码跑起来,电机能够正常运行,但是偶尔会出现电机一直运转的现象,检查发现定时器5没有产生中断,导致一直在发送脉冲。我以为定时器5的中断优先级太低导致的,我调整了优先级仍然会出现,我尝试改变从定时器触发方式,仍然会有这个问题。
请教各位帮忙分析下,为什么会出现TIM5进不了中断,如何解决这个问题。