搜索
您的当前位置:首页正文

步进电机控制系统的设计与仿真

来源:二三娱乐


一、设计题目

步进电机控制系统的设计与仿真 二、设计要求

设计一个单片机四相步进电机控制系统,要求系统具有以下功能。

(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 #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 keybscan(void) {uchar scode,rcode; }

/*返回键码子程序*/ 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

因篇幅问题不能全部显示,请点此查看更多更全内容

Top