基于单片机控制的步进电机的方案设计书.docx
《基于单片机控制的步进电机的方案设计书.docx》由会员分享,可在线阅读,更多相关《基于单片机控制的步进电机的方案设计书.docx(44页珍藏版)》请在冰点文库上搜索。
基于单片机控制的步进电机的方案设计书
电气综合设计
题目__________________________
二级学院______________________
专业_______________
班级_________
学生姓名_____学号____________
学生姓名________学号______________
学生姓名_________学号_______________
指导教师________________
时间:
__________________
考核工程
平时成绩20分
设计50分
答辩30分
得分
总分
考核等级
教师签名
摘要:
介绍了步进电机和直流电机原理及其驱动程序控制控制模块,通过AT89S52单片机及大电流驱动阵列ULN2003完成步进电机和直流电机各种运行方式的控制。
实现步进电机的正反转速度控制并且显示数据。
整个系统采用模块化设计,结构简单、可靠,通过按键控制,操作方便,节省成本。
关键词:
步进电机。
ULN2003。
AT89S51。
引言
随着数字化技术发展,数字控制技术得到了广泛而深入的应用。
步进电机是一种将数字信号直接转换成角位移或线位移的控制驱动元件,具有快速起动和停止的特点。
因为步进电动机组成的控制系统结构简单,价格低廉,性能上能满足工业控制的基本要求,所以广泛地应用于手工业自动控制、数控机床、组合机床、机器人、计算机外围设备、照相机,投影仪、数码摄像机、大型望远镜、卫星天线定位系统、医疗器件以及各种可控机械工具等等。
直流电机广泛应用于计算机外围设备(如硬盘、软盘和光盘存储器)、家电产品、医疗器械和电动车上,无刷直流电机的转子都普遍使用永磁材料组成的磁钢,并且在航空、航天、汽车、精密电子等行业也被广泛应用。
在电工设备中的应用,除了直流电磁铁(直流继电器、直流接触器等)外,最重要的就是应用在直流旋转电机中。
在发电厂里,同步发电机的励磁机、蓄电池的充电机等,都是直流发电机;锅炉给粉机的原动机是直流电动机。
此外,在许多工业部门,例如大型轧钢设备、大型精密机床、矿井卷扬机、市内电车、电缆设备要求严格线速度一致的地方等,通常都采用直流电动机作为原动机来拖动工作机械的。
直流发电机通常是作为直流电源,向负载输出电能;直流电动机则是作为原动机带动各种生产机械工作,向负载输出机械能。
在控制系统中,直流电机还有其它的用途,例如测速电机、伺服电机等。
他们都是利用电和磁的相互作用来实现向机械能能的转换。
一、步进电机的工作原理
步进电机本质上是一个数字角度转换器。
以三相电机为例,其结构原理见图1。
各相夹角为120°的定子磁极上均匀分布了5个矩形小齿,没有绕组的转子圆周上也均匀的分布着40个小齿(相邻齿夹角为9°)。
利用电磁学的性质,在某相绕组通电时,相应的磁极产生磁场,与转子形成磁路如此时定子的小齿与转子的小齿没有对齐,则在磁场作用下,转子就转动一定角度,达到齿的对齐。
在单三拍控制方式下,若A相通电,B、C相不通电,在磁场作用下使转子齿和A相定子齿相对假设此时为初态并且令与A相中心对齐的转子齿为0号齿,因为B相与A相相差120°,可知120°/9°=133⁄9,不为整数,即此时转子齿与B相不对齐,只是13号齿靠近相的中心,且相差3°。
如果此时突然变为B相通电,而A、C相都不通电,那么,13号齿会在磁场的作用下转到与相中心对齐的位置,这就是常说的走一步,此时,转子转了。
这样,按照A-B-C-A顺序通电次,可以使转子转动9°。
那么步进电机的步距角Q=(360/NZ)°(式中N=MC为运行拍数;M为控制绕组相数;C为状态系数,单三拍或双三拍时C=1,单六拍或双六拍时C=2为转子齿数)。
二、硬件系统
1、电路图
2、ULN2003
ULN是集成达林顿管IC,内部还集成了一个消线圈反电动势的二极管,可用来驱动继电器。
它是双列16脚封装,NPN晶体管矩阵,最大驱动电压=50V,电流=500mA,输入电压=5V,适用于TTLCOMS,由达林顿管组成驱动电路。
ULN是集成达林顿管IC,内部还集成了一个消线圈反电动势的二极管,它的输出端允许通过电流为200mA,饱和压降VCE约1V左右,耐压BVCEO约为36V。
用户输出口的外接负载可根据以上参数估算。
采用集电极开路输出,输出电流大,故可直接驱动继电器或固体继电器,也可直接驱动低压灯泡。
通常单片机驱动ULN2003时,上拉2K的电阻较为合适,同时,COM引脚应该悬空或接电源。
ULN2003是一个非门电路,包含7个单元,但独每个单元驱动电流最大可达350mA.资料的最后有引用电路,9脚可以悬空。
比如1脚输入,16脚输出,你的负载接在VCC与16脚之间,不用9脚。
ULN2003的作用:
ULN2003是大电流驱动阵列,多用于单片机、智能仪表、PLC、数字量输出卡等控制电路中。
可直接驱动继电器等负载。
输入5VTTL电平,输出可达500mA/50V。
ULN2003是高耐压、大电流达林顿陈列,由七个硅NPN达林顿管组成。
ULN2003的每一对达林顿都串联一个2.7K的基极电阻,在5V的工作电压下它能与TTL和CMOS电路直接相连,可以直接处理原先需要标准逻辑缓冲器。
ULN2003是高压大电流达林顿晶体管阵列系列产品,具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。
ULN2003A引脚图及功能:
ULN2003是高耐压、大电流、内部由七个硅NPN达林顿管组成的驱动芯片。
经常在以下电路中使用,作为显示驱动、继电器驱动、照明灯驱动、电磁阀驱动、伺服电机、步进电机驱动等电路中。
ULN2003的每一对达林顿都串联一个2.7K的基极电阻,在5V的工作电压下它能与TTL和CMOS电路直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据。
ULN2003工作电压高,工作电流大,灌电流可达500mA,并且能够在关态时承受50V的电压,输出还可以在高负载电流并行运行。
ULN2003的封装采用DIP—16或SOP—16。
ULN2003可以驱动7个继电器,具有高电压输出特性,并带有共阴极的续流二极管使器件可用于开关型感性负载。
每对达林顿管的额定集电极电流是500mA,达林顿对管还可并联使用以达到更高的输出电流能力。
显示电路主要包括大型LED数码管BSI20-1(共阳极,数字净高12cm)和高电压大电流驱动器ULN2003,大型LED数码管的每段是由多个LED发光二极管串并联而成的,因此导通电流大、导通压降高。
ULN2003是高压大电流达林顿晶体管阵列电路,他具有7个独立的反相驱动器,每个驱动器的输出灌电流可达500mA,导通时输出电压约1V,截止时输出电压可达50V。
ULN2003的1~7脚为信号输入脚,依次对应的输出端为16~10脚,8脚为接地端。
当驱动电源电压为+12V时,若要求数码管每段导通电流为40mA,则每段的限流电阻为50Ω。
则一块ULN2003恰好驱动一个LED数码管的7段。
大数码管采用共阳极接法,低电平有效。
锁存器输出的电平经NPN三极管9014反相后,再由ULN2003放大后推动大数码管显示.
3、AT89C51
AT89C51是一种带4K字节FLASH存储器(FPEROM—FlashProgrammableandErasableReadOnlyMemory)的低电压、高性能CMOS8位微处理器,俗称单片机。
AT89C2051是一种带2K字节闪存可编程可擦除只读存储器的单片机。
单片机的可擦除只读存储器可以反复擦除1000次。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪速存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。
AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
外形及引脚排列如图所示。
主要特性
·与MCS-51兼容
·4K字节可编程FLASH存储器
·寿命:
1000写/擦循环
·数据保留时间:
10年
·全静态工作:
0Hz-24MHz
·三级程序存储器锁定
·128×8位内部RAM
·32可编程I/O线
·两个16位定时器/计数器
·5个中断源
·可编程串行通道
·低功耗的闲置和掉电模式
·片内振荡器和时钟电路
特性概述
AT89C51提供以下标准功能:
4k 字节Flash 闪速存储器,128字节内部RAM,32个I/O口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。
同时,AT89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。
空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。
掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
管脚说明
VCC:
供电电压。
GND:
接地。
P0口:
P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
当P0口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的低八位。
在FIASH编程时,P0口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须接上拉电阻。
P1口:
P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
在FLASH编程和校验时,P1口作为低八位地址接收。
P2口:
P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。
P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3口:
P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。
当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。
作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
P3口也可作为AT89C51的一些特殊功能口,如下表所示:
口管脚备选功能
P3.0RXD(串行输入口)
P3.1TXD(串行输出口)
P3.2/INT0(外部中断0)
P3.3/INT1(外部中断1)
P3.4T0(计时器0外部输入)
P3.5T1(计时器1外部输入)
P3.6/WR(外部数据存储器写选通)
P3.7/RD(外部数据存储器读选通)
P3口同时为闪烁编程和编程校验接收一些控制信号。
RST:
复位输入。
当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:
当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的低位字节。
在FLASH编程期间,此引脚用于输入编程脉冲。
在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。
因此它可用作对外部输出的脉冲或用于定时目的。
然而要注意的是:
每当用作外部数据存储器时,将跳过一个ALE脉冲。
如想禁止ALE的输出可在SFR8EH地址上置0。
此时,ALE只有在执行MOVX,MOVC指令是ALE才起作用。
另外,该引脚被略微拉高。
如果微处理器在外部执行状态ALE禁止,置位无效。
/PSEN:
外部程序存储器的选通信号。
在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。
但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA/VPP:
当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。
注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。
在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
XTAL1:
反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:
来自反向振荡器的输出。
振荡器特性:
XTAL1和XTAL2分别为反向放大器的输入和输出。
该反向放大器可以配置为片内振荡器。
石晶振荡和陶瓷振荡均可采用。
如采用外部时钟源驱动器件,XTAL2应不接。
有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。
三、软件系统
该系统采用多个模块的方式来实现对步进电机的控制。
控制模块采用单片机AT89S51来控制ULN2003驱动电机转动。
1.main
/************************************************************
*实例名称:
步进电机
*实例说明:
实现步进电机的正反转以及加减速控制,并在LCD屏上实时
显示步进电机的状态
*作者:
hzd
*时间:
14.01.10
************************************************************/
#include"target.h"
#include"key.h"
#defineMOTER_SPEED_NORMAL5//电机正常运行上限
#defineMOTER_SPEED_MIN15//电机低速运行下限
uchartimer0Count。
//timer0中断溢出计数
ucharmoterStep。
//电机步数(0x00~0x07)
uintmoterSpeed。
//速度值变化量(0~moterSpeedMax)
uintmoterSpeedMax。
//速度最快值
ucharmoterState。
//电机运行状态
ucharmoterDirect。
//电机运转方向,静止/0x00。
正转/0x01。
反转/0x02
ucharmoterAddReduce。
//电机加速及减速量
ucharspeedDirect。
//0x01,电机加速。
0x02,电机减速
bitdisplay_is_ok。
//显示屏是否需要更新
/**********************************************************
MOTER_STOP,停止。
MOTER_FRONT_ADD,正转加速
MOTER_FRONT_REDUCE,正转减速。
MOTER_FRONT_NORMAL,正转正常
MOTER_FRONT_LOWER,正转低速。
MOTER_QUEEN_ADD,反转加速
MOTER_QUEEN_REDUCE,反转减速,MOTER_QUEEN_NOMAL,反转正常
MOTER_QUEEN_LOWER,反转低速
***********************************************************/
voidmain()
{
ucharkeyValueRead。
target_init()。
moterState=MOTER_STOP。
timer0Count=0x00。
moterAddReduce=0x00。
moterStep=0x00。
moterSpeed=0x00。
moterSpeedMax=0x00。
//默认停止
moterDirect=0x00。
//默认停止
moter_state_display(MOTER_STOP)。
display_is_ok=1。
sei()。
while
(1)
{
keyValueRead=get_key_value()。
switch(keyValueRead)
{
caseKEY_FRONT:
//正转
{
moterState=MOTER_FRONT_LOWER。
moterDirect=0x01。
moterSpeedMax=MOTER_SPEED_MIN。
display_is_ok=0。
//moter_state_display(MOTER_FRONT_LOWER)。
break。
}
caseKEY_QUEEN:
//反转
{
moterState=MOTER_QUEEN_LOWER。
moterDirect=0x02。
moterSpeedMax=MOTER_SPEED_MIN。
display_is_ok=0。
//moter_state_display(MOTER_QUEEN_LOWER)。
break。
}
caseKEY_ADD:
//加速
{
speedDirect=0x01。
moterAddReduce=100。
display_is_ok=0。
if(moterDirect==0x01)//正转
moter_state_display(MOTER_FRONT_ADD)。
elseif(moterDirect==0x02)
moter_state_display(MOTER_QUEEN_ADD)。
break。
}
caseKEY_REDUCE:
//减速
{
speedDirect=0x02。
moterAddReduce=100。
display_is_ok=0。
if(moterDirect==0x01)//正转
moter_state_display(MOTER_FRONT_REDUCE)。
elseif(moterDirect==0x02)
moter_state_display(MOTER_QUEEN_REDUCE)。
break。
}
caseKEY_STOP:
//停止
{
moterState=MOTER_STOP。
moterSpeedMax=0x00。
//默认停止
moterDirect=0x00。
//默认停止
moter_state_display(MOTER_STOP)。
display_is_ok=1。
break。
}
default:
break。
}
if(display_is_ok==0)//判断LCD内容是否需要更新
{
switch(moterSpeedMax)
{
caseMOTER_SPEED_NORMAL:
{
if(moterDirect==0x01)
moter_state_display(MOTER_FRONT_NORMAL)。
elseif(moterDirect==0x02)
moter_state_display(MOTER_QUEEN_NOMAL)。
display_is_ok=1。
break。
}
caseMOTER_SPEED_MIN:
{
if(moterDirect==0x01)
moter_state_display(MOTER_FRONT_LOWER)。
elseif(moterDirect==0x02)
moter_state_display(MOTER_QUEEN_LOWER)。
display_is_ok=1。
break。
}
default:
break。
}
}
}
}
voidtimer0_overflow(void)interrupt1//timer0定时10ms
{
TH0=-500/256。
//定时10ms
TL0=-500%256。
{
timer0Count=0x00。
if(speedDirect==0x01)//如果为加速
{
if(moterSpeedMax>MOTER_SPEED_NORMAL)
moterSpeedMax--。
//最大加速到正常值
else
{
moterAddReduce=0x00。
speedDirect=0x00。
//已经加速到正常值,不再加速
}
}
elseif(speedDirect==0x02)
{
if(moterSpeedMaxmoterSpeedMax++。
else
{
moterAddReduce=0x00。
speedDirect=0x00。
}
}
}
if(moterSpeedmoterSpeed++。
else
{
moterSpeed=0x00。
if(moterDirect==0x01)//正转
{
if(moterStep>0x00)
moterStep--。
else
moterStep=0x07。
}
elseif(moterDirect==0x02)//反转
{
if(moterStep<0x07)
moterStep++。
else
moterStep=0x00。
}
ground(moterStep)。
}
}
2.target
#defineTARGET_GLOBAL1
#include"target.h"
#include"dot.h"
voidtimer0_init(void)
{
TMOD|=0x01。
//MODEL1,timer
TH0=0xDC。
//定时10ms
TL0=0x00。
ET0=1。
//中断使能
TR0=1。
//关闭定时器0
}
voidtarget_init(void)
{
timer0_init()。
Lcd_Initial()。
}
/************************************************
*函数名称:
display_head(void)
*函数功能:
显示“步进电机运行状态”字样
*函数入口:
无
*函数出口:
无
************************************************/
voiddisplay_head(void)
{
uchari,temp。
temp=0x00。
for(i=0。
i<8。
i++)
{
Lcd_Character_16X16(1,10,temp,MOTER_HEAD[i])。
temp+=16。
}
}
/************************************************
*函数名称:
display_state(state)
*函数功能:
显示电机状态“停止”,“正转”,“反转”
*函数入口:
state,电机状态
*函数出口:
无
*说明:
state:
0