📄 main.c
字号:
#include <AT89X52.H>
#include <absacc.h>
#include <math.h>
#include <stdlib.h>
#define uchar unsigned char
#define uint unsigned int
#define Ram XBYTE[0x2000]
#define Rom XBYTE[0x4000]
//画线****************************
#define zheng 1 //收缩
#define fan 0 //释放
#define one_step 0.010
#define time_count 20000 //定时常数
//*****************************
extern void delay(uint dtime);
/*串口操作 ************************* ******************************/
extern char getbyte(void); //从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。
extern putbyte(char c); //放入一个字节到发送缓冲区
extern putstring(uchar *puts); //发送一个定义在程序存储区的字符串到串口
extern putbytes(uchar *outplace,uint j);//放一串数据到发送缓冲区,需要定义发送的字节数
extern puthex(uchar c); //发送一个字节的hex码,分成两个字节发。
extern bit inbufsign; //串口接收到数据标志
extern void serial_init (void); //串口初始化
#define CR putstring("\r\n") //发送一个回车换行
#define XIAN 1
#define YUAN 2
#define QUXIAN 3
/*液晶操作***/
extern void lcd_cls(void); //清屏
extern void lcd_string(uchar attr,uchar *string); //显示字符串
extern void Set_module_light(uchar module);
//extern void lcd_cursor(uchar x, uchar y);
//8279操作
extern void init8279();
//**********键盘操作
extern uchar data key;
//画线函数定义
uchar shape=0;
uint xdata num0 _at_ 0x209b;
uint xdata num1 _at_ 0x20a1;
uchar xdata state _at_ 0x20b0;
float xdata l_xishu _at_ 0x2008;
float xdata r_xishu _at_ 0x2010;
float xdata xstart _at_ 0x2016;
float xdata ystart _at_ 0x201b;
float xdata xend _at_ 0x2020;
float xdata yend _at_ 0x2026;
float xdata xcur _at_ 0x202b;
float xdata ycur _at_ 0x2030;
uchar xdata direction_l _at_ 0x2040;
uchar xdata direction_r _at_ 0x2042;
static uchar xdata keystr[2][4] _at_ 0x2072;
static uchar xdata count _at_ 0x207b,isy _at_ 0x207c;
uchar xdata x_temp _at_ 0x2100;
uchar xdata y_temp _at_ 0x2102;
uchar xdata xystr[3] _at_ 0x2103;
double xdata pt1_x _at_ 0x2200,pt1_y _at_ 0x2208,
pt2_x _at_ 0x2210,pt2_y _at_ 0x2218,
temp _at_ 0x2220, motorl_step _at_ 0x2228,
motorr_step _at_ 0x2230;
uint xdata timer0_l _at_ 0x2068,timer1_l _at_ 0x206c;
uint data timer1_r;
void GetPCdata()
{
if(inbufsign!=1)
return;
if(getbyte() == 0x05);
{
key=getbyte();
// sdkey=key;
}
}
// uchar sdkey;
//左电机正转函数
void step0_z(uchar i)
{
switch(i)
{
case 0:
P1_0=0;
P1_1=0;
break;
case 1:
P1_0=1;
P1_1=0;
break;
case 2:
P1_0=1;
P1_1=1;
break;
case 3:
P1_0=0;
P1_1=1;
break;
}
}
//左电机反转函数
void step0_f(uchar i)
{
switch(i)
{
case 0:
P1_0=0;
P1_1=1;
break;
case 1:
P1_0=1;
P1_1=1;
break;
case 2:
P1_0=1;
P1_1=0;
break;
case 3:
P1_0=0;
P1_1=0;
break;
}
}
//右电机正转函数
void step1_z(uchar i)
{
switch(i)
{
case 0:
P1_2=0;
P1_3=0;
break;
case 1:
P1_2=1;
P1_3=0;
break;
case 2:
P1_2=1;
P1_3=1;
break;
case 3:
P1_2=0;
P1_3=1;
break;
}
}
//左电机反转函数
void step1_f(uchar i)
{
switch(i)
{
case 0:
P1_2=0;
P1_3=1;
break;
case 1:
P1_2=1;
P1_3=1;
break;
case 2:
P1_2=1;
P1_3=0;
break;
case 3:
P1_2=0;
P1_3=0;
break;
}
}
//上面的变量赋初值后调用下面函数计算电机应走的步数以及方向
void shoudong()
{
// GetPCdata();
P0=0xff;
//timer0_l=10000;
//timer1_r=10000;
motorl_step=1000;
motorr_step=1000;
if(!P0_0)direction_l=1;
if(!P0_1)direction_l=0;
if(!P0_0||!P0_1)TR0=1;else TR0=0;
if(!P0_2)direction_r=0;
if(!P0_3)direction_r=1;
if(!P0_2||!P0_3)TR1=1;else TR1=0;
}
float dis;
displayxy()
{
while(state)
if(!(num0%10)||!(num0)%7)
{
dis=(pt1_x+(pt2_x-pt1_x)*num0/motorl_step);
xystr[0]=dis/10+48;
xystr[1]=(int)dis%10+48;
xystr[2]='\0';
lcd_cls();
lcd_string(0,"\r\nX: ");
lcd_string(0,xystr);
lcd_string(0," cm");
dis=(pt1_y+(pt2_y-pt1_y)*num0/motorl_step);
xystr[0]=dis/10+48;
xystr[1]=(int)dis%10+48;
xystr[2]='\0';
lcd_string(0,"\r\nY: ");
lcd_string(0,xystr);
lcd_string(0," cm");
}
// shoudong();
}
void line()
{
// temp=0;
motorr_step=
(sqrt((95-pt2_x)*(95-pt2_x)+
(115-pt2_y)*(115-pt2_y))-
sqrt((95-pt1_x)*(95-pt1_x)+
(115-pt1_y)*(115-pt1_y))-
(pt2_x-40)*0.001)
/one_step;//右电机应走的步数
motorl_step=(sqrt((pt2_x+15)*(pt2_x+15)+(115-pt2_y)*(115-pt2_y))
-sqrt((pt1_x+15)*(pt1_x+15)+(115-pt1_y)*(115-pt1_y))-
(pt2_x-40)*0.001)/one_step;//左电机应走的步数
if(motorl_step<0)
direction_l=zheng;
else
direction_l=fan;
if(motorr_step<0)
direction_r=zheng;
else
direction_r=fan;
motorl_step=abs(motorl_step);
motorr_step=abs(motorr_step);
temp=motorl_step/motorr_step;
l_xishu=1;
r_xishu=temp;
TR0=1;
TR1=1;
state=1;
}
void timer0_init()
{
timer0_l=time_count*l_xishu;
TMOD=0x01; //设定定时器的工作方式//左电机
TH0=(65536-timer0_l)/256;
TL0=(65536-timer0_l)%256;
ET0=1;
EA=1;
}
void timer1_init()//定时1毫秒
{
timer1_l=time_count*r_xishu;
TMOD=0x11; //设定定时器的工作方式//右电机
TH1=(65536-timer1_l)/256;
TL1=(65536-timer1_l)%256;
ET1=1;
EA=1;
//IE复位后的状态 0X0000B
}
void time0_1ms() interrupt 1//左电机定时
{
uint data timer0_l=time_count*l_xishu;
TH0=(65536-timer0_l)/256;
TL0=(65536-timer0_l)%256;
if(direction_l==zheng)
step0_z(num0%4);
else
step0_f(num0%4);
if(num0>=motorl_step)
{
TR0=0;
num0=0;
state=0;
}
else
{
num0++;
}
}
void time1_1ms() interrupt 3//右电机定时
{
timer1_r=time_count*r_xishu;
TH1=(65536-timer1_r)/256;
TL1=(65536-timer1_r)%256;
if(direction_r==zheng)
step1_z(num1%4);
else
step1_f(num1%4);
if(num1>=motorr_step)
{
TR1=0;
num1=0;
state=0;
}
else
{
num1++;
}
}
//**********************
uchar data KeyFuncIndex = 0;//当前状态
//状态函数开始
void start1()
{
lcd_cls();
lcd_string(1,"定点\r\n");//背光显示
lcd_string(0,"矩形\r\n");
lcd_string(0,"三角\r\n");
lcd_string(0,"圆形\r\n");
lcd_string(0,"循迹\r\n");
}
void start2()
{
lcd_cls();
lcd_string(0,"定点\r\n");//背光显示
lcd_string(1,"矩形\r\n");
lcd_string(0,"三角\r\n");
lcd_string(0,"圆形\r\n");
lcd_string(0,"循迹\r\n");
}
void start3()
{
lcd_cls();
lcd_string(0,"定点\r\n");//背光显示
lcd_string(0,"矩形\r\n");
lcd_string(1,"三角\r\n");
lcd_string(0,"圆形\r\n");
lcd_string(0,"循迹\r\n");
}
//***************************
void start4()
{
lcd_cls();
lcd_string(0,"定点\r\n");//背光显示
lcd_string(0,"矩形\r\n");
lcd_string(0,"三角\r\n");
lcd_string(1,"圆形\r\n");
lcd_string(0,"循迹\r\n");
}
void start5()
{
lcd_cls();
lcd_string(0,"定点\r\n");//背光显示
lcd_string(0,"矩形\r\n");
lcd_string(0,"三角\r\n");
lcd_string(0,"圆形\r\n");
lcd_string(1,"循迹\r\n");
}
//********************************
void middle6()
{
lcd_cls();
lcd_string(0,"★设置终点坐标★\r\n");
shape=XIAN;
// lcd_string(0,"\r\nX: ");
// lcd_string(0,"\r\nY: cm");
}
//******************************
void middle7()//矩形
{
// lcd_cls();
// lcd_string(0," ★实时坐标显示★");
// lcd_string(0,"\r\n\r\nX: cm");
// lcd_string(0,"\r\nY: k cm");
/*
pt1_x=0;
pt1_y=0;
pt2_x=50;
pt2_y=30;
line();
while(state);
pt1_x=50;
pt1_y=30;
pt2_x=50;
pt2_y=70;
line();*/
}
void middle8()//三角
{
//lcd_cls();
//lcd_string(0," ★实时坐标显示★");
//lcd_string(0,"\r\n\r\nX: cm");
//lcd_string(0,"\r\nY: k cm");
/*
pt1_x=0;
pt1_y=0;
pt2_x=60;
pt2_y=0;
line();
displayxy();
// while(state);
pt1_x=60;
pt1_y=0;
pt2_x=0;
pt2_y=60;
line();
displayxy();
// while(state);
pt1_x=0;
pt1_y=60;
pt2_x=0;
pt2_y=0;
line();
displayxy();
*/
pt1_x=0;
pt1_y=0;
pt2_x=24;
pt2_y=38;
line();
displayxy();
// while(state);
pt1_x=24;
pt1_y=38;
pt2_x=62;
pt2_y=9;
line();
displayxy();
// while(state);
pt1_x=62;
pt1_y=9;
pt2_x=0;
pt2_y=0;
line();
displayxy();
}
//**********************
uchar xdata yuanptcount _at_ 0x20cd;
bit bdata yuanflag=1;
void middle9()
{
lcd_cls();
lcd_string(0,"★设置圆心坐标★\r\n");
//
//lcd_string(0," ★实时坐标显示★");
//lcd_string(0,"\r\n\r\nX: cm");
//lcd_string(0,"\r\nY: cm");
shape=YUAN;
}
void middle10()
{
//lcd_string(0,"\r\n\r\n 运行中...\r\n");
lcd_cls();
lcd_string(0,"★设置起点坐标★\r\n");
shape=QUXIAN;
}
void gif()
{
lcd_cls();
lcd_string(0,"\r\n 悬挂运动控制系统\r\n");
lcd_string(0,"\r\n 2005-9-13");
lcd_string(0,"\r\n待机");
return;
}
//**********************
typedef struct
{
uchar KeyStateIndex; //当前状态索引号
uchar KeyDnState; //按下"向下"键时状态索引号
uchar KeyUpState; //按下"向上"键时状态索引号
uchar KeyCrState; //按下"回车"键时状态索引号
uchar KeyCaState; //按下"取消"键时状态索引号
void (*CurrentOperate)(); //当前状态应该执行的功能操作
} KbdTabStruct;
void (*KeyFuncPtr)(); //按键功能函数指针
//************************
KbdTabStruct code KeyTab[]=
{//cur down up enter cancel curfunction
{0, 0, 0, 0, 0,(*gif)}, //开机画面
{1, 2, 5, 6, 1, (*start1)},
{2, 3, 1, 7, 2, (*start2)},
{3, 4, 2, 8, 3, (*start3)},
{4, 5, 3, 9, 4, (*start4)},
{5, 1, 4, 10, 5, (*start5)},
{6, 6, 6, 6, 1, (*middle6)},
{7, 7, 7, 7, 2, (*middle7)},
{8, 8, 8,8, 3, (*middle8)},
{9, 9, 9, 9, 4, (*middle9)},
{10, 10, 10, 10, 5,(*middle10)},
};
//状态函数结束
void yuan()
{
for(yuanptcount=0;yuanptcount<72;yuanptcount++)
{
pt2_x=40*cos(0.08726646*yuanptcount)*1.05+xend;
pt2_y=40*sin(0.08726646*yuanptcount)*0.95+yend;
if(yuanflag)
{
pt1_x=pt2_x;
pt1_y=pt2_y;
yuanflag=0;
}
line();
displayxy();
pt1_x=pt2_x;
pt1_y=pt2_y;
}
}
float qxtemp;
uchar qxcount;
bit bdata quxianflag=1;
void quxian()
{
while(1)
{
qxtemp=0;
if(quxianflag)
{
pt1_x=xend;
pt1_y=yend;
pt2_x=pt1_x;
quxianflag=0;
}
pt2_y=pt1_y+0.2;
if(!P1_4)qxtemp=-1.4;//,lcd_string(0,"z0");
// else lcd_string(0,"z1");
if(!P1_5)qxtemp=1.4;//,lcd_string(0,"y0");
//else lcd_string(0,"y1");
if(P1_6)qxcount++;//,lcd_string(0,"q1");
else qxcount=0;//,lcd_string(0,"q0");
if(qxcount>100)break;
// if(!P1_4||!P1_5)
pt2_x=pt1_x+qxtemp;
line();
displayxy();
while(state);
pt1_x=pt2_x;
pt1_y=pt2_y;
}
}
void GetKeyInput(void)
{
switch(key)
{
case 0x00:
return;
case 0xda://回车键
if(KeyFuncIndex==0)
return;
if(count)
{
keystr[isy][count]='\0';
count=0;
if(!isy)
{
xend=atoi(keystr[0]);
}
else
{
yend=atoi(keystr[isy]);
pt1_x=xstart;
pt1_y=ystart;
pt2_x=xend;
pt2_y=yend;
if(shape==XIAN)
line();
else if(shape==YUAN)
yuan();
else if(shape==QUXIAN)
quxian();
displayxy();
shape=0;
}
isy=!isy;
}
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyCrState;
break;
case 0xdc://开始循迹
lcd_cls();
lcd_string(0,"开始循迹");
break;
case 0xdb: //启动键
if(KeyFuncIndex==0)
KeyFuncIndex=1;
break;
case 0xd2://取消键
if(KeyFuncIndex<=5)
return;
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyCaState;
break;
case 0xc2://向上键
if(KeyFuncIndex==0)
return;
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyUpState;
break;
case 0xca://向下键
if(KeyFuncIndex==0)
return;
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyDnState;
break;
case 0xdd:
keystr[isy][count++]=48;
key=0;
lcd_string(0,"0");
return;
case 0xd5:
keystr[isy][count++]=49;
key=0;
lcd_string(0,"1");
return;
case 0xd4:
keystr[isy][count++]=50;
key=0;
lcd_string(0,"2");
return;
case 0xd3:
keystr[isy][count++]=51;
key=0;
lcd_string(0,"3");
return;
case 0xcd:
keystr[isy][count++]=52;
key=0;
lcd_string(0,"4");
return;
case 0xcc:
keystr[isy][count++]=53;
key=0;
lcd_string(0,"5");
return;
case 0xcb:
keystr[isy][count++]=54;
key=0;
lcd_string(0,"6");
return;
case 0xc5:
keystr[isy][count++]=55;
key=0;
lcd_string(0,"7");
return;
case 0xc4:
keystr[isy][count++]=56;
key=0;
lcd_string(0,"8");
return;
case 0xc3:
keystr[isy][count++]=57;
key=0;
lcd_string(0,"9");
return;
default: //按键错误的处理
return;
}
KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate;
(*KeyFuncPtr)();//执行当前按键的操作
key=0;
}
//*************************
void init_main()
{
serial_init();
init8279();
timer0_init();
timer1_init();
KeyFuncPtr=KeyTab[0].CurrentOperate;//开机画面
(*KeyFuncPtr)();//执行当前按键的操作
}
void main(void)
{
isy=0;
count=0;
xstart=0,ystart=0;
num0=0,num1=0;
state=0;
l_xishu=1;
r_xishu=1;
quxianflag=1;
init_main();
for(;;)
{
GetPCdata();
shoudong();
GetKeyInput();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -