江西农大
单片机原理及应用
课程设计报告
设计课题: 单片机控制步进电机
专业班级: 信工091班
学生姓名: 崔**
指导教师: 何老师
2012 年 5 月
目 录
目 录·· 1
1 设计任务书·· 2
1.1 基本设计要求·· 2
1.2 选作项目·· 2
2 设计阐明·· 3
2.1设计内容·· 3
2.2设计要求·· 3
2.3设备及工作环境·· 3
3 系统方案整体设计·· 4
3.1 设计思路·· 4
4 硬件设计·· 6
4.1 系统硬件设计·· 6
4.1.1 最小单片机系统·· 6
4.1.2 键盘设计·· 6
4.2 系统工作原理论述·· 7
5 软件设计·· 9
5.1 分析论证·· 9
5.1.1 步进电机运行驱动模块·· 9
5.1.2 温度采集模块·· 9
5.1.3 主函数模块·· 9
5.1.4 整体功效·· 9
5.2 程序流程图·· 10
5.3程序清单·· 11
6 调试过程及分析·· 18
7 设计总结·· 19
参 考 文 献·· 20
1 设计任务书
1.1 基本设计要求
(1)用万能板、主芯片AT89S52、35BYJ412步进电机、BLN2003以及其他周围原件芯片完成实验设计。
(2)程序的首地址应使目标机可以直接运行,即从0000H开端。在主程序的开端部分必须设置一个合适的栈底。程序放置的地址须持续且靠前,不要在中间留下大批的空间地址,以使目标机可以应用较少的硬件资源。
(3)采用单片机控制一个三相单三拍的步进电机工作。步进电机的旋转方向由正反转控制信号控制。步进电机的步数由键盘输入,可输入的步数分别为3、6、9、12、15、18、21、24和27步,且键盘具有键盘锁功能,当键盘上锁时,步进电机不接受输入步数,也不会运转。只有当键盘锁打开并输入步数时,步进电机才开始工作。
(4)电机运转的时候有正转和反转指示灯指示。
(5)电机在运转过程中,如果过热,则电机停止运转,同时红色指示灯亮,同时警报响。本题目的关键之处是:如何生成控制步进电机的脉冲序列。
1.2 选作项目
1、用单片机(AT89S52)为主芯片设计电路来控制步进电机。
2、设三个自锁按键,分别作开关键盘、左转、右转控制。
3、设9个触电按键分别控制输入的步数为3、6、9、12、15、18、21、24和27步。
4、设置一片LCD12864显示器实时显示步进电机工作状态,并提示用户步操作。
2 设计阐明
2.1设计内容
用ZY15MCU12BD型综合单片机实验箱仿真实现控制步进电机集采问过程。
2.2设计要求
(1)采用单片机控制一个三相单三拍的步进电机工作。步进电机的旋转方向由正反转控制信号控制。步进电机的步数由键盘输入,可输入的步数分别为3、6、9、12、15、18、21、24和27步,且键盘具有键盘锁功能,当键盘上锁时,步进电机不接受输入步数,也不会运转。只有当键盘锁打开并输入步数时,步进电机才开始工作。
(2)电机运转的时候有正转和反转指示灯指示。
(3) 电机在运转过程中,如果过热,则电机停止运转,同时红色指示灯亮,同时警报响。
(4) 上机调试程序。
(5) 写出设计报告。
2.3设备及工作环境
(1) 硬件:AT89S52单片机一片、35BYJ412步进电机一台、ISP下载器一个、LCD12864显示器、温度传感器18B20芯片。
(2) 软件:Windows操纵系统、Keil C51软件。
3 系统方案整体设计
3.1 设计思路
步进电机的不同驱动方式,都是在工作时,脉冲信号按一定顺序轮流加到三相绕组上,从而实现不同的工作状态。由于通电顺序不同,其运行方式有三相单三相拍、三相双三拍和三相单、双六拍三种(注意:上面“三相单三拍”中的“三相”指定子有三相绕组;“拍”是指定子绕组改变一次通电方式;“三拍”表示通电三次完成一个循环。“三相双三拍”中的“双”是指同时有两相绕组通电)。
(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)比较,又逆时针转过了一个角度。
图 反应式步进电机工作原理图
当脉冲不断到来时,通过分配器使定子的绕组按着A相--B相--C相--A相……的规律不断地接通与断开,这时步进电动机的转子就连续不停地一步步的逆时 针方向转动。如果改变步进电动机的转动方向,只要将定子各绕组通电的顺序改为A相--C相--B相--A相,转子转动方向即改为顺时针方向。
单三拍分配方式时,步进电动机由A相通电转换到B相同点,步进电动机的转子转过一个角度,称为一步。这时转子转过的角度是30度。步进电动机每一步转过的角度称为步距角。
(2)三相双三拍运行方式三相双三拍运行方式:每次都有两个绕组通电,通电方式是AB--BC--CA--AB……,如果通电顺序改为AB--CA--BC--AB……则步进电机反转。双三拍分配方式时,步进电动机的步距角也是30度
(3)三相单,双六拍运行方式:三相六拍分配方式就是每个周期内有六个通电状态。这六中通电状态的顺序可以使A--AB--B--BC--C--CA--A……或者A-- CA--C--BC--B--AB--A……六拍通电方式中,有一个时刻两个绕组同时通电,这是转子齿的位置将位于通电的两相的中间位置。在三相六拍分配 方式下,转子每一步转过的角度只是三相三拍方式下的一半,步距角是15度。
单三拍运行的突出问题是每次只有一相绕组通电,在转换过程中,一相绕组断电,另一相绕组通电,容易发生失步;另外单靠一相绕组通电吸引转子,稳定性不好,容易在平衡位置附近震荡,故用的较少。
双三拍运行的特点是每次都有两相绕组通电,且在转换过程中始终有一相绕组保持通电状态,因此工作稳定,且步距角与单三拍相同。
六拍运行方式转换时始终有一相绕组通电,且步距角较小,故工作稳定性好,但电源较复杂,实际应用较多。
4 硬件设计
4.1 系统硬件设计
4.1.1 最小单片机系统
5V电源:给系统供电。
复位电路:程序跑飞时复位电路可以使程序从新执行,相当于电脑的重启。
晶振:给单片机运行提供时钟。比如电脑的2.2GHz频率。
EA接高电平:表示运行内部程序存储器下载的程序。
P0口接排阻:P0口开漏结构,使用时一般接排阻拉高电平。
4.1.2 键盘设计
该电路中采用独立键盘工作方式,共设有12个按键,分别提供3、6、9、12、15、18、21、24布局选择功能、键盘锁功能以及步进电机转动方向选择功能。其中有程序决定起作用。
4.2 系统工作原理论述
该系统的工作核心CPU为ATMEL公司生产的AT89S52芯片将多种功能的8位CPU与FPEROM(快闪可编程/擦除只读存储器)结合在一个芯片上,是一种低功耗、高性能的CMOS控制器,为很多嵌入式控制应用提供了非常灵活而又价格适宜的方案,其性能价格比远高于同类芯片。它与MCS-51指令系统兼容,片内FPEROM允许对程序存储器在线重复编程,也可用常规的EPROM编程器编程,可循环写入/擦除1000次。89S52内含4KB的FPEROM,一般的EEPROM的字节擦除时间和写入时间基本上均为10ms,对于任一个实时控制系统来说,这样长的时间是不可能在线修改程序的。
l CPU为Atmel公司生产的89C51/89C52/89C55等。出厂所配晶振频率为11.0592MH,每个机器周期为1.085us,用户更换晶振以提高速度;
l 存贮器为64K,前4K/8K20K在CPU内部,其它程序在EPR0M27512中;
l 数据存贮器为32K(62256),地址为8000—FFFFH;
l Ⅰ/O扩展8155,片内RAM地址∶200O-20FFH ;
l 8155命令口地址为∶2100H ;
l A口地址∶21O1H B口地址:2102H C口地址:2103H ;
l T低八位∶2104H T高八位∶2105H ;
l 多路模拟开关的使用∶
IN0∶P1=0F8H IN4:P1=0FCH IN1∶P1=0F9H IN5:P1=OFDH
IN2∶P1=0FAH IN5:P1=0FEH IN3∶P1=0FBH IN7:P1=0FFH
l 不掉电数据存贮器为∶500EH-507FH ;
l 控制板∶160x1O9(mm) 供电∶+5V300mA +12V100mA -12V100mA ;
l AT89C51是一种低功耗、高性能的片内含有4KB快闪可编程/擦除只读存储器(FPEROM-Flash Programmable and Eraseable Read Only Memory)的8位CMOS微控制器,使用高密度、非易失存储技术制造,并且与80C51引脚和指令系统完全兼容;
l 主要性能:
与MCS-51 微控制器产品系列兼容;
片内有4KB可在线重复编程的快闪擦写存储器 。
引脚简介:
整体介绍:
该系统采用的芯片还有:DS18B20温度传感器、ULN2003A以及MP28GA四相五线步进电机,并且步进电机在双八拍的方式下工作,步矩为 5.625° ,步进电机的旋转方向由正反转控制信号控制。步进电机的步数由键盘输入,可通过独立键盘S1~S9输入的步数分别为3、6、9、12、15、18、21、24和27步对应的角度为16.875°、33.725°、……、151.875°,且键盘S10具有键盘锁功能,当键盘上锁时,步进电机不接受输入步数,也不会运转。只有当键盘锁打开,选择运转方向并且输入步数时,步进电机才开始工作。
电机运转的时候有正转指示灯D2和反转指示灯D3指示。
电机在运转过程中用温度传感器采集步进电机外表温度(可设置),如果过热,则电机停止运转,同时红色指示灯亮,同时蜂鸣器警报响。
5 软件设计
5.1 分析论证
此步进电机控制电路设计与实现,主要采用了ULN2003A驱动芯片,温度传感器芯片DS18B20芯片,独立键盘等,包含步进电机运行驱动,温度采集,主函数三大功效模块。
5.1.1 步进电机运行驱动模块
由于该系统中没有完全使用I/O端口,所以采用了独立键盘的工作方式,系统工作时,键盘控制的I/O口处于高电平状态,当按键按下时触发低电平,驱动程序实时监测并立即响应执行相应工作。
5.1.2 温度采集模块
该模块的重要功效是对步进电机的外表采集温度,并且对已设定好的数值进行比较,从而确定机身温度是否过高,正常时电机正常转动,当温度过高时电机不再转动,并且蜂鸣器报警,红灯点亮。
5.1.3 主函数模块
该模块重要功效是调动温度采集函数、步进电机函数中函数,实现模块化编程。
5.1.4 整体功效
AT89S52芯片控制ULN2003A芯片驱动步进电机,扫描键盘输入运行状态以及运转步数,当电机外表温度超过32℃是电机停止转动,并且报警!
5.2 程序流程图
主程序流程图如图所示:
是
否
是
否
否
图2 程序流程图
5.3程序清单
步进电机驱动函数:
//BJDJ.h
#ifndef _BJDJ_H_
#define _BJDJ_H_
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;
sbit k6=P1^5;
sbit k7=P1^6;
sbit k8=P1^7;
sbit k9=P0^0;
sbit k10=P0^1;
sbit k11=P0^2;
sbit k12=P0^3;
void key_scan();
void motor_turn();
void motor_stop();
#endif
//BJDJ.c
#include"BJDJ.h"
uchar code FFW[8]={0xfe,0xfc,0xfd,0xf9,0xfb,0xf3,0xf7,0xf6};
uchar code REV[8]={0xf6,0xf7,0xf3,0xfb,0xf9,0xfd,0xfc,0xfe};
uchar rate ;
extern uchar i=0;
/********************************************************/
/* 延时
/********************************************************/
void delay(uchar x)
{
uchar i,j;
for(i=0;i<x;i++);
for(j = 0 ; j<110 ; j++) ;
}
/********************************************************/
/*步进电机正转
/********************************************************/
void motor_ffw(uchar x)
{
uchar i,j;
for (j=0; j<x; j++) //转1*n圈
{
for (i=0; i<8; i++) //一个周期转45度
{
P2 = FFW[i]; //取数据
delay(150); //调节转速
}
}
}
/********************************************************/
/*
/*步进电机反转
/********************************************************/
void motor_rev(uchar x)
{
uchar i,j;
for (j=0; j<x; j++) //转1*n圈
{
//退出此循环程序
for (i=0; i<8; i++) //一个周期转45度
{
P2 = REV[i]; //取数据
delay(150); //调节转速
}
}
}
/*******************************************************
*键盘扫描
******************************************************/
void key_scan()
{
i=0;
if(k1==0)
{
delay(5);
if(k1==0)i=24;
}
if(k2==0)
{
delay(5);
if(k2==0)i=46;
}
if(k3==0)
{
delay(5);
if(k3==0)i=72;
}
if(k4==0)
{
delay(5);
if(k4==0)i=96;
}
if(k5==0)
{
delay(5);
if(k5==0)i=120;
}
if(k6==0)
{
delay(5);
if(k6==0)i=144;
}
if(k7==0)
{
delay(5);
if(k7==0)i=168;
}
if(k8==0)
{
delay(5);
if(k8==0)i=192;
}
if(k9==0)
{
delay(5);
if(k9==0)i=216;
}
}
/********************************************************
*电机转动
********************************************************/
void motor_turn()
{
if(k10==0)
{
delay(5);
if(k10==0)P2=P2&0xf0;
}
if(k11==0&&k12==1&&k10==1)
{
delay(5);
if(k11==0&&k12==1&&k10==1)
motor_ffw(i);
}
if(k12==0&&k11==1&&k10==1)
{
delay(5);
if(k12==0&&k11==1&&k10==1)
motor_rev(i);
}
}
void motor_stop()
{
motor_rev(0);
}
温度传感器18B20驱动函数:
//DS18B20.h
#ifndef __DS18B20_H__
#define __DS18B20_H__
#include<reg52.h>
#include < intrins.h >
#define uint unsigned int
#define uchar unsigned char
extern uchar T;
sbit DQ=P2^7; //温度输入口
sbit bell=P0^4;
sbit led1=P0^7;
void delay2(uint t);
void ow_reset(void);
void write_byte(uchar val);
void read_temp();
void work_temp();
#endif
//DS18B20.c
#include"DS18B20.h"
extern uchar data temp_data[2]={0x00,0x00};
uchar flag;
char presence=1;
uchar T;
/***********11微秒延时函数**********/
void delay2(uint t)
{
for(;t>0;t--);
}
/***********18B20复位函数**********/
void ow_reset(void)
{
presence=1;
while(presence)
{
while(presence)
{
DQ=1;_nop_();_nop_();
DQ=0; //
delay2(50); // 550us
DQ=1; //
delay2(6); // 66us
presence=DQ; // presence=0继续下一步
}
delay2(45); //延时500us
presence = ~DQ;
}
DQ=1;
}
/**********18B20写命令函数*********/
void write_byte(uchar val)
{
uchar i;
for (i=8; i>0; i--)
{
DQ=1;
_nop_();_nop_();
DQ = 0;
_nop_();_nop_();_nop_();_nop_();_nop_();//5us
DQ = val&0x01; //最低位移出
delay2(6); //66us
val=val/2; //右移一位
}
DQ = 1;
delay2(1);
}
/*********18B20读1个字节函数********/
uchar read_byte(void)
{
uchar i;
uchar value = 0;
for (i=8;i>0;i--)
{
DQ=1;
_nop_();_nop_();
value>>=1;
DQ = 0; //
_nop_();_nop_();_nop_();_nop_(); //4us
DQ = 1;
_nop_();_nop_();_nop_();_nop_(); //4us
if(DQ)value|=0x80;
delay2(6); //66us
}
DQ=1;
return(value);
}
/***********读出温度函数**********/
void read_temp()
{
ow_reset(); //总线复位
write_byte(0xCC); // 发Skip ROM命令
write_byte(0xBE); // 发读命令
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
ow_reset();
write_byte(0xCC); // Skip ROM
write_byte(0x44); // 发转换命令
}
/***********温度数据处理函数**********/
void work_temp()
{
T=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x07)<<4);
}
主函数:
//main.c
#include"DS18B20.h"
#include"BJDJ.h"
void main()
{
while(1)
{
T=0;
P1=0xff;
P0=0x0f;
led1=1;
ow_reset(); // 开机先转换一次
write_byte(0xCC); // Skip ROM
write_byte(0x44); // 发转换命令
read_temp(); //读出18B20温度数据
work_temp(); //处理温度数据
key_scan();
if(T>31)
{
motor_stop();
led1=0;
bell=1;
delay2(1000);
}
else
{
led1=1;
bell=0;
motor_turn();
}
}
}
6 调试过程及分析
编写好的源程序在 Keil 编译后呈现很多错误,这些错误有很多时平时的实验碰到过的,例如:字母开头忘加0,零和字母O弄混杂了,有些标号用了几次,CJNE写成了CJNZ等等,幸好这些错误在平时的实验中碰到了,所以改错误很轻易,。除了常见的错误外,还有几条错误时在前几次实验都没有出现过,如:AJMP跳转指令跳不回指定的地位,是由于跳转的长度大于AJMP跳转的长度,最后只好用LJMP跳转后才跳到指定的地位。在前期的程序编写和几天的上机调试,使我又获得了很多新的知识,由于前期编写程序时查了很多材料学到了很多知识,这几天的调试更时获得很新的知识,由于程序中又很多的错误,为了修正错误必须看书或向别人请教,在这个过程中无意识的获得了很多知识。同时也使我对单片机更感兴趣了,这点我感到很重要,相信这会对以后的学习有所帮助。
7 设计总结
本次课程设计是用ZY15MCU12BD综合单片机实验箱及串口电路设计单片机驱动步进电机电路,经过两个星期的调试,成果满足基本设计请求,验证无误。设计重要用到了多种芯片,程序也比较长,比较麻烦,同时也碰到了不少艰苦,尤其是关于校时模块和时钟与秒表之间切换的设计实现。关于显示模块,在以前的实验中做过,所以题目很轻易解决。
通过本次设计,我懂得了时钟的设计流程,尤其是硬、软件的设计方法以及键盘显示电路的基础功效及编程方法和键盘电路和显示电路的一般原理,也进一步了解了8031定时器的应用和中断CPU程序的编程方法,开辟了思路,,提高了分工协作才能和分析题目,解决题目的能力。
参 考 文 献
1.张毅刚编著,《单片机原理及应用》高等教育出版社,2010。
2.郭天祥编著,《Altium Designer6.9 PCB设计视频教程》,2007。
3.楼然苗等编著,《51系列单片机设计实例》北京航空航天大学出版社,2006。
4.汪道辉编著,《单片机系统设计与实践》 电子工业出版社 2005。
5.谭浩强编著,《C程序设计(第三版)》清华大学出版社 2005。
6.王港元编著,《电工电子实践指导》江西科学技术出版社 2008。
7.周润景编著,《PROTEUS入门实用教程》机械工业出版社 2011。
8.林立编著,《单片机原理及应用:基于Proteus和Keil C》电子工业出版社 2011。
9.阎石编著,《数字电子技术基础》高等教育出版社,2006。