微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 51单片机控制四相步进电机

51单片机控制四相步进电机

时间:11-19 来源:互联网 点击:
  接触单片机快两年了,不过只是非常业余的兴趣,实践却不多,到现在还算是个初学者吧。这几天给自己的任务就是搞定步进电机的单片机控制。以前曾看过有关步进电机原理和控制的资料,毕竟自己没有做过,对其具体原理还不是很清楚。今天从淘宝网买了一个EPSON的UMX-1型步进电机,此步进电机为双极性四相,接线共有六根,外形如下图所示:

拿到步进电机,根据以前看书对四相步进电机的了解,我对它进行了初步的测试,就是将5伏电源的正端接上最边上两根褐色的线,然后用5伏电源的地线分别和另外四根线(红、兰、白、橙)依次接触,发现每接触一下,步进电机便转动一个角度,来回五次,电机刚好转一圈,说明此步进电机的步进角度为360/(4×5)=18度。地线与四线接触的顺序相反,电机的转向也相反。

如果用单片机来控制此步进电机,则只需分别依次给四线一定时间的脉冲电流,电机便可连续转动起来。通过改变脉冲电流的时间间隔,就可以实现对转速的控制;通过改变给四线脉冲电流的顺序,则可实现对转向的控制。所以,设计了如下电路图:



C51程序代码为:

代码一

#include

static unsigned intcount;
static unsigned intendcount;

voiddelay();

voidmain(void)
{
count = 0;
P1_0 = 0;
P1_1 = 0;
P1_2 = 0;
P1_3 = 0;

EA = 1;//允许CPU中断
TMOD = 0x11;//设定时器0和1为16位模式1
ET0 = 1;//定时器0中断允许

TH0 = 0xFC;
TL0 = 0x18;//设定时每隔1ms中断一次
TR0 = 1; //开始计数

startrun:

P1_3 = 0;
P1_0 = 1;
delay();
P1_0 = 0;
P1_1 = 1;
delay();
P1_1 = 0;
P1_2 = 1;
delay();
P1_2 = 0;
P1_3 = 1;
delay();
gotostartrun;
}

//定时器0中断处理
voidtimeint(void)interrupt1
{
TH0=0xFC;
TL0=0x18;//设定时每隔1ms中断一次
count++;
}

voiddelay()
{
endcount=2;
count=0;
do{}while(count}

将上面的程序编译,用ISP下载线下载至单片机运行,步进电机便转动起来了,初步告捷!

不过,上面的程序还只是实现了步进电机的初步控制,速度和方向的控制还不够灵活,另外,由于没有利用步进电机内线圈之间的“中间状态”,步进电机的步进角度为18度。所以,我将程序代码改进了一下,如下:

代码二

#include

static unsigned intcount;
static intstep_index;

voiddelay(unsigned intendcount);
voidgorun(bitturn,unsigned intspeedlevel);

voidmain(void)
{
count = 0;
step_index = 0;
P1_0 = 0;
P1_1 = 0;
P1_2 = 0;
P1_3 = 0;

EA = 1;//允许CPU中断
TMOD = 0x11;//设定时器0和1为16位模式1
ET0 = 1;//定时器0中断允许

TH0 = 0xFE;
TL0 = 0x0C;//设定时每隔0.5ms中断一次
TR0 = 1;//开始计数

do{
gorun(1,60);
}while(1);

}

//定时器0中断处理
voidtimeint(void)interrupt1
{
TH0=0xFE;
TL0=0x0C;//设定时每隔0.5ms中断一次
count++;
}

voiddelay(unsigned intendcount)
{
count=0;
do{}while(count}

voidgorun(bitturn,unsigned intspeedlevel)
{
switch(step_index)
{
case0:
P1_0 = 1;
P1_1 = 0;
P1_2 = 0;
P1_3 = 0;
break;
case1:
P1_0 = 1;
P1_1 = 1;
P1_2 = 0;
P1_3 = 0;
break;
case2:
P1_0 = 0;
P1_1 = 1;
P1_2 = 0;
P1_3 = 0;
break;
case3:
P1_0 = 0;
P1_1 = 1;
P1_2 = 1;
P1_3 = 0;
break;
case4:
P1_0 = 0;
P1_1 = 0;
P1_2 = 1;
P1_3 = 0;
break;
case5:
P1_0 = 0;
P1_1 = 0;
P1_2 = 1;
P1_3 = 1;
break;
case6:
P1_0 = 0;
P1_1 = 0;
P1_2 = 0;
P1_3 = 1;
break;
case7:
P1_0 = 1;
P1_1 = 0;
P1_2 = 0;
P1_3 = 1;
}

delay(speedlevel);

if(turn==0)
{
step_index++;
if(step_index>7)
step_index=0;
}
else
{
step_index--;
if(step_index<0)
step_index=7;
}

}

改进的代码能实现速度和方向的控制,而且,通过step_index静态全局变量能“记住”步进电机的步进位置,下次调用 gorun()函数时则可直接从上次步进位置继续转动,从而实现精确步进;另外,由于利用了步进电机内线圈之间的“中间状态”,步进角度减小了一半,只为9度,低速运转也相对稳定一些了。

但是,在代码二中,步进电机的运转控制是在主函数中,如果程序还需执行其它任务,则有可能使步进电机的运转收到影响,另外还有其它方面的不便,总之不是很完美的控制。所以我又将代码再次改进:

代码三

#include

static unsigned intcount;//计数
static intstep_index;//步进索引数,值为0-7

static bitturn;//步进电机转动方向
static bitstop_flag;//步进电机停止标志
static intspeedlevel;//步进电机转速参数,数值越大速度越慢,最小值为1,速度最快
static intspcount;//步进电机转速参数计数
voiddelay(unsigned intendcount);//延时函数,延时为endcount*0.5毫秒
voidgorun();//

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top