基于proteus的步进电机电机仿真.docx
《基于proteus的步进电机电机仿真.docx》由会员分享,可在线阅读,更多相关《基于proteus的步进电机电机仿真.docx(25页珍藏版)》请在冰豆网上搜索。
基于proteus的步进电机电机仿真
基于proteus的步进电机电机仿真
摘要:
步进电机广泛应用在生产实践的各个领域。
它最大的应用是在数控机床的制造中,因为步进电机不需要A/D转换,能够直接将数字脉冲信号转化成为角位移,所以被认为是理想的数控机床的执行元件。
本设计利用proteus仿真软件进行电路仿真,系统通过设置四个按键分别控制不进电机的起止、圈数、方向、不进速度,使用1602液晶显示以上参数。
整个系统具有稳定性好,实用性强,操作界面友好等优点。
关键词:
proteus仿真不进电机拍数
一、Proteus简介
ProteusISIS是英国Labcenter公司开发的电路分析与实物仿真软件。
它运行于Windows操作系统上,可以仿真、分析(SPICE)各种模拟器件和集成电路,该软件的特点是:
①实现了单片机仿真和SPICE电路仿真相结合。
具有模拟电路仿真、数字电路仿真、单片机及其外围电路组成的系统的仿真、RS232动态仿真、I2C调试器、SPI调试器、键盘和LCD系统仿真的功能;有各种虚拟仪器,如示波器、逻辑分析仪、信号发生器等。
②支持主流单片机系统的仿真。
目前支持的单片机类型有:
68000系列、8051系列、AVR系列、PIC12系列、PIC16系列、PIC18系列、Z80系列、HC11系列以及各种外围芯片。
③提供软件调试功能。
在硬件仿真系统中具有全速、单步、设置断点等调试功能,同时可以观察各个变量、寄存器等的当前状态,因此在该软件仿真系统中,也必须具有这些功能;同时支持第三方的软件编译和调试环境,如KeilC51uVision2等软件。
④具有强大的原理图绘制功能。
总之,该软件是一款集单片机和SPICE分析于一身的仿真软件,功能极其强大。
二、整体电路分析
如下图,整个设计以STC89C51单片机为中心,由复位电路,时钟电路,电机驱动,步进电机,显示电路等组成,硬件模块如图2-1所示:
图1硬件模块图
通过按键进行相应的参数设定,单片机接收到信号后经过判断驱动电机驱动模块,然后由驱动电路驱动步进电机运转,并用1602显示设置的参数。
三、系统硬件电路选择与设计
1、主控器的选择
按照题目要求本次主控单元使用C51单片机对整个系统进行控制。
STC89C51RC包含512字节RAM、32条I/O口线、3个16位定时/计数器、8输入4优先级嵌套中断结构、1个串行I/O口(可用于多机通信、I/O扩展或全双工UART)以及片内振荡器和时钟电路。
此外,由于器件采用了静态设计,可提供很宽的操作频率范围(频率可降至0)。
可实现两个由软件选择的节电模式、空闲模式和掉电模式。
空闲模式冻结CPU,但RAM、定时器、串口和中断系统仍然工作。
掉电模式保存RAM的内容,但是冻结振荡器,导致所有其它的片内功能停止工作。
由于设计是静态的,时钟可停止而不会丢失用户数据。
运行可从时钟停止处恢复。
所以该单片机可以满足系统要求,电路图如下:
图2单片机最小系统电路图
2、步进电机选择
步进电机是一种能够将电脉冲信号转换成角位移或线位移的机电元件,它实际上是一种单相或多相同步电动机。
单相步进电动机有单路电脉冲驱动,输出功率一般很小,其用途为微小功率驱动。
多相步进电动机有多相方波脉冲驱动,用途很广。
本设计使用的是四相三拍步进电机,连接图如下:
图3步进电机接线图
3、驱动电路的选择
驱动模块我们使用集成驱动芯片ULN2003,给芯片是高耐压、大电流达林顿管由七个硅NPN达林顿管组成。
该电路的特点如下:
ULN2003的每一对达林顿都串联一个2.7K的基极电阻,在5V的工作电压下它能与TTL和CMOS电路直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据。
ULN2003工作电压高,工作电流大,灌电流可达500mA,并且能够在关态时承受50V的电压,输出还可以在高负载电流并行运行。
1脚输入,16脚输出,你的负载接在VCC与16脚之间,不用9脚。
图4ULN2003内部结构图图5ULN2003管脚图
ULN2003是大电流驱动阵列,多用于单片机、智能仪表、PLC、数字量输出卡等控制电路中。
可直接驱动继电器等负载。
所以足以满足驱动步进电机的要求,连接图如下:
图6uln2003接线图
4、显示电路的
LCD显示模块是把LCD显示屏、背景光源、线路板和驱动集成电路等部件构造成1个整体作为1个独立部件使用,只留1个接口与外部通信。
显示模块通过这个接口接收显示的命令和数据,并按指令和数据的要求进行显示,外部电路通过这个接口读出显示模块的工作状态和显示数据。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:
阿拉伯数字、英文字母的大小写、常用的符号和日文假名等,每1个字符都有1个固定的代码。
用户对模块写入适当的控制命令,即可完成清屏、显示、地址设置等操作。
设计采用并行方式控制,LCD与单片机的通讯接口电路如图3所示采用直连的方法。
图71602显示电路接线图
5键盘输入模块电路
设计中,键盘采用非编码键盘系统中的独立式按键结构。
键盘工作方式采用定时扫描方式。
采用定时器TO定时,通过输出数据,识别按键的工作状态。
键盘主要用来提供人机接口,电路如图3所示,采用独立式按键电路,各按键开关均采用了上拉电阻,保证在按键断开时,各I/O有确定的高电平。
按键功定义如下:
当P3.2按下时,步进电机开始加速;当P3.3按下时,步进电机开始减速;当P3.4按下时,步进电机开始正转;当P3.5按下时,步进电机开始反转。
按键抖动的消除采用软件消抖实现。
连接图如下:
图8按键接连接图
四、系统软件设计
1、软件流程图
图9系统流程图
2程序代码
见附件。
五、总结
采用模块程序设计,逐个模块调好以后,再进行系统程序总调试。
利用仿真软件Proteus及KeilC5l进行调试。
系统实现了可程序设定和显示步进角、步进方向和步进速度,支持用开关量单独控制步进电机的转向,转速。
电路简单可靠,结构紧凑,控制灵活,成本低,可移植性强。
经实验验证,本系统对步进电机的各项控制都能达到比较理想的效果,具有较高的实用价值。
通过此次课程设计,我不仅将知识融会贯通,而且在查找资料的过程中也了解了许多课外知识,开拓了视野,使自己在专业知识方面和动手能力方面有了很大的提高,让我学会了理论到实践的转化,即如何将自己学到的运用到以后的生活和工作中,同时,也让我意识到团队精神的重要性。
此外,感谢丁老师的悉心教导以及同学的帮助,正是王老师细心的辅导和提供的一些参考资料还有同学们的互相帮助,让我顺利的完成了毕业设计,相信这对我以后的生活和工作都会有很大的帮助。
六参考文献
[1]徐薇莉,曹柱中.控制理论与设计[M].上海:
上海交通大学出版社.2003.
[2]黄坚.自动控制原理及其应用[M].北京:
高等教育出版社,2004.
[3]先锋工作室.单片机程序设计实例[M].北京:
清华大学出版社,2003.’
[4]王幸之,钟爱琴.AT89系列单片机原理及接口技术[M].北京:
北京航天大学出版社,2004.
[5]康华光,陈大钦.模拟电子电路[M].北京:
高教育出版社,2004.
七附录
(1)整体电路图
(2)程序代码
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#definedelayNOP();{_nop_();_nop_();_nop_();_nop_();};
unsignedcharcodeFFW[8]={0xfe,0xfc,0xfd,0xf9,0xfb,0xf3,0xf7,0xf6};//反转
unsignedcharcodeREV[8]={0xf6,0xf7,0xf3,0xfb,0xf9,0xfd,0xfc,0xfe};//正转
//unsignedcharcodeFFW[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};//反转
//unsignedcharcodeREV[8]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//正转
sbitK1=P3^2;//运行与停止
sbitK2=P3^3;//设定圈数
sbitK3=P3^4;//方向转换
sbitK4=P3^5;//速率调整
sbitLCD_RS=P2^0;
sbitLCD_RW=P2^1;
sbitLCD_EN=P2^2;
biton_off=0;//运行与停止标志
bitdirection=1;//方向标志
bitrate_dr=1;//速率标志
bitsnum_dr=1;//圈数标志
ucharcodecdis1[]={"NO.0738230126"};
ucharcodecdis2[]={"2012/5/24"};
ucharcodecdis3[]={"STOP"};
ucharcodecdis4[]={"NUM:
RATE:
"};
ucharcodecdis5[]={"RUNNING"};
ucharm,v=0,q=0;
ucharnumber=0,number1=0;
ucharsnum=20,snum1=20;//预设定圈数
ucharrate=3;//预设定速率
uchardata_temp,data_temP0,data_temp2;
/********************************************************/
/*
/*延时t毫秒
/*11.0592MHz时钟,延时约1ms
/*
/********************************************************/
voiddelay(uintt)
{
uchark;
while(t--)
{
for(k=0;k<124;k++)
{}
}
}
/********************************************************/
voiddelayB(ucharx)//x*0.14MS
{
uchari;
while(x--)
{
for(i=0;i<13;i++)
{}
}
}
/********************************************************/
/*
/*检查LCD忙状态
/*lcd_busy为1时,忙,等待。
为0时,闲,可写指令与数据。
/*
/********************************************************/
bitlcd_busy()
{
bitresult;
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=指令码。
/*
/********************************************************/
voidlcd_wcmd(ucharcmd)
{
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=数据。
/*
/********************************************************/
voidlcd_wdat(uchardat)
{
while(lcd_busy());
LCD_RS=1;
LCD_RW=0;
LCD_EN=0;
P0=dat;
delayNOP();
LCD_EN=1;
delayNOP();
LCD_EN=0;
}
/********************************************************/
/*
/*LCD初始化设定
/*
/********************************************************/
voidlcd_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);
}
/********************************************************/
/*
/*设定显示位置
/*
/********************************************************/
voidlcd_pos(ucharpos)
{
lcd_wcmd(pos|0x80);//数据指针=80+地址变量
}
/********************************************************/
/*
/*LCD1602初始显示子程序
/*
/********************************************************/
voidLCD_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);
}
}
/********************************************************/
/*
/*数据转换子程序
/*
/********************************************************/
voiddata_conv()
{
data_temP0=data_temp/10;//高位
if(data_temP0==0)
{data_temP0=0x20;}//高位为0不显示
else
{data_temP0=data_temP0+0x30;}
data_temp2=data_temp%10;//低位
data_temp2=data_temp2+0x30;
}
/********************************************************/
/*
/*数据显示子程序
/*
/********************************************************/
voiddata_dis()
{
data_temp=snum;//显示圈数
data_conv();
lcd_pos(0x44);
lcd_wdat(data_temP0);
lcd_pos(0x45);
lcd_wdat(data_temp2);
data_temp=rate;//显示速率
data_conv();
lcd_pos(0x4d);
lcd_wdat(data_temP0);
lcd_pos(0x4e);
lcd_wdat(data_temp2);
}
/********************************************************
/*
/*显示运行方向符号
/*
/********************************************************/
voidmotor_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);
}
}
}
/********************************************************
/*
/*显示运行状态
/*
/********************************************************/
voidmotor_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;P0=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=0x01;//T0定时方式1
TL0=0x33;
TH0=0xf5;
EA=1;
ET0=1;
P1=0;
while
(1)
{
if(K1==0)
{
//beep();
while(K1==0);//等待键释放
on_off=~on_off;
motor_RUN();
}//K1end
/********************************************************/
if(K2==0)
{
if(snum_dr==1)
{snum++;
snum1=snum;
if(snum==0x14)
{snum_dr=~snum_dr;}
}
else
{snum--;
snum1=snum;
if(snum==0x01)
{snum_dr=~snum_dr;}
}
}//K2end
/********************************************************/
if(K3==0)
{
direction=~direction;
motor_DR();
}//K3end
/********************************************************/
if(K4==0)
{
if(rate_dr==1)
{rate++;
if(rate==0x10)
{rate_dr=~rate_dr;}
}
else
{
rate--;
if(rate==0x01)
{rate_dr=~rate_dr;}
}
}//K4end
/********************************************************/
if(number1==snum1)//与设定圈数是否相等
{number1=0;
on_off=0;
TR0=0;
snum=snum1;
P1=0x0f;
motor_RUN();
}
data_dis();
}//while
(1)end
}//mainend
/********************************************************/
/*
/*定时器T0中断
/