使用stm32f103野火指南者开发板驱动一个两相闭环步进电机的问题,单片机连接步进电机驱动器,共阳极连接。程序正常,但是上电后步进电机不是每次都能正常运转,经常无反应,但是没有修改程序也没有修改线路,偶尔电机又可以受控制的运转。经测试:当电机能正常控制时,关掉开发板电源,在打开开发板电源,电机受控;但是关掉驱动器的电源,再启动,电机不受控制。而且下一次电机能否受控制是随机的,经常都是单片机发出脉冲后无反应,太玄学了,有知道的朋友可以解答吗
void USUALL_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 输出比较通道1-4初始化
RCC_APB2PeriphClockCmd(
USUALL_TIM_CH2_GPIO_CLK |
USUALL_TIM_CH3_GPIO_CLK |
USUALL_TIM_CH4_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = //通道1-4
USUALL_TIM_CH2_PIN |
USUALL_TIM_CH3_PIN |
USUALL_TIM_CH4_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5);
}
void USUALL_TIM_Mode_Config(uint16_t CCR1_Val,uint16_t CCR2_Val,uint16_t CCR3_Val,uint16_t CCR4_Val)
{
// 开启定时器时钟,即内部时钟CK_INT=72M
USUALL_TIM_APBxClock_FUN(USUALL_TIM_CLK,ENABLE);
/*--------------------时基结构体初始化-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=USUALL_TIM_PERIOD; //100
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= USUALL_TIM_PSC; //19
// 时钟分频因子 ,配置死区时间时需要用到
// TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(USUALL_TIM, &TIM_TimeBaseStructure);
/*--------------------输出比较结构体初始化-------------------*/
// 占空比配置
TIM_OCInitTypeDef TIM_OCInitStructure;
// 配置为PWM模式1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
// 输出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
// 互补输出不使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
// 输出通道电平极性配置
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 设置通道1占空比大小
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OC1Init(USUALL_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(USUALL_TIM, TIM_OCPreload_Enable);
// 设置通道2占空比大小
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(USUALL_TIM, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(USUALL_TIM, TIM_OCPreload_Enable);
// 设置通道3占空比大小
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(USUALL_TIM, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(USUALL_TIM, TIM_OCPreload_Enable);
// 设置通道4占空比大小
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(USUALL_TIM, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(USUALL_TIM, TIM_OCPreload_Enable);
TIM_ITConfig(USUALL_TIM,TIM_IT_Update,ENABLE);
// 使能计数器
TIM_Cmd(USUALL_TIM, ENABLE);
// TIM_CtrlPWMOutputs();启动或暂停输出PWM,
}
static void USUALL_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn ;
// 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM5_IRQHandler (void)
{
if ( TIM_GetITStatus( USUALL_TIM, TIM_IT_Update) != RESET )
{
count_pwm++;
TIM_ClearITPendingBit(USUALL_TIM , TIM_FLAG_Update);
}
}
void BUJIN_MOTer(void)
{
count_pwm=0;
USUALL_TIM_GPIO_Config();
USUALL_TIM_Mode_Config(50,50,50,50);
USUALL_TIM_NVIC_Config();
}
extern uint16_t count_pwm;
int main(void)
{
LED_config();
USART_Config();
key_config();
while ( 1 )
{
if (1) //按键调速
{
if(key_san(key2_port,key2_pin)==key_on)
{
LED_RED;
BUJIN_MOTer();
GPIO_SetBits(GPIOA,GPIO_Pin_5);
}
if ( (count_pwm==6400) &(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_5)))
{
count_pwm=0;
TIM_Cmd(USUALL_TIM, DISABLE);
LED_WHITE;
}
if ( (count_pwm==3200 )&(~GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_5)))
{
count_pwm=0;
TIM_Cmd(USUALL_TIM, DISABLE);
LED_WHITE;
}
if(key_san(key1_port,key1_pin)==key_on)
{
LED_BLUE;
BUJIN_MOTer();
GPIO_ResetBits(GPIOA,GPIO_Pin_5);
}
}
}
}
```代码,请勿粘贴截图
连接图如下:

1.关闭开发板电源,再打开开发板电源,这个时候程序已经重新开始跑了。
2.关闭驱动器电源,这个时候开发板还有电,如果程序不能够很好的处理电机掉线问题,估计程序就跑飞出bug了。
3.建议看一下闭环控制是不是有问题,包括电机数据采集等涉及电机控制部分的变量和数据。
驱动器意外断电可能让驱动器进入了保护或者休眠状态,启动器重新上电后能复位一下驱动芯片最好,不然的话就一起上电。
根据您提供的代码和连接图,我注意到您正在使用定时器TIM5来驱动步进电机,并通过定时器中断来计数脉冲。我还注意到您将步进电机驱动器连接到GPIOA的Pin 5引脚。
根据您的描述,电机在上电后无法稳定运转,并且关掉驱动器电源再启动后,电机也无法受控制。这可能涉及到电源和GPIO引脚的初始化以及步进电机驱动器的操作。
以下是几个可能的问题和建议的解决方案:
1、GPIO引脚配置:请确保在初始化GPIO引脚时,将其配置为正确的模式和状态。对于Pin 5引脚,您当前将其配置为推挽输出模式(GPIO_Mode_Out_OD),但步进电机驱动器一般需要使用开漏输出模式。请尝试将GPIO模式配置为GPIO_Mode_Out_PP。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
2、电源问题:确保步进电机驱动器和开发板之间的共地连接良好,且电源稳定。检查电源供应是否满足电机和驱动器的要求,以及电源供应的稳定性。还请确保开发板和驱动器的地线连接正确,以避免信号干扰或地回路问题。
3、中断处理函数:在中断处理函数TIM5_IRQHandler()中,您需要清除TIM的中断标志位,以便下一次中断可以触发。确保您使用了正确的标志位。
TIM_ClearITPendingBit(USUALL_TIM, TIM_IT_Update);
4、中断优先级:请确保您正确配置了中断优先级,并与其他中断优先级进行适当的调整。根据您的代码,您设置了中断优先级组为NVIC_PriorityGroup_0,并将中断优先级设置为0和3,这取决于您的需求和其他中断的优先级设置。
5、正确的计数器设置:请检查步进电机驱动器的配置和工作模式是否正确。确保步进电机驱动器的步进模式、旋转方向等设置正确。根据您的代码,我无法确定CCR1_Val、CCR2_Val、CCR3_Val和CCR4_Val的值是否正确设置。