/*********************************************************************************************
程序名: FL-08 电机MCPU主程序
编写人: 李坤学
编写时间: 2010年10月1日
硬件支持: STC11F04 12MHz
接口说明: P1口接电机输出线,
控制标说明: 01:电机走一步
02:按步数工作用加减速操作
03:电机复位工作
04:关电机输出并设置电机工作速度
修改日志: (1); 2010年10月6号完成
(2); 2010年10月18号增加了读取内部坐标的功能
(3); 2010年10月19号增加了T轴电机连续旋转的功能
(4); 2010年12月09号增加了电机坐标处理函数
(5); 2011年02月03日,重写部份工作函数
(6); 2011年05月24日,加入电机加速时间控制
/*********************************************************************************************/
#include <STC11Fxx.H> //STC11系列头文件
#include <absacc.h> //绝对地址的访问
#define M_data P1 //定义电机输出口
idata unsigned int RDDH=0;
data unsigned int Mo_data=0;//定义电机坐标变量
data unsigned char Motor_t=0;//定义电机编码变量
data unsigned char CBB=0;//定交电机半流时间变量
data unsigned char CMM=0;//定义电机速度变量,初值设为01
data unsigned char MTdata =0; //定义同花参数变量
data unsigned char Mii =1; //定义电机标志
data unsigned char Mx =6; //电初加速初始速度
data unsigned char SP_dat; //定义SP值副本值
bdata bit MIIM=0; //定义电机脉冲输出标志
bdata bit Mot=1; //定义电机方向标志位,并付初值为1 电机正转
bdata bit Moc=1; //定义通信标志
bdata bit MOTT=1; //定义计数中断标志位
sbit MRET = P1^0; //光电信号输入口
//sbit BF = P3^7; //应答信号线,数据接收标志
sbit RW = P3^3; //MCPU选通线
sbit MBB = P3^4; //电机脉冲输出线
sbit LED = P1^2; //工作指示灯
sbit MOIC = P1^3; //电机电流控制线
sbit CLK = P3^0; //时钟线
sbit IO_data = P3^1; //读写控制线,及数据线
sbit RETI = P3^2; //外中断复位线
alien void MOTOR_RETI(); //定义复位汇编函数
void MOTOR(); //电机走一步子函数
void MOTORDEL(unsigned int a);//步进电机加减速工作函数
void MOTORH(void); //电机复位函数
/****************************************************************************************************
函数名:延时函数
调 用:DELAYR (?);
参 数:
返回值:无
结 果:占用CPU方式延时与参数数值相同的毫秒时间
/****************************************************************************************************/
void DELAY (unsigned int j)
{
while(j)j--;
}
/***************************************************************************************************
函数名:步进电机正反转一步
调 用:MOTOR()
参 数:Mot=0,电机反转一步 ,Mot=1电机正转
返回值:无
结 果:电机坐标 Motor 自动加一或减一,电机走一步
***************************************************************************************************/
void MOTOR(void){ //步进电机正反转一步子程序
code unsigned char MOTOR_DB[]={0x00,0xb0,0x90,0xd0,0x50,0x70,0x60,0xe0,0xa0,0x00};//定义电机输出编码
unsigned char i;
MOIC=0; //开电机电流
i=0; //电机输出编码初值设00
CBB=10; //设减小电机电流时间设为10
if(Mot==1)Mo_data++;
else{if(Mo_data!=0)Mo_data--;}//如果电机反转,并且当前电机坐标不小于1时,坐标减一
while(1)
{
if(Mot)Motor_t ++;//当前电机输出编码加一指向下一编码
else Motor_t --;//电机输出编码减一
i=MOTOR_DB[Motor_t]; //取电机输出编码
if(i!=0)break;
else{
if(Mot)Motor_t=0;
else Motor_t=9;
}
}
i=i&0xf8; //屏蔽低3位,高5位不变
M_data=M_data&0x07;//屏蔽P1口的高5位,低3位不变
M_data=M_data|i; //高5位送P1口,P1口的低3位不变
}
/*******************************************************************************************
函数名:MEdelayr 步进电机加减速延时函数
调 用:MEdelayr(k,i);
参 数:k电机编号,i加速指针
返回值:无
结 果:步进电机工作延时
/*******************************************************************************************/
void MEdelayr(unsigned int j) //起动定时器1子函数
{
code unsigned int MOTOR_DB1[]={ //步进电机工作加减速时间表
600,600,590,590,580,580,570,570,560,560,550,550,540,540,530,530,520,520,510,510, //1
500,500,490,490,480,480,470,470,460,460,450,450,440,440,430,430,420,420,410,410, //2
400,395,390,385,380,375,370,365,360,355,350,345,340,335,330,325,320,315,310,305, //3
301,298,295,292,289,286,283,280,277,274,271,268,265,262,259,256,253,250,247,244, //4
240,237,234,231,228,225,222,219,216,213,210,207,204,201,198,195,192,189,186,183, //5
180,177,174,171,168,165,162,159,156,153,150,150,147,144,141,138,135,132,130,128, //6
126,124,122,120,119,118,117,116,115,114,113,112,111,110,109,108,108,108,108,108, //7
107,107,106,106,105,105,104,104,103,103,102,102,102,101,101,101,100,100,100,100, //8
99,99,98,98,97,96,96,96,95,95,95,94,94,94,94,93,93,93,92,92, //9
92,91,91,91,90,90,90,89,89,89,88,88,88,87,87,87,86,86,86,85, //10
85,85,85,84,84,84,83,83,83,82,82,82,81,81,81,80,80,80,79,79, //11
79,78,78,78,76,76,76,75,75,75,74,74,74,73,73,73,72,72,72,71, //12
71,71,71,70,70,70,70,69,69,69,69,68,68,68,68,67,67,67,67,66, //13
66,66,66,65,65,65,65,64,64,64,64,63,63,63,63,62,62,62,62,60, //14
60,60,60,60,60,60,60,60,60,60,59,59,59,59,59,59,59,59,59,59, //15
59,59,59,59,59,59,59,59,59,59,58,58,58,58,58,58,58,58,58,58, //16
58,58,58,58,58,58,58,58,58,58,57,57,57,57,57,57,57,57,57,57, //17
57,57,57,57,57,57,57,57,57,57,56,56,56,56,56,56,56,56,56,56, //18
};
j=MOTOR_DB1[j]+CMM; //查表取加速时间与电机设定速度值相加
MOTOR();//步进电机走一步
if(MIIM)MBB=0; //输出脉冲
for(;j>0;j--);
MBB =1; //复位电机脉冲
}
/*******************************************************************************************
函数名:MOTOR_ttz T轴与Z轴,步进电机按坐标加减速方试工作
调 用:MOTOR_ttz(k,a)
参 数:MDATA 是电机工作参数
返回值:无
结 果:电机坐标自动加一或减一,电机走一步
*******************************************************************************************/
void MOTORDEL(unsigned int dat){//步进电机加减速工作子程序
unsigned int k1,k2,k3,k4; //定义加速总步数,减速总步数变,及加速指针变量
if(dat<5){k1=0;k3=0;k2=dat;}
else{
if(dat>680){k1=340;k3=340;k2=dat-680;}//电机步数大于加减速步数的情况
else{k1=dat/2;k2=0;k3=dat-k1;}//电机步数小于或等于加减速步数的情况
}
k4=0;//加速指针初值设为0
for(;k1>0;k1--){MEdelayr(k4);k4++;} //加速工作
for(;k2>0;k2--){MEdelayr(k4);} //恒速工作
for(;k3>0;k3--){MEdelayr(k3);} //减速工作
CMM=0; //电加速时间清零
}
/***************************************************************************************************
函数名:步进电机复位子程序
调 用:MOTORH ()
参 数:k,电机标志.x,同花位移参数,如果等于100,则不作同花调整
返回值:无
结 果:处理电机复位工作
备 注:检测光电输出信号,完成电机坐标初始化工作
MTdata 同花参数变量
Mii 电机标志
/**************************************************************************************************/
void Motorh(void){
unsigned int k,a;
MRET=1;//初始化复位检测线
DELAY(1000);
if(Mii==1) //如果是T电机标志
{
k= Mo_data % 800; //取T轴电机位置坐标
a= MTdata+5; //计算检测位置偏移量
if(k>400)
{
Mot=1; //设电机正转
MOTORDEL((800-k)+a);//电机正转走到零坐标
while(MRET==0)MEdelayr(0); //电机走到检测点上
}
else{
if(k>a)
{
Mot=0;//设电机反转
MOTORDEL((k-a)-5); //电机反转走到零坐标
while(MRET==0)MEdelayr(0); //电机走到检测点上
}
else{
Mot=1; //设电机正转
while(MRET==0)MEdelayr(0); //电机走到检测点上
}
}
Mot=0;//设电机反转
while(MRET==1)MEdelayr(0);//电机反转离开测试点
for(k=a;k>0;k--)MEdelayr(0);//电机反转,走到完同花位移参数
}
else{
if(Mo_data>20){Mot=0; MOTORDEL(Mo_data-15);} //电机走到复位点减15步的坐标上
Mot=0;//设电机反转
while(MRET==0)MEdelayr(0);//电机反转复位
}
Mo_data=0;//电机坐标清零,完电机电机复位工作
}
/***************************************************************************************************
函数名:工作函数
调 用:SPII();
参 数:无
返回值:无
结 果:外中断反回函数
/**************************************************************************************************/
void SPII_MOTOR(void) {
unsigned char k,j,dat;
unsigned int x;
unsigned char s[4];
SP= SP_dat; //重设SP初值
EA =1; //CPU开中断
TR0 =1; //定时器启动
while(1)
{
RW=1;MBB=1;IO_data=1; //初始化选通及脉冲输出线等CPU选通
if(RW==0) //等待主CPU选通!
{
DELAY(8); //延迟一段时间
if(RW==0)
{
TR0=0;LED=0;RW=0; //关闭定时器,开工作指示灯,并应答主CPU
if(IO_data)
{ //发送电机坐标
x= Mo_data; //取电机坐标
for(j=0;j<16;j++)
{
while(CLK==1); //等时钟线变低
IO_data=x&0x01; //将最低位数据送到选通线上
while(CLK==0); //等时钟线变高
x>>=1; //要传送的数据左移一位
}
IO_data=1; //置位数据线
}
else{
for(k=0;k<4;k++)
{
dat=0; //清接收临时变量清零
for(j=8;j>0;j--)
{
while(CLK==1); //等时钟线变低
IO_data=1; //初始化数据线
dat>>=1; //接收数据的最高位左移一位
if(IO_data)dat+=0x80; //取数据线上的数据
while(CLK==0); //等时钟线变高
DELAY(1); //延时1个机器周期
}
s[k]= dat; //保存数据
}
IO_data=1; //置位数据线
k=s[0]; //取功能控制参数
Mot=k&0x80; //取电机方向
MIIM=k&0x40; //取电机脉冲输出标志
k&=0x0f; //取控制指令
CMM =s[1]; //取电机工作速度
switch(k) //取控制参数变量
{
case 1: MOTOR();break;//调用电机走一步子程序
case 2: {
x= s[2]*256+s[3];//取电机工作步数
MOTORDEL(x);//将收到的电机工作步数送电机加速工作程序
};break;//电机按步数工作
case 3: Motorh();break;//电机复位
case 4: { //关闭电机工作电流
MTdata =s[2]; //取同花参数变量
Mii = s[3]; //取电机标志
Moc=0;//置正常通信标志
M_data=M_data|0xf0;//关闭电机输出
}break;
}
}
TR0=1; //开定时器
}
}
}
}
/***************************************************************************************************
函数名:主函数
调 用:main
参 数:无
返回值:无
结 果:外中断反回函数
备 注:主函数工作后,将工作函数的入口地址保存于变量 RDDH中
/**************************************************************************************************/
void main(void) { //主程序
RDDH=(void*)SPII_MOTOR; //取SPII_MOTOR工作函数的地址作为复位反回地址
TMOD =0x11;
TH0 =0x00;
TL0 =0x01;
IE =0x83; //定义中断控制
IP =0x08; //定义优先中断权为定时器T1
TCON =0x01; //定义外中断INT0为负缘触发方试
SP_dat=SP; //SP值存副本
SPII_MOTOR();
}
/***************************************************************************************************
函数名:外部中断INT0中断处理程序
调 用:[外部引脚INT0中断处理]
参 数:无
返回值:无
结 果:用户处理外部中断信号
备 注:
/**************************************************************************************************/
void INT_0 (void) interrupt 0 using 0 { //切换寄存器组到0 注在特殊情况下,必需设为0组寄存器.
EA =0; //关中断
if(RETI==0)//判断是否有复位脉冲
{
DELAY(800);
DPH=RDDH/256; //将复位地址装入DPTR中
DPL=RDDH%256;
MOTOR_RETI(); //调用复位汇编程序
}
else{EA=1;}//开外中断使能
}
/***************************************************************************************************
函数名:记数器中断处理函数
调 用:无
参 数:无
返回值:无
结 果:改变电机输出电流,
/**************************************************************************************************/
void name (void) interrupt 1 using 1
{
TH0 = 0x00;
TL0 = 0x05;//定时器付初值
if(MOIC==0)
{
if(CBB!=0)CBB--; //判断半流时间计数器是否为0!
else MOIC=1;//置电机半流工作方试
}
if(Moc==0)LED=!LED; //判断当前是否与主CPU通信过//指示灯输出取反
else LED=0; //关闭指示灯
}
/***************************************************************************************************
函数名:定时中断1中断处理程序
调 用:
参 数:无
返回值:无
结 果:步进电机工作延时
备 注:
/**************************************************************************************************
void name1(void) interrupt 3
{
TR1 =0;//关闭计数器T1
MOTT =0;//置中断标志
}
/**************************************************************************************************
坤学自动化工作室
2011-06-25
likunxue@126.com
**************************************************************************************************/
|