单词量比较少,有时候需要变量名的时候真的是捉襟见肘 !
程序是在逻辑分析仪辅助下反复修改完成的,节省了大量时间,再次感谢下这30块不到的神器!
指针还不会用,目前就这个水平了,自己的目前主业不是程序员,但希望这可以成为主业!
以下程序还望大师多多指教!
/* 程序要求:
1:控制两个两相步进电机A,B运转;
2:转的时候要做到可以不共同开始,停的时候以各自的停止信号为准
3:有运转信号输入的时候要立马切断,上一周期的运转完成信号
4:在启动的时候马达会先转动一定的角度,避开检测开关的范围,之后才开始检测是否到位。
*/
#include <STC89C5xRC.H>
sbit StartM = P1^0; //开始运转信号
sbit StopA = P1^4; //A停止信号
sbit StopB = P1^6; //B停止信号
sbit TurnB = P2^4; //B马达脉冲输出 板子线路都焊死了懒得再改板子,就改程序了
sbit TurnA = P2^6; //A马达运转脉冲输出
sbit OK = P2^0; //两个电机都到位之后输出信号
sbit LED = P2^2; //程序运转指示灯
bit EnTimerA = 0,EnTimerB = 0; //电机延时开始计数使能
bit EnStartMA = 1, EnStartMB = 1; //电机延时结束输出位
unsigned int ta = 0 ,tb = 0,i = 0,n = 0;//电机延时指令计数变量ta,tb;i是扫描消抖变量,n是指示灯变量
//unsigned char Index = 0; //电机当前脉冲相位,用于不使用驱动器
//unsigned char BateCode[]={0x08,0x0a,0x02,0x06,0x04,0x05,0x1,0x09}; //不使用驱动器,步进电机电机运转参数
unsigned char StartMotor = 1, StopAMotor = 1,StopBMotor = 1,bate = 0,StartMotorbuf = 1;//启动,A停止,B停止,节拍,启动缓存
unsigned char StopAbuf = 0,StopBbuf = 0, KA = 1,KB = 1;//记录电机是否到位缓存 和一些变量
void SignalInput(); //信号消抖输出函数(使用是位移消抖)
void TurnMotor(); //马达运转函数,因为不需要倒转,所以么有添加倒转功能
void InitTimer0(); //启动定时器0;开启中断2ms定时
void BeatMotor(); //电机脉冲节拍,可以在此处调节脉冲宽度
void DelayStartMotor(); //电机启动延时函数
void main(void)
{
P0 = 0xff; //初始化,各数位置1
P1 = 0xff;
P3 = 0xff;
P2 = 0xff;
InitTimer0(); //初始化定时器
while(1)
{
if(n >= 250) //运转指示灯变量
{
n = 0;
LED = !LED;
}
}
}
void InitTimer0() //启动T0,初始化
{
TMOD = 0x01;
TH0 = 0xf8;
TL0 = 0xd0;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void BeatMotor() //节拍器.到时间后输出计时置位信号,此处可以调速,调脉冲占空比等参数
{
static unsigned char cnt = 0; //节拍器计时
cnt ++;
if(cnt <= 2 )
{
bate = 0;
}
if(cnt > 2)
{
bate = 1;
}
if(cnt > 4)
{
cnt = 0;
//Index ++;
}
/*if(Index >= 8) //用于不用驱动器的时候
{
Index = 0;
} */
}
void SignalInput() //按键消抖检测函数,48ms秒消抖。
{
static unsigned char StartBuf=0,StopABuf =0,StopBBuf=0 ;//(启动缓存,A停止缓存,B停止缓存,A之前状态,B之前状态)
StartBuf = (StartBuf<<1) | StartM; //通过位移消抖
if(StartBuf == 0x00 )
{
StartMotor = 0; //确认稳定后,输出启动信号
}
else StartMotor = 1; //信号必须敏感,不是0就是1。而且要及时变动
StopABuf = (StopABuf<<1) | StopA;
if(StopABuf == 0)
{
StopAMotor = 0; //输出A停止信号
}
else StopAMotor = 1;
StopBBuf = (StopBBuf<<1) | StopB;
if(StopBBuf == 0)
{
StopBMotor = 0; //输出B停止信号,0代表停止
}
else StopBMotor = 1;
}
void DelayStartMotor()
{
if(ta == 220) //200*2ms = 400ms = 0.4s;实测0.44s应该是误差,我是
{
EnTimerA = 0; //关闭计时使能
EnStartMA = 0; //延时结束,启动马达
}
if(tb == 220)
{
EnTimerB = 0; //关闭计数使能
EnStartMB = 0; //延时结束,输出启动马达信号
}
}
void TurnMotor() //电机运转函数,
{
static unsigned int i = 0,e = 0;
static unsigned char batebufa,batebufb;/*tmp,*/ //上半个脉冲高低电平的缓存,
if(StartMotorbuf != StartMotor) //对比电机运转使能信号是否发生变化
{ //有变化就说明本次周期结束,将电机电机转到位的信号缓存清零
StopAbuf = 0;
StopBbuf = 0;
}
if(StopAbuf == 0) //A电机无转到位信号的时候才允许运转
{
if(StartMotor == 0) //检测运转使能,有运转使能的时候
{
EnTimerA = 1; //打开延时计数器使能,ta 开始计
if(EnStartMA == 0) //当延时器时间到后输出信号。0
{
if(batebufa != bate) //当电平值不等于上一个值的时候
{
TurnA = bate; //A电机运转
i ++; //脉冲计数加1
KA = 0; //再次清零 运转完时成输出信号的 缓存数据
batebufa = bate; //保存上一个电平值,用来做对比;
}
if(i >= 250) //先走一定的步数,保证离开检测开关的检测范围
{
if((StopAMotor || StartMotor) == 0) //要求必须一直给运转使能,能允许输出转到位信号
{
i = 0; //脉冲计数清零
StopAbuf = 1; //A转到位的信号缓存;
KA = 1; //输出A到位
EnStartMA = 1; //关闭延时函数给的电机运转使能 ,等待下一周期
StartMotorbuf = StartMotor; //将启动使能信号另外保存,用以判断该信号是否有变化
}
}
}
}
else
{
EnTimerA = 0; //当使能信号有低到高发生变化之后,并且没有运转使能输进来
ta = 0; //的时候,将不开始运转延时的计时,并清零延时用的变量
}
}
if(StopBbuf == 0) // B运转函数。驱动器用
{
if(StartMotor == 0)
{
EnTimerB = 1;
if(EnStartMB == 0)
{
if(batebufb != bate)
{
TurnB = bate;
KB = 0;
e ++;
}
batebufb = bate;
if(e >= 250)
{
if((StopBMotor || StartMotor) == 0)
{
e = 0;
StopBbuf = 1;
KB = 1;
EnStartMB = 1;
StartMotorbuf = StartMotor;
}
}
}
}
else
{
EnTimerB = 0;
tb = 0;
}
}
/* 这个函数是没用步进电机驱动器,直接用单片机发数据;后来买了步进电机驱动器之后,只需要发脉冲。
这段就不需要了,这是个两相四线的步进电机驱动函数但是后面用驱动器之后就没给这个函数再做修改了;
if(StopBbuf == 0) // B运转函数。驱动板函数。
{
if(StartMotor == 0)
{
if(BateCode[Index] != tmp)
{
n ++;
} ;
tmp = BateCode[Index];
P2 = tmp;
if(n >= 25)
{
if((StopBMotor || StartMotor) == 0)
{
n = 0;
StopBbuf = 1; //B转到位的信号;
StartMotorbuf = StartMotor;
}
}
}
} */
if (KA && KB) //两个电机都到位的时候输出到信号供机械手使用。
{ //延时使能清零
OK = 0; //输出点P1.0
}
else OK = 1;
}
void Timer0Interrupt(void) interrupt 1
{
TH0 = 0xf9; //定时2ms初值
TL0 = 0x29;
BeatMotor(); //节拍函数
i ++;
if(i == 3)
{
i = 0;
SignalInput(); //信号输入消抖函数,消抖时间理论48ms,实测50ms,具体原因:没查,但可能不是误差
}
if(EnTimerA == 1) //运转信号输入后,电机延时运转计时使能
{
ta ++; //计时变量
if(ta < 2) //这个判断的作用是:运转信号输入后直接将电机到位信号切断,而不是到延时结束时再切断
{ //目的是为了避免重复将 K1 置 0 ;
KA = 0; //
}
}
if(EnTimerB == 1) //同A电机
{
tb ++;
if(tb < 2)
{
KB = 0;
}
}
DelayStartMotor(); //一个延时函数,可以分别调节两个电机的起始运转延时
n ++; //程序运转指示灯变量
TurnMotor(); //电机运转程序
}
|