一、设计题目
步进电机控制系统的设计与仿真 二、设计要求
设计一个单片机四相步进电机控制系统,要求系统具有以下功能。
(1)用K0-K2作为通电方式选择键,K0为单四拍,K1为双四拍,K2为四相八拍。 (2)K3-K4作为启动和方向控制。
(3)正转时红色指示灯亮,反转时黄色指示灯亮,不转时绿灯亮。 (4)可通过键盘设定步进电机步数给定值。 (5)用三位LED数码管显示剩余工作步数
三、系统总体框图与原理说明
通过键盘模块设置步进电机的工作模式、步数以及正反转,同时用数码管模块显示剩余工作步数,用LED灯模块显示步进电机的工作状态。
4*4键盘模块:采用外部中断的方式实时扫描键盘,判别按下的键,并执行所按下的键相应的操作,即输入步数、选择工作模式、正/反转、调速以及启动/停止等,由于键数的限制,把一些键功能复用。用线反转法扫描键盘,即先在P2口输出0xf0,二次确认有按键按下后,逐行输出低电平,确认按键所在的列,便可知道所按下的是哪个键,再返回对应的键值。
数码管显示模块:采用定时中断的方式定时扫描一次显示,从而实现数码管的动态显示,同时P0口需外接上拉电阻。本设计采用共阴数码管,故0到9的段码为:0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
四相步进电机模块:采用L298驱动芯片驱动电机,同时P1口驱动能力不够,需外接上拉电阻,通过四个LED灯接在P1.0到P1.3口来观察电机的拍子。据分析可得到,四相单四拍:A->B->C->D;四相双四拍:AB->BC->CD->DA;四相八拍:A->AB->B->BC->C->CD->D->DA
LED灯模块:把红黄绿三个灯接在P3口上,在程序中通过置位复位来实现相应状态的转换。
图1为系统总体设计方框图,由单片机AT89C51,L298驱动芯片,四相步进电机,7段LED数码管等一些电路模块组成。
四相步进电机模块 AT89C51单片机整体控制 LED显示模块 LED显示灯显示电机工作状态 键盘选择电机工作模式
图1 系统总体框图
四、硬件电路图
此次我们所设计的是一个步进电机控制系统,主要由单片机AT89C51、四相步进电机、7段数码管、LED灯、L298驱动芯片及一些其他相关元件设计而成。可以通过键盘来控制系统的输入步数、选择工作模式、正/反转、调速以及启动/停止工作。运转时,用3位7段数码管来输出生育工作步数。最后根据思路所设计出来的硬件电路图如下。
1
图2 系统的硬件电路图
2
五、程序流程图
开始 步数清零 数码管输出0 默认单四拍、正转 红、绿灯亮 设置步数 设置工作模式 N 正转? 反转 N Y 红灯亮 Y 黄灯亮
3
启动? N Y 输出控制字 步数自减1 数码管输出步数 N 增速? 减速? N Y 缩短延时 Y 增长延时 Y 步数位0? N N 停止? Y 结束
4
六、仿真说明
上电后,电机步数为0,默认为四相单四拍、正转的工作模式,红、绿灯亮,数码管显示0,输入步数,数码管显示步数,选择工作模式,设置正/反转,相应的指示灯亮,并启动后,绿灯灭,电动机开始按设定的模式工作,数码管显示剩余的工作步数,运行时,可通过加速和减速按键进行电机的调速,按下停止按键后,电机停止工作,数码管显示停止时剩余的工作步数,当步数减到0后,电机停止工作,数码管显示0。 七、心得体会
在设计的过程中,学会了很多东西,熟悉了步进电机控制系统的整体运行过程和总体布局,掌握了该硬件电路的设计方法,掌握了步进电机控制系统程序的设计和调试,最大的收获便是学会了如何把C语言应用于单片机得编程上,避免了汇编的低效率的缺点。
5
附录:程序清单
#include #define uchar unsigned char #define uint unsigned int uchar code disp[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; //共阴数码管显示码 uchar code table1[]={0x01,0x02,0x04,0x08, 0x08,0x04,0x02,0x01}; //单四拍 uchar code table2[]={0x03,0x06,0x0c,0x09, 0x09,0x0c,0x06,0x03}; //双四拍 uchar code table3[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09, 0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01}; //四相八拍 uchar *p=NULL;//表指针 uchar paishu=0,qibu=0,start=0; uint speed=100;//设置转速 uint dat1=0,count=0; //拍数 sbit weg=P3^0; sbit wes=P3^1; sbit web=P3^3; //个位位选 //十位位选 //百位位选 sbit k31=P3^5; // 正转指示灯 sbit k32=P3^6; //反转指示灯 sbit k4=P3^7; //停止指示灯 void init() ; void display_3(uint dat); void Delay1ms(unsigned int count); uchar keybscan(void); uchar keyaction (void); /*1ms延时子程序*/ void Delay1ms(unsigned int count) { } 6 unsigned int i,j; for(i=0;i /*返回键码子程序*/ uchar keyaction (void) { switch(keybscan()) { case 0xfe : return('#'); break; //无按键则返回 case 0xde : return(0); break; //第一行第一列按键编码 case 0xce : return(1); break; //第一行第二列按键编码 case 0xae : return(2); break; case 0x6e : return(3); break; 7 P2=0xf0; if((P2&0xf0)!=0xf0) { Delay1ms(1); { scode=0xfe; } while((scode&0x10)!=0) { } P2=scode; if((P2&0xf0)!=0xf0) { rcode=(P2&0xf0); return(scode+rcode); if((P2&0xf0)!=0xf0) } } else scode=(scode<<1)|0x01; return(0xfe); case 0xdd : return(4); break; case 0xcd : return(5); break; case 0xad : return(6); break; case 0x6d : return(7); break; case 0xdb : return(8); break; case 0xcb : return(9); break; case 0xab : return(10); break; case 0x6b : return(11); break; case 0xd7 : return(12); break; case 0xc7 : return(13); break; case 0xa7 : return(14); break; case 0x67 : return(15); break; // } } /*3位数显示子程序*/ void display_3(uint dat) { P0=0; P0=disp[dat/100%10]; //3位 web=0; Delay1ms(1); web=1; P0=0; P0=disp[dat/10%10]; //2位 wes=0; Delay1ms(1); wes=1; P0=0; P0=disp[dat%10]; //1位 weg=0; Delay1ms(1); weg=1; } 8 第四行第四列按键编码 /*定时器0初始化子程序*/ void init() { TMOD=0x01; TH0=(65536-10000)/256; TL0=(65536-10000)%256; EA=1; ET0=1; TR0=1; } /*定时器0中断程序*/ void timer0() interrupt 1 { TH0=(65536-10000)/256; //每10ms扫描显示 TL0=(65536-10000)%256; display_3(count); //显示剩余步数 } /*外部中断0中断程序*/ int0()interrupt 0 using 0 { EA=0; //关中断 if (start==0) { switch(keyaction()) { case 0: { dat1=dat1*10+0; count=dat1; } case 1: {dat1=dat1*10+1; count=dat1; } break; case 2: {dat1=dat1*10+2; count=dat1;} case 3: {dat1=dat1*10+3; count=dat1;} 9 break; break; break; case 4: {dat1=dat1*10+4; count=dat1;} break; break; case 5: {dat1=dat1*10+5; count=dat1;} case 6: {dat1=dat1*10+6; count=dat1;} break; case 7: {dat1=dat1*10+7; count=dat1;} break; case 8: {dat1=dat1*10+8; count=dat1;} break; case 9: {dat1=dat1*10+9; count=dat1;} break; case 10: {p=&table1[0];break;} //单四拍 case 11: {p=&table2[0];break;}//双四拍 case 12: {p=&table3[0];break;}//四相八拍 case 13: {qibu=0; if(p==(&table3[0])) paishu=8; else paishu=4; k31=1;k32=0;break;}// 正转 case 14: {if(p==(&table3[0])) {qibu=8;paishu=16;} else {qibu=4;paishu=8;} k31=0;k32=1;break;} // 反转 case 15: {start=1;k4=0;break;} //启动标志 case '#': break; // 无按键按下 10 } } else switch (keyaction()) { } EA=1; //开中断 case 0: if (speed<20000) speed+=10;break; //减速 case 1: if (speed>10) speed-=10;break; case 15:start=0;k4=1;break; //加速 } void main() { uint i=0; p=&table1[0]; qibu=0; paishu=4; k31=1; //默认模式为单四拍,正转 k32=0; k4=1; init(); IT0=1; //设置外部中断0为边沿触发方式,下降沿有效 P2=0xf0; Delay1ms(1); while(!start) P2=0xf0; i=qibu; while(1) { P2=0xf0; while(count) 11 EA=1; //开总中断 EX0=1; //开外部中断0 //等待启动信号 { P2=0xf0; if(i>=paishu) i=qibu; if (start==1) P1=p[i]; while(!start) P2=0xf0; //等待启动信号 else } } } Delay1ms(speed); i++; count--; 12 因篇幅问题不能全部显示,请点此查看更多更全内容