单片机控制步进电机的方法很简单,可以用IO口输出脉冲控制线圈电流驱动电机旋转,可分为四相四拍,四相八拍。四相电机,有四相四拍运行方式AB-BC-CD-DA-AB,四相八拍运行方式即 A-AB-B-BC-C-CD-D-DA-A。前面文档给出的表是四相八拍。
下面说下STM32单片机的程序部分,主函数只有定时器、IO初始化和循环。如下
int main(void)
{
LED_GPIO_Config();
TIM_Config();
while(1)
{
}
}
定时器初始化部分,使用定时器的计数功能,使能定时器中断,使用内部晶振,计算8000000/(79+1)/100 =1000 ,即1ms中断一次。
void TIM_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_DeInit(TIM3);
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1 ;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up ;
TIM_TimeBaseInitStruct.TIM_Period = 100 ;
TIM_TimeBaseInitStruct.TIM_Prescaler = 79 ;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct ) ;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
TIM_ITConfig(TIM3, TIM_IT_Update,ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
四相八拍 中断服务函数,按照A-AB-B-BC-C-CD-D-DA-A方式控制IO输出。
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM3_count++;
if(TIM3_count>7)
{
TIM3_count=0;
}
if(TIM3_count==0)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,1);
}
else if(TIM3_count==1)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,1);
}
else if(TIM3_count==2)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,0);
}
else if(TIM3_count==3)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,0);
}
else if(TIM3_count==4)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,0);
}
else if(TIM3_count==5)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,0);
}
else if(TIM3_count==6)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,0);
}
else if(TIM3_count==7)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,1);
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
}
}
使用逻辑分析仪抓的信号如下
四相四拍中断服务函数,按照AB-BC-CD-DA-AB控制输出IO
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM3_count++;
if(TIM3_count>3)
{
TIM3_count=0;
}
if(TIM3_count==0)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,0);
}
else if(TIM3_count==1)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,0);
}
else if(TIM3_count==2)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,1);
}
else if(TIM3_count==3)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8,1);
GPIO_WriteBit(GPIOA, GPIO_Pin_9,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_10,0);
GPIO_WriteBit(GPIOA, GPIO_Pin_11,1);
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
}
}
别看这个步进电机小,其实挺有劲的,转起来手抓不住。直接用脉冲的控制方式噪音大,震动明显,后面介绍正弦波驱动方式,能很好的解决噪音和震动问题。