步进电机控制系统的设计与仿真.docx
《步进电机控制系统的设计与仿真.docx》由会员分享,可在线阅读,更多相关《步进电机控制系统的设计与仿真.docx(14页珍藏版)》请在冰豆网上搜索。
步进电机控制系统的设计与仿真
一、设计题目
步进电机控制系统的设计与仿真
二、设计要求
设计一个单片机四相步进电机控制系统,要求系统具有以下功能。
(1)用K0-K2作为通电方式选择键,K0为单四拍,K1为双四拍,K2为四相八拍。
(2)K3-K4作为启动和方向控制。
(3)正转时红色指示灯亮,反转时黄色指示灯亮,不转时绿灯亮。
(4)可通过键盘设定步进电机步数给定值。
(5)用三位LED数码管显示剩余工作步数
三、系统总体框图与原理说明
通过键盘模块设置步进电机的工作模式、步数以及正反转,同时用数码管模块显示剩余工作步数,用LED灯模块显示步进电机的工作状态。
4*4键盘模块:
采用外部中断的方式实时扫描键盘,判别按下的键,并执行所按下的键相应的操作,即输入步数、选择工作模式、正/反转、调速以及启动/停止等,由于键数的限制,把一些键功能复用。
用线反转法扫描键盘,即先在P2口输出0xf0,二次确认有按键按下后,逐行输出低电平,确认按键所在的列,便可知道所按下的是哪个键,再返回对应的键值。
数码管显示模块:
采用定时中断的方式定时扫描一次显示,从而实现数码管的动态显示,同时P0口需外接上拉电阻。
本设计采用共阴数码管,故0到9的段码为:
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
四相步进电机模块:
采用L298驱动芯片驱动电机,同时P1口驱动能力不够,需外接上拉电阻,通过四个LED灯接在P1.0到P1.3口来观察电机的拍子。
据分析可得到,四相单四拍:
A->B->C->D;四相双四拍:
AB->BC->CD->DA;四相八拍:
A->AB->B->BC->C->CD->D->DA
LED灯模块:
把红黄绿三个灯接在P3口上,在程序中通过置位复位来实现相应状态的转换。
图1为系统总体设计方框图,由单片机AT89C51,L298驱动芯片,四相步进电机,7段LED数码管等一些电路模块组成。
图1系统总体框图
四、硬件电路图
此次我们所设计的是一个步进电机控制系统,主要由单片机AT89C51、四相步进电机、7段数码管、LED灯、L298驱动芯片及一些其他相关元件设计而成。
可以通过键盘来控制系统的输入步数、选择工作模式、正/反转、调速以及启动/停止工作。
运转时,用3位7段数码管来输出生育工作步数。
最后根据思路所设计出来的硬件电路图如下。
图2系统的硬件电路图
五、程序流程图
六、仿真说明
上电后,电机步数为0,默认为四相单四拍、正转的工作模式,红、绿灯亮,数码管显示0,输入步数,数码管显示步数,选择工作模式,设置正/反转,相应的指示灯亮,并启动后,绿灯灭,电动机开始按设定的模式工作,数码管显示剩余的工作步数,运行时,可通过加速和减速按键进行电机的调速,按下停止按键后,电机停止工作,数码管显示停止时剩余的工作步数,当步数减到0后,电机停止工作,数码管显示0。
七、心得体会
在设计的过程中,学会了很多东西,熟悉了步进电机控制系统的整体运行过程和总体布局,掌握了该硬件电路的设计方法,掌握了步进电机控制系统程序的设计和调试,最大的收获便是学会了如何把C语言应用于单片机得编程上,避免了汇编的低效率的缺点。
附录:
程序清单
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
ucharcodedisp[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};//共阴数码管显示码
ucharcodetable1[]={0x01,0x02,0x04,0x08,
0x08,0x04,0x02,0x01};//单四拍
ucharcodetable2[]={0x03,0x06,0x0c,0x09,
0x09,0x0c,0x06,0x03};//双四拍
ucharcodetable3[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09,
0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//四相八拍
uchar*p=NULL;//表指针
ucharpaishu=0,qibu=0,start=0;
uintspeed=100;//设置转速
uintdat1=0,count=0;//拍数
sbitweg=P3^0;//个位位选
sbitwes=P3^1;//十位位选
sbitweb=P3^3;//百位位选
sbitk31=P3^5;//正转指示灯
sbitk32=P3^6;//反转指示灯
sbitk4=P3^7;//停止指示灯
voidinit();
voiddisplay_3(uintdat);
voidDelay1ms(unsignedintcount);
ucharkeybscan(void);
ucharkeyaction(void);
/*1ms延时子程序*/
voidDelay1ms(unsignedintcount)
{
unsignedinti,j;
for(i=0;ifor(j=0;j<100;j++);
}
/*键盘扫描子程序*/
ucharkeybscan(void)
{ucharscode,rcode;
P2=0xf0;
if((P2&0xf0)!
=0xf0)
{
Delay1ms
(1);
if((P2&0xf0)!
=0xf0)
{
scode=0xfe;
while((scode&0x10)!
=0)
{
P2=scode;
if((P2&0xf0)!
=0xf0)
{
rcode=(P2&0xf0);
return(scode+rcode);
}
else
scode=(scode<<1)|0x01;
}
}
}
return(0xfe);
}
/*返回键码子程序*/
ucharkeyaction(void)
{
switch(keybscan())
{
case0xfe:
return('#');break;//无按键则返回
case0xde:
return(0);break;//第一行第一列按键编码
case0xce:
return
(1);break;//第一行第二列按键编码
case0xae:
return
(2);break;
case0x6e:
return(3);break;
case0xdd:
return(4);break;
case0xcd:
return(5);break;
case0xad:
return(6);break;
case0x6d:
return(7);break;
case0xdb:
return(8);break;
case0xcb:
return(9);break;
case0xab:
return(10);break;
case0x6b:
return(11);break;
case0xd7:
return(12);break;
case0xc7:
return(13);break;
case0xa7:
return(14);break;
case0x67:
return(15);break;//第四行第四列按键编码
}
}
/*3位数显示子程序*/
voiddisplay_3(uintdat)
{
P0=0;
P0=disp[dat/100%10];//3位
web=0;
Delay1ms
(1);
web=1;
P0=0;
P0=disp[dat/10%10];//2位
wes=0;
Delay1ms
(1);
wes=1;
P0=0;
P0=disp[dat%10];//1位
weg=0;
Delay1ms
(1);
weg=1;
}
/*定时器0初始化子程序*/
voidinit()
{
TMOD=0x01;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET0=1;
TR0=1;
}
/*定时器0中断程序*/
voidtimer0()interrupt1
{
TH0=(65536-10000)/256;//每10ms扫描显示
TL0=(65536-10000)%256;
display_3(count);//显示剩余步数
}
/*外部中断0中断程序*/
int0()interrupt0using0
{
EA=0;//关中断
if(start==0)
{
switch(keyaction())
{
case0:
{dat1=dat1*10+0;count=dat1;}break;
case1:
{dat1=dat1*10+1;count=dat1;}break;
case2:
{dat1=dat1*10+2;count=dat1;}break;
case3:
{dat1=dat1*10+3;count=dat1;}break;
case4:
{dat1=dat1*10+4;count=dat1;}break;
case5:
{dat1=dat1*10+5;count=dat1;}break;
case6:
{dat1=dat1*10+6;count=dat1;}break;
case7:
{dat1=dat1*10+7;count=dat1;}break;
case8:
{dat1=dat1*10+8;count=dat1;}break;
case9:
{dat1=dat1*10+9;count=dat1;}break;
case10:
{p=&table1[0];break;}//单四拍
case11:
{p=&table2[0];break;}//双四拍
case12:
{p=&table3[0];break;}//四相八拍
case13:
{qibu=0;
if(p==(&table3[0]))
paishu=8;
else
paishu=4;
k31=1;k32=0;break;}//正转
case14:
{if(p==(&table3[0]))
{qibu=8;paishu=16;}
else
{qibu=4;paishu=8;}
k31=0;k32=1;break;}//反转
case15:
{start=1;k4=0;break;}//启动标志
case'#':
break;//无按键按下
}
}
else
switch(keyaction())
{
case0:
if(speed<20000)speed+=10;break;//减速
case1:
if(speed>10)speed-=10;break;//加速
case15:
start=0;k4=1;break;
}
EA=1;//开中断
}
voidmain()
{
uinti=0;
p=&table1[0];
qibu=0;
paishu=4;
k31=1;//默认模式为单四拍,正转
k32=0;
k4=1;
init();
EA=1;//开总中断
IT0=1;//设置外部中断0为边沿触发方式,下降沿有效
EX0=1;//开外部中断0
P2=0xf0;
Delay1ms
(1);
while(!
start)P2=0xf0;//等待启动信号
i=qibu;
while
(1)
{
P2=0xf0;
while(count)
{
P2=0xf0;
if(i>=paishu)i=qibu;
if(start==1)
P1=p[i];
else
while(!
start)P2=0xf0;//等待启动信号
Delay1ms(speed);
i++;
count--;
}
}
}