微机原理与接口技术课程设计报告
基于51单片机的步进电机控制系统
学号
姓名
班级 2011级电子2班
华侨大学电子工程系
摘要
步进电机是将电脉冲信号变换成角位移或直线位移的执行部件。步进电机可以直接用数字信号驱动,使用非常方便。步进电动机的角位移量和输入脉冲的个数严格成正比,在时间上与输入脉冲同步,因此只要控制输入脉冲的数量、频率及电动机绕组通电的相序,便可获得所需的转角、转速及转动方向。在没有脉冲输入时,在绕组电源的激励下气隙磁场能使转子保持原有位置处于定位状态。因此非常适合于单片机控制。它的运行速度和步距不受电源电压波动及负载的影响, 因而被广泛应用于数模转换、速度控制和位置控制系统。本课程设计以STC89C52单片机作为微控制器,使用混合式步进电机驱动芯片ULN2003AN进行驱动,实现了对步进电机运行状态的简单控制,并将其运行状态用LCD1602液晶显示。本次设计能实现的功能有电机运行、停止,设置运行圈数,调节转速,电机正反转,点动等。
关键词:STC89C52单片机,28BYJ-48步进电机,ULN2003AN驱动芯片,LCD1602显示,电机控制,点动
第一章 总体设计方案
本次课程设计本课程设计以STC89C52单片机作为微控制器,使用混合式步进电机驱动芯片ULN2003AN进行驱动,实现了对步进电机运行状态的简单控制,并将其运行状态用LCD1602液晶显示。本次设计能实现的功能有电机运行、停止,设置运行圈数,调节转速,电机正反转,点动等。
系统流程图如下:
第二章 硬件原理
一、 STC89c52单片机
2.1、STC89c52芯片简介
STC89C52是一个低功耗,高性能CMOS 8位单片机,片内含8k Bytes ISP(In-system programmable)的可反复擦写1000次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及STC89C52引脚结构,芯片内集成了通用8位中央处理器和ISP Flash存储单元,功能强大的微型计算机的STC89C52可为许多嵌入式控制应用系统提供高性价比的解决方案。
STC89C52具有如下特点:40个引脚,8k Bytes Flash片内程序存储器,256 bytes的随机存取数据存储器(RAM),32个外部双向输入/输出(I/O)口,5个中断优先级2层中断嵌套中断,2个16位可编程定时计数器,2个全双工串行通信口,看门狗(WDT)电路,片内时钟振荡器。
2.2、STC89c52芯片引脚功能说明
STC89C52RC引脚图
STC89C52RC引脚功能说明
VCC(40引脚):电源电压
VSS(20引脚):接地
P0端口(P0.0~P0.7,39~32引脚):P0口是一个漏极开路的8位双向I/O口。作为输出端口,每个引脚能驱动8个TTL负载,对端口P0写入“1”时,可以作为高阻抗输入。在访问外部程序和数据存储器时,P0口也可以提供低8位地址和8位数据的复用总线。此时,P0口内部上拉电阻有效。在Flash ROM编程时,P0端口接收指令字节;而在校验程序时,则输出指令字节。验证时,要求外接上拉电阻。
P1端口(P1.0~P1.7,1~8引脚):P1口是一个带内部上拉电阻的8位双向I/O口。P1的输出缓冲器可驱动(吸收或者输出电流方式)4个TTL输入。对端口写入1时,通过内部的上拉电阻把端口拉到高电位,这是可用作输入口。P1口作输入口使用时,因为有内部上拉电阻,那些被外部拉低的引脚会输出一个电流()。
P2端口(P2.0~P2.7,21~28引脚):P2口是一个带内部上拉电阻的8位双向I/O端口。P2的输出缓冲器可以驱动(吸收或输出电流方式)4个TTL输入。对端口写入1时,通过内部的上拉电阻把端口拉到高电平,这时可用作输入口。P2作为输入口使用时,因为有内部的上拉电阻,那些被外部信号拉低的引脚会输出一个电流()。
在访问外部程序存储器和16位地址的外部数据存储器(如执行“MOVX @DPTR”指令)时,P2送出高8位地址。在访问8位地址的外部数据存储器(如执行“MOVX @R1”指令)时,P2口引脚上的内容(就是专用寄存器(SFR)区中的P2寄存器的内容),在整个访问期间不会改变。
在对Flash ROM编程和程序校验期间,P2也接收高位地址和一些控制信号。
P3端口(P3.0~P3.7,10~17引脚):P3是一个带内部上拉电阻的8位双向I/O端口。P3的输出缓冲器可驱动(吸收或输出电流方式)4个TTL输入。对端口写入1时,通过内部的上拉电阻把端口拉到高电位,这时可用作输入口。P3做输入口使用时,因为有内部的上拉电阻,那些被外部信号拉低的引脚会输入一个电流()。
在对Flash ROM编程或程序校验时,P3还接收一些控制信号。
,如下表所示:
RST(9引脚):复位输入。当输入连续两个机器周期以上高电平时为有效,用来完成单片机单片机的复位初始化操作。看门狗计时完成后,RST引脚输出96个晶振周期的高电平。特殊寄存器AUXR(地址8EH)上的DISRTO位可以使此功能无效。DISRTO默认状态下,复位高电平有效。
ALE/(30引脚):地址锁存控制信号(ALE)是访问外部程序存储器时,锁存低8位地址的输出脉冲。在Flash编程时,此引脚()也用作编程输入脉冲。
在一般情况下,ALE以晶振六分之一的固定频率输出脉冲,可用来作为外部定时器或时钟使用。然而,特别强调,在每次访问外部数据存储器时,ALE脉冲将会跳过。
如果需要,通过将地址位8EH的SFR的第0位置“1”,ALE操作将无效。这一位置“1”,ALE仅在执行MOVX或MOV指令时有效。否则,ALE将被微弱拉高。这个ALE使能标志位(地址位8EH的SFR的第0位)的设置对微控制器处于外部执行模式下无效。
(29引脚):外部程序存储器选通信号()是外部程序存储器选通信号。当AT89C51RC从外部程序存储器执行外部代码时,在每个机器周期被激活两次,而访问外部数据存储器时,将不被激活。
/VPP(31引脚):访问外部程序存储器控制信号。为使能从0000H到FFFFH的外部程序存储器读取指令,必须接GND。注意加密方式1时,将内部锁定位RESET。为了执行内部程序指令,应该接VCC。在Flash编程期间,也接收12伏VPP电压。
XTAL1(19引脚):振荡器反相放大器和内部时钟发生电路的输入端。
XTAL2(18引脚):振荡器反相放大器的输入端。
二、 28BYJ-48步进电机
2.2.1步进电机的工作原理
步进电机是一种将电脉冲转化为角位移的执行机构。通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。可以通过控制脉冲个来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
本次设计是采用步进电机28BYJ48型四相八拍电机,电压为DC5V—DC12V。当对步进电机施加一系列连续不断的控制脉冲时,它可以连续不断地转动。每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度(一个步距角)。当通电状态的改变完成一个循环时,转子转过一个齿距。四相步进电机可以在不同的通电方式下运行,常见的通电方式有单(单相绕组通电)四拍(A-B-C-D-A。。。),双(双相绕组通电)四拍(AB-BC-CD-DA-AB-。。。),八拍(A-AB-B-BC-C-CD-D-DA-A。。。)
其相序分配表如下:
2.2.2 步进电机24BYJ48的相关电气参数
1.额定电压:12VDC(另有电压:5V、6V、24V)
2.相数:4
3.减速比:1/64(另有减速比:1/16、1/32)
4.步距角:5.625°/64
5.驱动方式:4相8拍
6.直流电阻:200Ω±7%(25℃)(按客户要求而定:80、130欧姆)
7.空载牵入频率:≥600Hz
8.空载牵出频率:≥1000Hz
9.牵入转矩:≥34.3mN.m(120Hz)
10.自定位转矩:≥34.3mN.m
11.绝缘电阻:>10MΩ(500V)
12.绝缘介电强度:600VAC/1mA/1S
13.绝缘等级:A
14.温升:<50K(120Hz)
15.噪音:<40dB(120Hz)
16.重量:大约40g
17.未注公差按:GB1804-m
18.转向:CCW
2.2.3 步进电机的基本术语
2.2.3.1 相数
产生不同对极N、S磁场的激磁线圈对数,常用m表示。
2.2.3.2 拍数
完成一个磁场周期性变化所需脉冲数或导电状态用n表示,或指电机转过一个齿距角所需脉冲数,比如说本次设计中使用的24BYJ48有单(单相绕组通电)四拍(A-B-C-D-A。。。),双(双相绕组通电)四拍(AB-BC-CD-DA-AB-。。。),八拍(A-AB-B-BC-C-CD-D-DA-A。。。)
2.2.3.3 步距角
对应一个脉冲信号,电机转子转过的角位移用θ表示。θ=360度(转子齿数J*运行拍数),以常规二相,转子齿为50齿电机为例。四拍运行时步距角为θ=360度/(50*4)=1.8度(俗称整步),八拍运行时步距角为θ=360度/(50*8)=0.9度(俗称半步)。
2.2.3.4 信号分配
四相步进电机按照其通电方式的不同,可以分为单四拍,双四拍和双八拍三种工作方式。单四拍与双四拍的步距角相等,均为11.25度,而八拍的步距角则是单四拍与双四拍的一半,5.625度。单(单相绕组通电)四拍(A-B-C-D-A。。。),双(双相绕组通电)四拍(AB-BC-CD-DA-AB-。。。),八拍 (A-AB-B-BC-C-CD-D-DA-A。。。)。这里选取的是双相八拍的工作方式。
三、 ULN2003达林顿陈列芯片
步进电机的驱动采用ULN2003芯片。
ULN2003 是高耐压、大电流达林顿陈列, 由七个硅 NPN 达林顿管组成。 ULN2003 的每一对达林顿都串联一个 2.7K 的基极电阻 , 在 5V 的工作电压下它能与 TTL 和 CMOS 电路直接相连, 可以直接处理原先需要标准逻辑缓冲器来处理的数据。 ULN2003 工作电压高, 工作电流大, 灌电流可达 500mA , 并且能够在关态时承受 50V 的电压, 输出还可以在高负载电流并行运行。
其引脚及内部原理图如下:
本设计中实验1、2、3、4脚做输入端,16、15、14、13做相对应的输出端,起到放大的作用,以驱动电机。
四、 LCD1602液晶
1602液晶也叫1602字符型液晶 它是一种专门用来显示字母、数字、符号等的点阵型液晶模块 它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
其各引脚功能见下图:
其典型接口电路如下图:
其基本操作时序为:
读状态 输入:RS=L,RW=H,E=H
输出:DB0~DB7=状态字
写指令 输入:RS=L,RW=L,E=下降沿脉冲,DB0~DB7=指令码
输出:无
读数据 输入:RS=H,RW=H,E=H
输出:DB0~DB7=数据
写数据 输入:RS=H,RW=L,E=下降沿脉冲,DB0~DB7=数据
输出:无
第三章 电路设计
一、单片机最小系统与LCD1602接口电路
本电路模块包括单片机最小系统,即51单片机、时钟电路、复位电路、上电开关等,和1602液晶接口电路。
模块电路原理图如下:
各子模块电路如下:
(1) 时钟产生电路
用于产生单片机的控制时钟,实际使用时采用11.0592M晶振。
(2) 复位电路
用于单片机手动复位。
(3) 1602液晶接口电路
用于连接1602液晶,P2.0—P2.2分别接RS、RW、EN,P0口接数据指令输入口。
二、步进电机驱动及接口电路
本电路模块用于单片机对步进电机的控制及使用ULN2003芯片对步进电机进行驱动。
原理图如下:
由于所选24BYJ48步进电机为四相步进电机,故只需4个单片机IO口控制,此处使用单片机的IO口P1.0-P1.3,使用ULN2003的引脚1-4做输入,16-13引脚做输出口。
三、按键电路
本次设计为了便于今后功能扩展使用了8个按键。
原理图如下:
第四章 程序设计
进入主程序后首先进行LCD初始化和定时器中断初始化,之后进行依次对按键进行扫描,当检测到相应的按键按下时,即执行相应的功能。
系统流程图如下:
第五章 系统调试
经过对程序的反复修改,调试之后,系统可以实现电机运行、停止,设置运行圈数,调节转速,电机正反转,点动等功能,同时液晶显示相应的状态。
第六章 心得体会
为其近一个月的单片机课程设计结束了,在这一个月中我收获了很多,感到很有意义。
早在大二自学单片机时我就注意到步进电机这种器件,但当时只是略作了解,没有学习它的原理与编程控制,这次借课程设计的机会,我得以对步进电机进行了较为深入的了解和学习。
在课设的前期我通过查阅了许多资料,学习了步进电机的工作原理。之后我开始考虑整体硬件电路的设计,显示、驱动电路的设计,最终选择使用28BYJ48型步进电机、ULN2003驱动芯片、1602液晶显示。在这之后我开始考虑要实现的电机功能,最后决定实现电机运行、停止,设置运行圈数,调节转速,电机正反转,点动等功能。在完成了原理图与PCB图绘制、电路元件焊接后,我开始着手进行程序设计。通过查阅资料我了解到控制步进电机的关键是利用定时器中断控制脉冲的快慢、顺序来调节电机转速、正反转等状态。以此为基础我开始了程序设计与调试,在这个过程中我遇到过一些困难,最后通过深入的学习、不断修改程序和同学的帮助终于得到解决。最终,本次课程设计完成了预想的对步进电机的几项基本控制功能。
步进电机调速系统适用各种现场自动化控制,特别应用于小功率负载的控制;具有成本底,性能稳定,可靠性高等优点。我觉得通过这次课程设计我对步进电机的基本控制得到了掌握,这对今后我在学习、工作的诸多应用场合中很可能会有用武之地。
另外,在这次课设过程中涉及的LCD1602控制等内容也对我很有帮助。通过本次课设我对51单片机的编程控制、定时器中断等知识也得到了充分的复习巩固。
总之,这次课设让我受益匪浅,感谢邱应强老师一学期来单片机课程的悉心教导,这些是我完成本次课设的基础和关键。
附件
一、 电路原理图
二、 电路PCB图
三、 电路实物图
四、 源程序
#include <reg52.h>
#include <intrins.h> //内部包含延时函数 _nop_();
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
uchar code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9}; //正转相序编码
uchar code REV[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1};
sbit K1 = P3^0; //运行与停止
sbit K2 = P3^1; //设圈数
sbit K3 = P3^2; //方向转换
sbit K4 = P3^3; //转速加
sbit K5 = P3^4; //点动
sbit K6 = P3^5;
sbit K7 = P3^6;
sbit K8 = P3^7;
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
bit on_off=0,on_off1=0; //运行与停止标志
bit direction=1; //方向标志
bit rate_dr=1; //速率标志
bit snum_dr=1; //圈数标志
uchar code cdis1[ ] = {" STEPPING MOTOR "};
uchar code cdis2[ ] = {"CONTROL PROCESS"};
uchar code cdis3[ ] = {" STOP "};
uchar code cdis4[ ] = {"NUM: RATE: "};
uchar code cdis5[ ] = {" RUNNING "};
uchar code cdis6[ ] = {" DIAN DONG "};
uchar m,v=0,q=0,q1;
uint number=0,number1=0;
uchar snum=10,snum1=10,number2=0; //预设定圈数
uchar rate=2,rate_ctr; //预设定速率
uchar data_temp,data_temP1,data_temp2;
/********************************************************/
/*
/* 延时t毫秒
/* 11.0592MHz时钟,延时约1ms
/*
/********************************************************/
void delay(uint t) //tms
{
uchar k;
while(t--)
{
for(k=0; k<125; k++)
{ }
}
}
/********************************************************/
void delayB(uchar x) //x*0.14MS
{
uchar i;
while(x--)
{
for (i=0; i<13; i++)
{ }
}
}
/********************************************************/
/********************************************************/
/*
/*检查LCD忙状态
/*lcd_busy为1时,忙,等待。为0时,闲,可写指令与数据。
/*
/********************************************************/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/********************************************************/
/*
/*写指令数据到LCD
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。
/*
/********************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/********************************************************/
/*
/*写显示数据到LCD
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。
/*
/********************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/********************************************************/
/*
/* LCD初始化设定
/*
/********************************************************/
void lcd_init()
{
delay(30);
lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x0c); //显示开,关光标
delay(5);
lcd_wcmd(0x06); //写入新数据后光标右移
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
}
/********************************************************/
/*
/* 设定显示位置
/*
/********************************************************/
void lcd_pos(uchar pos)
{
lcd_wcmd(pos | 0x80); //数据指针=80+地址变量
}
/********************************************************/
/*
/* LCD1602初始显示子程序
/*
/********************************************************/
void LCD_init_DIS()
{
delay(10); //延时
lcd_init(); //初始化LCD
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis1[m] != '\0')
{ //显示字符
lcd_wdat(cdis1[m]);
m++;
}
lcd_pos(0x40); //设置显示位置为第二行第1个字符
m = 0;
while(cdis2[m] != '\0')
{
lcd_wdat(cdis2[m]); //显示字符
m++;
}
delay(3000); //延时
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis3[m] != '\0')
{ //显示字符
lcd_wdat(cdis3[m]);
m++;
}
lcd_pos(0x40); //设置显示位置为第二行第1个字符
m = 0;
while(cdis4[m] != '\0')
{
lcd_wdat(cdis4[m]); //显示字符
m++;
}
for(m=0;m<2;m++)
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3e);
}
}
/********************************************************/
/*
/*数据转换子程序
/*
/********************************************************/
void data_conv()
{
data_temP1=data_temp/10; //高位
if(data_temP1==0)
{data_temP1=0x20;} //高位为0不显示
else
{data_temP1=data_temP1+0x30;}
data_temp2=data_temp%10; //低位
data_temp2=data_temp2+0x30;
}
/********************************************************/
/*
/*数据显示子程序
/*
/********************************************************/
void data_dis()
{
data_temp = snum; //显示圈数
data_conv();
lcd_pos(0x44);
lcd_wdat(data_temP1);
lcd_pos(0x45);
lcd_wdat(data_temp2);
data_temp = rate; //显示速率
data_conv();
lcd_pos(0x4d);
lcd_wdat(data_temP1);
lcd_pos(0x4e);
lcd_wdat(data_temp2);
}
/********************************************************
/*
/* 显示运行方向符号
/*
/********************************************************/
void motor_DR()
{
if(direction==1) //正转方向标志
{ for(m=0;m<2;m++)
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3e);
}
}
else
{ for(m=0;m<2;m++) //反转方向标志
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3c);
}
}
}
/********************************************************
/*
/* 显示运行状态
/*
/********************************************************/
void motor_RUN()
{
if(on_off==1)
{ TR0=1;
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis5[m] != '\0')
{ lcd_wdat(cdis5[m]); //RUNNING
m++; }
motor_DR(); //
}
else
{ TR0=0; P1 =0x0f;
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis3[m] != '\0')
{ lcd_wdat(cdis3[m]); //STOP
m++; }
motor_DR(); //
snum=snum1; //
number1=0; //清圈数计数器
}
}
void motor_RUN1()
{
if(on_off1==1)
{ TR1=1;
rate_ctr=0;
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis6[m] != '\0')
{ lcd_wdat(cdis6[m]); //DIANDONG
m++; }
motor_DR(); //
}
else
{ TR1=0;
P1 =0x0f;
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis3[m] != '\0')
{ lcd_wdat(cdis3[m]); //STOP
m++; }
motor_DR(); //
snum=snum1; //
number1=0; //清圈数计数器
}
}
/********************************************************
*
* 主程序
*
*********************************************************/
main()
{
LCD_init_DIS();
TMOD = 0x11; //T0定时方式1
TL0 = 0xff;
TH0 = 0xf5;
TL1 = 0xff;
TH1 = 0xf5;
EA = 1;
ET0 = 1;
ET1=1;
P1 = 0x0f;
while(1)
{
if(K1==0)
{
delay(20);
if(K1==0)
{
while(K1==0); //等待键释放
on_off=~on_off;
motor_RUN();
}
} //K1 end
/********************************************************/
if(K2==0)
{
delay(20);
if(K2==0)
{
if(snum_dr==1)
{ snum++;
snum1=snum;
if(snum==0x14) //14H=20
{ snum_dr=~snum_dr;}
}
else
{snum--;
snum1=snum;
if(snum==0x01)
{ snum_dr=~snum_dr; }
}
}
delay(100);
} //K2 end
/********************************************************/
if(K3==0)
{
delay(20);
if(K3==0)
{
direction=~direction;
motor_DR();
}
delay(100);
}//K3 end
/********************************************************/
if(K4==0)
{
delay(20);
if(K4==0)
{
if(rate_dr==1)
{ rate++;
if(rate==0x10)
{ rate_dr=~rate_dr;}
}
else
{
rate--;
if(rate==0x01)
{ rate_dr=~rate_dr; }
}
}
delay(100);
} //K4 end
/********************************************************/
if(number1==snum1) //与设定圈数是否相等
{ number1=0;
on_off=0;
TR0=0;
snum=snum1;
P1=0x0f;
motor_RUN();
}
data_dis();
/********************************************************/
if(K5==0) //点动
{
on_off1=1;
motor_RUN1();
while(K5==0) {
;
}
on_off1=0;
motor_RUN1();
}
} // while(1) end
} //main end
/********************************************************/
/*
/* 定时器 0 中断
/*
/********************************************************/
void motor_onoff() interrupt 1
{
TL0 = 0xff;
TH0 = 0xf5;
q++;
if(q < rate)
{ return; }
else
{ q=0;
number++; //脉冲计数加一
if(number==4096) //8*8个脉冲电机转一圈,又减速比为1/64,故电机外轴转一圈为64*64个脉冲
{ snum--;
number=0;
number1++; } //电机已转动圈数加一
if(direction==1) //方向标志
{ if(v<8)
{P1 = FFW[v];v++;} //取数据,正转
if(v==8)
{ v=0; }
}
else
{ if(v<8)
{P1 = REV[v];v++;} //取数据,反转
if(v==8)
{ v=0; }
}
}
}
/********************************************************/
/*
/* 定时器 1 中断
/*
/********************************************************/
void motor_onoff1() interrupt 3
{
TL1 = 0xff;
TH1 = 0xf5;
q1++;
if(q1 < rate)
{ return; }
else
{ q1=0;
number2++; //脉冲计数
if(number2==4096) //64个脉冲电机转一圈
{
number2=0;
} //电机转动圈数
if(direction==1) //方向标志
{ if(v<8)
{P1 = FFW[v];v++;} //取数据,正转
if(v==8)
{ v=0; }
}
else
{ if(v<8)
{P1 = REV[v];v++;} //取数据,反转
if(v==8)
{ v=0; }
}
}
}