基于51单片机的步进电机(坐标定位)
小型机床
1、使用2个步进电机,实现平面坐标定位
2、可以设置电机转速、坐标位置灯参数
3、步进电机驱动到指定坐标位置后蜂鸣器提示
#include "reg51.h"
#include "lcd1602.h"
#define uchar unsigned char
#define uint unsigned int
sbit k1=P3^0;//按钮
sbit k2=P3^1;
sbit k3=P3^2;
sbit AA1=P1^0;//电机1
sbit BB1=P1^1;
sbit CC1=P1^2;
sbit DD1=P1^3;
sbit AA2=P1^4;//电机2
sbit BB2=P1^5;
sbit CC2=P1^6;
sbit DD2=P1^7;
sbit beep=P3^3;//蜂鸣器
uchar speed=2;//速度
uint xx=0,yy=0;//位置
uchar flag1=0,flag2=0,wei1=0,wei2=0;//电机控制
uchar time=0;
uint sec=0,miao=0;
uchar disp1[]="sudu:000";
uchar disp2[]="X:000 Y:000 ";
uchar mode=0;
uchar start=0;//启动
uchar biao=0;
//按键检测
uchar key_scan()
{
uchar i,j;
i=0;
j=0;
P2=0x0f;
if(P2!=0x0f) //检测有无按下
{
switch(P2)//检测行
{
case 0x0e:i=1;break;
case 0x0d:i=5;break;
case 0x0b:i=9;break;
case 0x07:i=13;
}
P2=0xf0;
switch(P2)//检测列
{
case 0xe0:j=0;break;
case 0xd0:j=1;break;
case 0xb0:j=2;break;
case 0x70:j=3;
}
}
return i+j;
}
//主函数
void main()
{
uchar i=0;
init_1602();
TMOD|=0X01;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
while(1)
{
if((xx!=wei1)||(yy!=wei2))//启动蜂鸣器
{
biao=0;
}
else
{
if(biao==0)
{
biao=1;
miao=500;
start=0;
}
}
i=key_scan();//按键检测
if(start==0)
{
if(!k1)//模式切换
{
if(mode<3)
mode++;
else
mode=0;
while(!k1);
}
}
if(mode==1)//设置速度
{
if(!k2)
{
if(speed>0)
speed--;
while(!k2);
}
if(!k3)
{
if(speed<100)
speed++;
while(!k3);
}
}
if(i==11)//启动
{
start=1;
mode=0;
}
if(i==12)//暂停
{
start=0;
}
if(i==13)//左
{
if(xx>0)
xx--;
start=1;
while(wei1!=xx);
start=0;
}
if(i==14)//右
{
if(xx<999)
xx++;
start=1;
while(wei1!=xx);
start=0;
}
if(i==15)//上
{
if(yy>0)
yy--;
start=1;
while(wei2!=yy);
start=0;
}
if(i==16)//下
{
if(yy<999)
yy++;
start=1;
while(wei2!=yy);
start=0;
}
if(mode==2)//设置x
{
if((i>0)&&(i<11))
{
xx=(xx%100)*10+i-1;
while(P2!=0xf0);//等待按键松开
}
}
if(mode==3)//设置y
{
if((i>0)&&(i<11))
{
yy=(yy%100)*10+i-1;
while(P2!=0xf0);//等待按键松开
}
}
}
}
//定时器中断
void Timer0() interrupt 1
{
if(miao>0)//蜂鸣器控制
{
miao--;
beep=0;
}
else
beep=1;
if(start==1)
{
if(time<speed)
time++;
else
{
time=0;
//正转
if(wei1<xx)
{
switch(flag1)
{
case 0:BB1=1;break;
case 1:AA1=0;break;
case 2:CC1=1;break;
case 3:BB1=0;break;
case 4:DD1=1;break;
case 5:CC1=0;break;
case 6:AA1=1;break;
case 7:DD1=0;
}
if(flag1<7)//下一个状态
flag1++;
else
{
flag1=0;
wei1++;
}
}
if(wei1>xx) //反转
{
switch(flag1)
{
case 0:DD1=1;break;
case 1:AA1=0;break;
case 2:CC1=1;break;
case 3:DD1=0;break;
case 4:BB1=1;break;
case 5:CC1=0;break;
case 6:AA1=1;break;
case 7:BB1=0;
}
if(flag1<7)//下一个状态
flag1++;
else
{
flag1=0;
wei1--;
}
}
if(wei2<yy)
{
switch(flag2)
{
case 0:BB2=1;break;
case 1:AA2=0;break;
case 2:CC2=1;break;
case 3:BB2=0;break;
case 4:DD2=1;break;
case 5:CC2=0;break;
case 6:AA2=1;break;
case 7:DD2=0;
}
if(flag2<7)//下一个状态
flag2++;
else
{
flag2=0;
wei2++;
}
}
if(wei2>yy) //反转
{
switch(flag2)
{
case 0:DD2=1;break;
case 1:AA2=0;break;
case 2:CC2=1;break;
case 3:DD2=0;break;
case 4:BB2=1;break;
case 5:CC2=0;break;
case 6:AA2=1;break;
case 7:BB2=0;
}
if(flag2<7)//下一个状态
flag2++;
else
{
flag2=0;
wei2--;
}
}
}
}
//显示
if(sec<500)
sec++;
else
{
sec=0;
disp1[5]=(100-speed)/100+0x30;
disp1[6]=(100-speed)%100/10+0x30;
disp1[7]=(100-speed)%10+0x30;
disp2[2]=xx/100+0x30;
disp2[3]=xx%100/10+0x30;
disp2[4]=xx%10+0x30;
disp2[10]=yy/100+0x30;
disp2[11]=yy%100/10+0x30;
disp2[12]=yy%10+0x30;
write_com(0x0c);
write_string(1,0,disp1);
write_string(2,0,disp2);
if(start)
{
write_string(1,10,"on ");
}
else
{
write_string(1,10,"off");
}
//设置光标
switch(mode)
{
case 1:write_sfm(1,7);break;
case 2:write_sfm(2,4);break;
case 3:write_sfm(2,12);
}
if(mode>0)
write_com(0x0e);
else
write_com(0x0c);
}
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
}