步进电机实际上是一个数字/角度转换器,也是一个串行的数/模转换器。因此,需把并行的二进制转换成串行的脉冲序列,并实现方向控制。每当步进电机脉冲输入线上得到一个脉冲,它便沿着特定的方向走一步。
设计要求:
采用单片机来控制一个三相单三拍的步进电机工作。步进电机的旋转方向由正反转控制信号来控制。步进电机的步数由键盘输入,可输入的步数分别为3,6,9,12,15,18,21,24,27步。并且键盘具有键盘锁的功能,当键盘上锁的时候,步进电机是不接受输入步数的,也不会运转。只有当键盘锁打开并输入步数的时候,步进电机才开始工作 。电机运转的时候有正转和反转指示灯指示。当电机在运转的过程当中,如果过热,则电机停止运转,同时红色指示灯亮.,同时警报响。
目录
1、绪论4
2、方案论证(规划、选定)7
3、方案说明(设计)7
4、硬件方案设计8
5、软件方案设计12
6、调试13
7、技术小结(结束语)14
8、参考文献15
9、附录(源程序代码、电路图等)16
1. 绪论 1.1步进电机是用电脉冲信号控制,以实现对生产过程或设备的数字控制,它是过程控制中一种十分重要和常用的功率执行器件,它可以把脉冲信号转换成角位移,并且可用作电磁制动轮、电磁差分器或角位移发生器等,近年来由于计算机应用技术的迅速发展,步进电机常常和计算机一起组成高精度的数字控制系统。由于它是由数字脉冲控制,因此非常适合于用单片机控制,本设计便是在此基础上,AT89C51型单片机为核心,并结合外围电路以步进电机为控制对象的控制系统。
1.2单片机控制步进电机原理 步进电机的不同驱动方式,都是在工作时,脉冲信号按一定顺序轮流加到三相绕组上,从而实现不同的工作状态。由于通电顺序不同,其运行方式有三相单三相拍、三相双三拍和三相单、双六拍三种(注意:上面“三相单三拍”中的“三相”指定子有三相绕组;“拍”是指定子绕组改变一次通电方式;“三拍”表示通电三次完成一个循环。“三相双三拍”中的“双”是指同时有两相绕组通电)。 1.2.1三相单三拍运行方式:下页图所示为反应式步进电动机工作原理图,若通过脉冲分配器输出的第一个脉冲使A相绕组通电,B,C相绕组不通电,在A相绕组通电后产生的磁场将使转子 上产生反应转矩,转子的1、3齿将与定子磁极对齐,如果图(a)所示。第二个脉冲到来,使B相绕组通电,而A、C相绕组不通电;B相绕组产生的磁场将 使转子的2、4齿与B相磁极对齐,如图(b)所示,与图(a)相比,转子逆时针方向转动了一个角度。第三个脉冲到来后,是C相绕组通电,而 A、B相不通电,这时转子的1、3齿会与C组对齐,转子的位置如图(c)所示,与图(b)比较,又逆时针转过了一个角度。 
图1.1 反应式步进电机工作原理图 当脉冲不断到来时,通过分配器使定子的绕组按着A相--B相--C相--A相……的规律不断地接通与断开,这时步进电动机的转子就连续不停地一步步的逆时 针方向转动。如果改变步进电动机的转动方向,只要将定子各绕组通电的顺序改为A相--C相--B相--A相,转子转动方向即改为顺时针方向。 单三拍分配方式时,步进电动机由A相通电转换到B相通电,步进电动机的转子转过一个角度,称为一步。这时转子转过的角度是30度。步进电动机每一步转过的角度称为步距角。 1.2.2三相双三拍运行方式三相双三拍运行方式:每次都有两个绕组通电,通电方式是AB--BC--CA--AB……,如果通电顺序改为AB--CA--BC--AB……则步进电机反转。双三拍分配方式时,步进电动机的步距角也是30度 1.2.3三相单,双六拍运行方式:三相六拍分配方式就是每个周期内有六个通电状态。这六中通电状态的顺序可以使A--AB--B--BC--C--CA--A……或者A-- CA--C--BC--B--AB--A……六拍通电方式中,有一个时刻两个绕组同时通电,这时转子齿的位置将位于通电的两相的中间位置。在三相六拍分配 方式下,转子每一步转过的角度只是三相三拍方式下的一半,步距角是15度。 单三拍运行的突出问题是每次只有一相绕组通电,在转换过程中,一相绕组断电,另一相绕组通电,容易发生失步;另外单靠一相绕组通电吸引转子,稳定性不好,容易在平衡位置附近震荡,故用的较少。 双三拍运行的特点是每次都有两相绕组通电,且在转换过程中始终有一相绕组保持通电状态,因此工作稳定,且步距角与单三拍相同。 六拍运行方式转换时始终有一相绕组通电,且步距角较小,故工作稳定性好,但电源较复杂,实际应用较多。
2.方案论证 2.1本设计由于需要实现9个不同部数的输入以及其他功能的输入,所以可以采用键盘输入,实现步进电机的步数由键盘输入且具有键盘锁功能。而本实验单片机的端口数量充足,最后决定直接采用键盘输入。 2.2在步进电机方面由于此次设计的软件采用proteus,在此软件中只有一个四相步进电机的模型,然后考虑到步进电机控制方法的难易度最后决定采用四相八拍控制法,由于单片机不能直接驱动步进电机,通过芯片放大控制电压。 2.3在测量温度方面一开始打算用一个温度传感器开关去实现监测电机的温度,当温度过高的时候就断开开关;但考虑到系统的可操作性,准确性,编程的难以度及仿真软件的限制,最后决定用DS18B20代替电机的测量系统,实现电机在运动过程中,如果过热,则电机停止运转,同时红色指示灯亮,同时报警。而转向方面用不同的指示灯指示正转和反转。当温度超过安全温度时,报警灯会亮和报警铃会鸣响,并让电机停止运转同时锁住键盘。
3.方案说明 步进电机和普通电动机不同之处是步进电机接受脉冲信号的控制。即步进电机是将电脉冲信号转换为机械角位移的执行元件。步进电机的控制可以用硬件,也可以用软件通过单片机实现。硬件方法是采用脉冲分配器芯片进行通用换相控制;而软件方法是用单片机产生控制脉冲来控制步进电机的运行状态,这种方法可简化电路,降低成本。 在用软件控制时,主要设计要点如下: - 判断旋转方向;
- 按相序确定控制字;
- 按顺序输入控制字;
- 确定控制步数和每一步的延时时间。
由于单片机的驱动电流一般都比较小,不能直接驱动电机工作,所以单片机的I/O口输出必须接驱动电路,即功率驱动,才得以控制电机正常工作。控制框图如下图所示: 开始启动时点击处于停止转动状态,用键盘按键控制键盘锁、步数、正转、反转。用80c51作为总控制芯片。ULN2003用于步进电机的驱动控制。其中在键盘控制时用键盘扫描程序。 图3.1 总方案图 4.硬件方案设计 系统硬件设计 4.1最小单片机系统 5V电源:给系统供电。 复位电路:程序跑飞时复位电路可以使程序从新执行,相当于电脑的重启。 晶振:给单片机运行提供时钟。 EA接高电平:表示运行内部程序存储器下载的程序。 P0接排阻:P0口开漏结构,使用时一般接排阻拉高电平。 4.2键盘设计 该电路中采用独立键盘工作方式,共设有十二个按键,分别是3,6,9,12,15,18,21,24,27布局选择功能,键盘锁功能以及步进电机转动方向选择功能。其中有程序决定起作用。 4.3步进电机 步进电机的驱动采用ULN2003,接到单片机的P1.0~P1.3,如图步进电机驱动和单片机连线图。
4.4正反转显示灯和报警灯铃
4.5温度传感器模块 5.软件设计 主程序流程图所示如下: 6.调试 6.1 Proteus仿真软件 Proteus是世界上著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。是目前世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,2010年又增加了Cortex和DSP系列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、Keil和MPLAB等多种编译器。 6.2 调试步骤及方法 本电路经调试符合题目要求,各项技术指标均达到设计的目的。具体操作控制方法如下: 1、当电机按下启动按钮时,步进电机根据制定默认状态开始转动; 2、当电机按下停止按钮时,步进电机停止转动; 3、当电机按下正转按钮时,步进电机正转; 4、当电机按下反转按钮时,步进电机反转; 5﹑当电机按下步数按钮时,步进电机根据步数实现转动
7.技术小结 为期一周的单片机课程设计在忙碌中已接近尾声,经过这么多天的努力,终于完成了这次课程设计基本设计要求,在充实中也学到了很多知识,是真正将所学知识运用于实践中的一次很好的体验,使人受益匪浅。由于此次控制要求不是很高,选用51系列80C51。接下来就是硬件接口分配问题和如何去驱动电机。对于步进电机之前没有什么接触,所以我上网查了许多关于步进电机的资料,知道了其基本工作原理以及怎么去实现其控制运转和驱动。接下来的主要问题就是如何编程去实现控制它了,这次程序的编写和调试对我来说是个不小的挑战,因为之前只编写过一些简短的小程序,对较大的程序总体性方面还不能很好的把握。经过反复的尝试和调试,用发现一个问题,解决一个问题的方法,还参考了一些别人的经验方法,完成了程序的编写。这对我以后编写程序是一次很好的经验积累。通过这次课程设计,我也了解到了自己的不足,以前自己学习单片机的时候,往往只去看懂别人写的程序,以为看懂了自己就知道写了,但事实并不是这样,虽然这次课程设计程序是完成了,但棘手的地方很多,编程并不像以前认为的简单。所以在以后的学习中,不能手高眼低,一定要脚踏实地,一步步地走,自己动手去做,这样才能将知识真正学到手。这次课程设计能得以顺利完成,还要感谢毛老师的指导,感受很深,是一次很好的经验积累和设计经历。
仿真图
单片机源程序如下: - #include<reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define led P0//数码管段选
- #define haha P2
- sbit s1 = P0^1;
- sbit s2 = P0^2;//按键定义,s1正转,s2反转
- sbit s3 = P0^3;//按键定义,停止
- sbit speaker = P0^4;
- sbit LED1 = P0^5;
- sbit LED2 = P0^6;
- sbit LED3 = P0^7;
-
- sbit a = P2^3;
- sbit b = P2^2;
- sbit c = P2^1;
- sbit d = P2^0;//脉冲信号输入端定义
-
- sbit _key3 =P1^0; //3步
- sbit _key6 =P1^1; //6步
- sbit _key9 =P1^2; //9步
- sbit _key12 =P1^3; //12步
- sbit _key15 =P1^4; //15步
- sbit _key18 =P1^5; //18步
- sbit _key21 =P1^6; //21步
- sbit _key24 =P1^7; //24步
- sbit _key27 =P0^0; //27步
-
- unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9
- unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
- unsigned char TempData[8]; //存储显示值的全局变量
-
- /*------------------------------------------------
- DS18B20 端口定义
- ------------------------------------------------*/
- sbit DQ=P2^7;//ds18b20 端口
- bit ReadTempFlag;//定义读时间标志
- /*------------------------------------------------
- 函数声明
- ------------------------------------------------*/
- unsigned int ReadTemperature(void);
- bit Init_DS18B20(void);
- unsigned char ReadOneChar(void);
- void WriteOneChar(unsigned char dat);
- void DelayUs2x(unsigned char t);
- void DelayMs(unsigned char t);
- void _18b20(void);
- //DS18B20定义
- /*-----------------------------------------------*/
-
- uchar code display[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//共阳数码管驱动信号0---9,不显示
- uchar code time_counter[10][2]={{0xda,0x1c},{0xde,0xe4},{0xe1,0xec},{0xe5,0xd4},{0xe9,0xbc}, //9.7 ----1ms
- {0xed,0xa4},{0xf1,0x8c},{0xf5,0x74},{0xf9,0x5c},{0xfc,0x18}};
- uchar num1 = 0;//控制取励磁信号变量
- uchar num2 = 8;
- uchar bushu = 0;
-
- uchar k=1;//加减档位控制,1为最小档
- bit flag1 = 0;//初始正转,正反转标志
- uchar buf[4]={0,10,10,1};//数码管显示缓存,正转,不显示,不显示,显示1档位,高----低(不能去掉)
- void key(void);
- void keyscan(void);
- //================================定时器0/1初始化函数================================
- void T0_T1_init()
- {
- TMOD = 0x11;//定时器0/1均工作于方式1,16位计时方式
- TH0 = (65536 - 4000)/256;
- TL0 = (65536 - 4000)%256;//定时器0,定时4ms用于数码管扫描显示
- TH1 = time_counter[k-1][0];
- TL1 = time_counter[k-1][1];//定时器1,定时10ms用于步进电机转速控制
- TR0 = 1;
- TR1 = 1;
- ET0 = 1;
- ET1= 1;//开定时器中断
- EA = 1;//开总中断
- }
- //================================ms级延时函数=======================================
- void delay1m(uint x)
- {
- uint i,j;
- for(i=0;i<x;i++) //连数x次,约 x ms
- for(j=0;j<120;j++); //数120 次,约1 ms
- }
- //================================主函数=============================================
- void main()
- {
- T0_T1_init();
- Init_DS18B20();
- //buf[1] = 10;//不显示
- LED3 = 1; speaker =1;
- while(1)
- {
- if(s1 == 0)
- {
- delay1m(3);
- if(s1 == 0)
- {
- flag1 = 0;//正转
- haha = 0x00;//停止
-
- }
- while(!s1);
- }
- if(s2 == 0)
- {
-
- delay1m(3);
- if(s2 == 0)
- {
- flag1 = 1;//反转
- haha = 0x00;//停止
- }
- while(!s2);
- }
- if(s3 == 0) {
- delay1m(3);
- if(s3 == 0) {
- EA = 0;
- LED2 = 1;
- LED1 = 1;
- LED3 = 1; speaker =1;
- }
- }
- else {
- EA = 1;
- }
- key();
- _18b20();
- }
-
- }
- //==================================定时器1中断函数,用于脉冲频率控制=====================================
- void time1_interrupt()interrupt 3
- {
- static num1 = 0;
- static num2 = 0;
- uchar m = 0;
- TH1 = time_counter[k-1][0];
- TL1 = time_counter[k-1][1];//定时器1,定时1 用于步进电机转速控制
- m = bushu;
- for(;m > 0; m--) {
- if(flag1 == 0)//正转
- {
- LED3 = 1;speaker =1;
- LED1 = 0;
- LED2 = 1;
- switch(num1)
- {
- case 0:a = 1;b = 0;c = 0;d = 0;break;
- case 1:a = 1;b = 1;c = 0;d = 0;break;
- case 2:a = 0;b = 1;c = 0;d = 0;break;
- case 3:a = 0;b = 1;c = 1;d = 0;break;
- case 4:a = 0;b = 0;c = 1;d = 0;break;
- case 5:a = 0;b = 0;c = 1;d = 1;break;
- case 6:a = 0;b = 0;c = 0;d = 1;break;
- case 7:a = 1;b = 0;c = 0;d = 1;break;
- }
- num1++;
- if(num1 == 8)num1 = 0;
- }
- else //反转
- {
- LED3 = 1;speaker =1;
- LED1 = 1;
- LED2 = 0;
- switch(num2)
- {
- case 0:a = 1;b = 0;c = 0;d = 1;break;
- case 1:a = 0;b = 0;c = 0;d = 1;break;
- case 2:a = 0;b = 0;c = 1;d = 1;break;
- case 3:a = 0;b = 0;c = 1;d = 0;break;
- case 4:a = 0;b = 1;c = 1;d = 0;break;
- case 5:a = 0;b = 1;c = 0;d = 0;break;
- case 6:a = 1;b = 1;c = 0;d = 0;break;
- case 7:a = 1;b = 0;c = 0;d = 0;break;
- }
- num2++;
- if(num2 == 8)num2 = 0;
- }
- }
- }
-
- void key()
- {
- if(s3 == 1) //这里开关闭合,表示键盘锁打开。如果开关不闭合,表示上锁,电机不转
- {
- delay1m(100);
- if(s3 == 1) {
- if(_key27==0) bushu=27; //步数高的优先,即多个步数开关同时打上,运行高步数
- else if(_key24==0) bushu=24;
- else if(_key21==0) bushu=21;
- else if(_key18==0) bushu=18;
- else if(_key15==0) bushu=15;
- else if(_key12==0) bushu=12;
- else if(_key9==0) bushu=9;
- else if(_key6==0) bushu=6;
- else if(_key3==0) bushu=3;
- }
- }
- }
- //以下为18B20程序
- /*------------------------------------------------
- 18b20初始化
- ------------------------------------------------*/
- bit Init_DS18B20(void)
- {
- bit dat=0;
- DQ = 1; //DQ复位
- DelayUs2x(5); //稍做延时
- DQ = 0; //单片机将DQ拉低
- DelayUs2x(200); //精确延时 大于 480us 小于960us
- DelayUs2x(200);
- DQ = 1; //拉高总线
- DelayUs2x(50); //15~60us 后 接收60-240us的存在脉冲
- dat=DQ; //如果x=0则初始化成功, x=1则初始化失败
- DelayUs2x(25); //稍作延时返回
- return dat;
- }
-
- /*------------------------------------------------
- 读取一个字节
- ------------------------------------------------*/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 给脉冲信号
- dat>>=1;
- DQ = 1; // 给脉冲信号
- if(DQ)
- dat|=0x80;
- DelayUs2x(25);
- }
- return(dat);
- }
- /*------------------------------------------------
- 写入一个字节
- ------------------------------------------------*/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- DelayUs2x(25);
- DQ = 1;
- dat>>=1;
- }
- DelayUs2x(25);
- }
-
- /*------------------------------------------------
- 读取温度
- ------------------------------------------------*/
- unsigned int ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned int b=0;
- unsigned int t=0;
- Init_DS18B20();
- WriteOneChar(0xCC); // 跳过读序号列号的操作
- WriteOneChar(0x44); // 启动温度转换
- DelayMs(10);
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
- a=ReadOneChar(); //低位
- b=ReadOneChar(); //高位
-
- b<<=8;
- t=a+b;
-
- return(t);
- }
-
- /*------------------------------------------------
- uS延时函数,含有输入参数 unsigned char t,无返回值
- unsigned char 是定义无符号字符变量,其值的范围是
- 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
- 长度如下 T=tx2+5 uS
- ------------------------------------------------*/
- void DelayUs2x(unsigned char t)
- {
- while(--t);
- }
-
- /*------------------------------------------------
- mS延时函数,含有输入参数 unsigned char t,无返回值
- unsigned char 是定义无符号字符变量,其值的范围是
- 0~255 这里使用晶振12M,精确延时请使用汇编
- ------------------------------------------------*/
- void DelayMs(unsigned char t)
- {
-
- while(t--)
- {
- //大致延时1mS
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
-
- /*------------------------------------------------
- 定时器中断子程序
- ------------------------------------------------*/
- void Timer0_isr(void) interrupt 1
- {
- static unsigned int num;
- TH0=(65536-2000)/256; //重新赋值 2ms
- TL0=(65536-2000)%256;
- num++;
- if(num==300) //
- {
- num=0;
- ReadTempFlag=1; //读标志位置1
- }
- }
-
- void _18b20(void) {
- unsigned int TempH,TempL,temp; //TempH,TempL
- if(ReadTempFlag==1)
- {
- ReadTempFlag=0;
- temp=ReadTemperature();
- if(temp&0x8000)
- {
- TempData[0]=0x40;//负号标志
- temp=~temp; // 取反加1
- temp +=1;
- }
- else
- TempData[0]=0;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
完整的Word格式文档51黑下载地址:
单片机三相单三拍步进电机.doc
(1.6 MB, 下载次数: 49)
|