📄 14_6.c
字号:
//C51单片机线切割机控制程序
//适用PHILIPS89C51RD2单片机,ROM内置、RAM外置,数码显示7位+7位共阴,键盘35只键
#include <reg51f.h> //Philips 89C51Rx+
#include <absacc.h>
#include <math.h>
#define XYPORT XBYTE[0x8003] //XY步进电机输出
signed long data m1 _at_ 0x10; //加工判别函数
signed long data n1 _at_ 0x14; //加工判别函数
union uni1
{
signed long s;
float f;
} freg1 _at_ 0x18,freg2 _at_ 0x1c;
bit cutting; //正在切割某一程序段标记,=0时为切割下一段作准备
bit q; //换象限标记
unsigned char bdata zw; //加工指令
sbit zw_bit0=zw^0; //=1 X-方向运动,=0 X+方向运动
sbit zw_bit1=zw^1; //=1 Y-方向运动,=0 Y+方向运动
sbit zw_bit2=zw^2; //=1 逆圆,=0 顺圆
sbit zw_bit3=zw^3; //=1 直线,=0 圆
sbit zw_bit4=zw^4; //=1 选择停标记
sbit zw_bit5=zw^5; //=1 凹曲线,=0 凸曲线
sbit zw_bit6=zw^6; //=1 4B格式,=0 3B格式
sbit zw_bit7=zw^7; //=1 GX,=0 GY
unsigned char bdata zw4;//暂存加工指令
unsigned char data aa;
unsigned char data bb;
unsigned char data ck;
unsigned long idata r; //加工半径,二进制绝对值
unsigned long data j; //加工时存放计数长度
signed long idata x0; //加工起点,二进制
signed long idata y0; //加工起点,二进制
signed long idata xe; //加工终点,二进制
signed long idata ye; //加工终点,二进制
unsigned char data ct;
unsigned char data xypnt; //X、Y步进电机相位寄存
signed int idata dltr; //补偿量
unsigned char xdata CUTTING_DATA[2501][13] _at_ 0x00EF;//外部RAM,存放切割程序
void error(void); //出错,报警,返回input
void input(void); //命令输入
void ndis(void); //清输入所有显示位
void X_output(void); //X 步进电机输出
void Y_output(void); //Y 步进电机输出
void display_j(unsigned long xy); //显示J计数
void get_cut_program(void); //从RAM中取出切割程序整理进切割缓冲区
unsigned char chz(unsigned char c1); //圆弧换象限
void chza(void); //切割加工中圆弧换象限
signed long bias(signed long xy1); //间隙补偿,偏移运算
void cut(void); //切割主程序
unsigned char back (unsigned char s); //步进电机环形分配器 逆时针转
unsigned char look (unsigned char s); //步进电机环形分配器 顺时针转
void open(void); //开脉冲源
void close(void); //关脉冲源
void output(void); //X、Y步进电机输出
void cutf(void); //双向插补子程序
main()
{
SP=0xA8;
AUXR|=0x02; //指向外部RAM
TMOD=0x20; //定时器0为方式0,定时器1为方式2
IP=0x02; //定时器中断0为高优先级
IT1=1; //变频中断下降沿触发
TL0=0x1A;TH0=0x8C; //定时器0的时间常数(2ms,11.0592MHZ) P89C51RD2 6时钟周期
TR0=1; //启动定时器0
IE=0xA3; //开放显示中断和定时器2中断
xypnt= 0x09; //定相(三相六拍)
output();
ndis(); //清显示
dltr=0; //默认补偿量=0
input(); //从键盘输入数据和命令
}
void cut(void) //切割主程序
{
cut1:get_cut_program(); //从内存中读入程序
if (zw_bit3==0) //圆弧
{
ACC=zw&0x0F;pp=P;
if (((pp==0)&&(x0==0))||((pp==1)&&(y0==0))) zw=chz(zw);//换象限
}
if (dltr!=0) //间隙补偿值不为零,需要间隙补偿
{
if ((zw_bit3==0)&&(r<abs(dltr))&&(bbb_bias_flag==0))
//圆弧半径小于补偿量时出错
{ //r<abs(dltr) 出错
error();
}
if (zw_bit6!=0) //直线与圆弧间隙补偿
{
x0=bias(x0); //x0,y0,j,r 偏移补偿运算
y0=bias(y0);
xe=bias(xe);
ye=bias(ye);
j=bias(j);
r=bias(r);
}
}
cut5: if (zw_bit3!=0) //直线
{
if (zw_bit0!=0) n1=-ye; else n1=ye; //L2,L3 / L1,L4
if (zw_bit1!=0) m1=xe; else m1=-xe; //L3,L4 / L1,L2
}
else
{ //圆弧,计算m1 m2 n1 n2初值
m1=y0+y0; //NR4,SR2,NR1,SR3
if (zw_bit1!=0) m1=-m1; //NR2,SR4,NR3,SR1
m1=m1+1;
n1=x0+x0; //NR4,SR2,NR3,SR1
if (zw_bit0!=0) n1=-n1; //NR1,SR3,NR2,SR4
n1=n1+1;
}
freg1.s=0; //初始F=0
cut6: cutf();
display_buffer1[11]=zw&0x0F; //显示加工指令
display_j(j); //显示j计数
if (j!=0) //判终点
{
cutf2: chza(); //圆弧,判别是否换象限
goto cut6; //继续插补下一步
}
else
{ //j=0,段号处理
zw4=zw; //暂存zw
if (zw_bit7==0) //双向终点判别,GY
{
while (x0!=xe)
{
if (x0<xe) zw&=0xFE;//x0+1-->x0
else zw|=0x01; //x0-1-->x0
X_output();
}
}
else
{
while (y0!=ye)
{ //GX
if (y0<ye) zw&=0xFD;//y0+1-->y0
else zw|=0x02; //y0-1-->y0
Y_output();
}
}
zw=zw4;
goto cut1;
}
close(); //切割完,关脉冲电源
}
void cutf(void) //八方向插补子程序
{
open(); //开脉冲源
freg2.s=freg1.s+m1; //走Y后的偏差
freg1.s=freg1.s+n1; //走X后的偏差
if (labs(freg1.s+freg1.s)<labs(freg2.s))
{
X_output(); //输出X
if (zw_bit7!=0) j--;
}
else
{
if (labs(freg2.s+freg2.s)<labs(freg1.s))
{
freg1.s=freg2.s;
Y_output(); //输出Y
if (zw_bit7==0) j--;
}
else
{
freg1.s=freg2.s+n1; //f=f+m1+n1
X_output(); //输出X,Y
Y_output();
j--;
}
}
}
void X_output(void) //X 步进电机输出
{
unsigned char s;
s=xypnt&0x07; //取出x相位(三相六拍)
if (zw_bit3==0) n1=n1+2;
if (zw_bit0==0)
{x0++;
s=look(s); //步进电机正走
}
else
{x0--;
s=back(s); //步进电机反走
}
xypnt&=0xF8; //将新的步进电机相位并入xypnt
xypnt|=s;
output(); //X 步进电机输出
}
void Y_output(void) //Y 步进电机输出
{
unsigned char s;
s=xypnt&0x38; //取出Y相位(三相六拍)
s>>=3; //(三相六拍)
if (zw_bit3==0) m1=m1+2;
if (zw_bit1==0)
{
y0++;
s=look(s);
}
else
{
y0--;
s=back(s);
}
s<<=3;
xypnt&=0xc7; //将新的步进电机相位并入xypnt
xypnt|=s;
output(); //Y 步进电机输出
}
void get_cut_program(void) //从RAM中取出切割程序整理进切割缓冲区
{
unsigned char data *c1;
void get_cut_program1(unsigned char data *c1,char s);//从RAM中取出3字节数据送进切割缓冲区
c1=&x0;
get_cut_program1(c1,0); //得到x0
c1=&y0;
get_cut_program1(c1,3); //得到y0
c1=&j;
get_cut_program1(c1,6); //得到j
c1=&r;
get_cut_program1(c1,9); //得到r
zw=CUTTING_DATA[sech1][12]; //得到zw
}
void get_cut_program1(unsigned char data *c1,char s) //从RAM中取出3字节数据送进切割缓冲区
{
unsigned char i;
*c1=0;
for (i=0;i<=2;i++) {c1++;*c1=CUTTING_DATA[sech1][i+s];}
}
signed long bias(signed long m1) //间隙补偿,偏移运算
{
bit b=0;
n1=abs(dltr);
if (m1<0) {m1=abs(m1);b=1;}
freg1.f=n1*m1; //化为浮点数
freg1.f=freg1.f/r;
getfreg1(); //四舍五入
n1=freg1.f; //化为长整型
if (dltr<0)
if ((zw_bit5)!=0) m1=m1+n1; //凹曲线
else m1=m1-n1; //凸曲线
else if ((zw_bit5)!=0) m1=m1-n1; //凹曲线
else m1=m1+n1; //凸曲线
if (b!=0) m1=-m1;
return(m1);
}
unsigned char chz(unsigned char c1) //圆弧换象限
{
ACC=c1&0x0F;
if (P==1) ACC^=0x01;
else ACC^=0x02;
c1&=0xF0;
c1|=ACC;
return(c1);
}
void chza(void) //切割加工中圆弧换象限
{
if (zw_bit3==0) //圆弧,判别是否换象限
{
ACC=zw&0x0F;pp=P;
if (((pp==0)&&(x0==0))||((pp==1)&&(y0==0)))
{
zw=chz(zw); //换象限
q=1; //设立换象限标记
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -