资源描述
. .
单片机课程综合设计
设计题目:
基于单片机的秒表设计
学号:、、、
XX:杨晓博尹序鑫罗恩勇陈晓峰
班级 :电气1302
提交日期 :2015.12.26
信息与电气工程学院
目录
1 概述5
1.1 根本要求:5
2 系统总体方案及硬件设计6
2.1系统总体方案6
2.2硬件电路设计7
〔1〕单片机简介7
〔2〕电源电路8
〔3〕晶体振荡电路8
〔4〕复位电路8
〔5〕显示电路9
〔6〕键盘电路10
3 软件设计11
3.1软件设计概述11
3.2程序流程图12
Proteus软件仿真14
4.1软件功能简介15
4.2 Proteus运行流程16
5课程设计体会18
课程小结19
附1 源程序代码21
摘要
本设计是一个利用单片机控制的多功能秒表系统,它是基于51系列的单片机进展的系统设计。它采用STC12C52A60S2单片机为中心器件,利用其定时器/计数器定时和记数的原理,结合显示电路、电源电路、LED数码管以及键盘电路来设计计时器。将软、硬件有机地结合起来,使得系统能够实现四位LED显示,最大显示时间为9分59.9秒,每毫秒自动加1,一个开场暂停按键、一个复位按键。其突出的优点:体积小、场外作业、功耗最低、宜用电池作为电源、硬件构造紧凑、简单和软件设计灵活.
当今时代,是一个新技术层出不穷的时代。在电子领域,尤其是自动化智能控制领域,传统的分立元件或数字逻辑电路构成的控制系统正以前所未见的速度被单片机智能控制系统所取代。单片机具有体积小、功能强、本钱低、应用面广等优点,可以说,智能控制与自动控制的核心就是单片机。单片机的出现是现代科技开展的一个重要的里程碑。由于单片机的集成度高、功能强,通用性好,特别是它具有体积下、重量轻、能耗低、价格廉价等优点,使单片机迅速得到推广应用,目前已成为测量控制应用系统中的优选机种和新电子产品的关键部件。
关键字:单片机,多功能秒表
一、概述
1.1 根本要求:
设计一个秒表,用4位的LED数码管显示时间,从00:00秒到59:59秒,然后利用2个按键来控制:按键1开场/暂停,按键2 归零。
发挥局部:
1、利用8位LED数码管,显示年月日时分秒,要求单片机掉电重启时,不影响时间计时。可选用RTC芯片配合钮扣电池,简化设计。
2、将时间转换为ASCII码,以9600 bps输出,与/由PC机进展同步。
二、系统总体方案及硬件设计
2.1系统总体方案
本系统采用STC12C52A60S2单片机为中心器件,利用其定时器/计数器定时和记数的原理,结合硬件电路如电源电路,晶振电路,复位电路,显示电路,以及一些按键电路等来设计计时器,将软、硬件有机地结合起来。其中软件系统采用汇编语言编写程序,包括显示程序,计数程序,中断,硬件系统利用PROTEUS强大的功能来实现,简单切易于观察,在仿真中就可以观察到实际的工作状态。
外围电路
显示电路
单片机
电源电路
键盘电路
系统电路原理图
2.2硬件电路设计
本系统中,硬件电路主要有电源电路,晶振电路,复位电路,显示电路,以及一些按键电路等,本设计数码管采用共阳极四位数码管,总体电路图下
〔1〕单片机简介
本系统设计采用STC12C52A60S2单片机。
STC12C52A60S2是一种带4K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容〔由于在微机原理中学过C-51的具体知识,这里不再详细说明〕。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的STC12C52A60S2是一种高效的微控制器。
〔2〕电源电路
电源电路是系统最根本的局部,任何电路都离不开电源局部,由于三端集成稳压器件所组成的稳压电源线路简单,性能稳定,工作可靠,调整方便,已逐渐取代分立元件,在生产中被广泛采用,由于是小系统,我们采用7809电源提供+5V稳压电压。
〔3〕晶体振荡电路
MCS--51单片机内部的振荡电路是一个高增益反相放大器,引线 XTAL1和XTAL2分别为反向振荡放大器的输入及内部时钟工作电路的输入和来自反向振荡器的输出,该反向放大器可以配置为片内振荡器。
这里,我们选用51单片机12MHZ的内部振荡方式,电容器C1,C2起稳定振荡频率,快速起振的作用,C1和C2可在20-100PF之间取,这里取30P,接线时要使晶体振荡器X1尽可能接近单片机。
〔4〕复位电路
采用上电+按键复位电路,上电后,由于电容充电,使RST持续一段高电平时间。当单片机已在运行之中时,按下复位键也能使用使RST持续一段时间的高电平,从而实现上电加开关复位的操作。这不仅能使单片机复位,而且还能使
单片机的外围芯片也同时复位。当程序出现错误时,可以随时使电路复位。
〔5〕显示电路
显示电路既可以选用液晶显示器,也可以选用数码管显示。我们采用的是数码管显示电路。用4个共阳极LED显示,LED是七段式显示器,内部有7个条形发光二极管和1个小圆点发光二极管组成,根据各管的亮暗组合成字符。
在用数码管显示时,我们有静态和动态两种选择,静态显示程序简单,显示稳定,但是占用端口比拟多;动态显示所使用的端口比拟少,可以节省单片机的I/O口。
在设计中,我们采用LED动态显示,用P0口驱动显示。由于数码管使用的是共阳极,我们使用增强型51单片机具有的强推万挽模式,能够满足较大输出电流驱动数码管的要求。
电路图如下所示:
〔6〕键盘电路
在按键电路中,我们可以在I/O口上直接接按键,或者通过I/O口设计一个键盘,然后通过键盘扫描程序判断是否有键按下等。键盘扫描电路节省I/O口,但编程有些复杂,在这里,由于我们所用的按键较少,且系统是一个小系统,有足够的I/O口可以使用,为了使程序简化,我们采用按键电路,用局部P1口做开关,P1.0启动,P1.1清零,电路图如下所示
三、 软件设计
3.1软件设计概述
在软件设计中,一般采用模块化的程序设计方法,它具有明显的优点。把一个多功能的复杂的程序划分为假设干个简单的、功能单一的程序模块,有利于程序的设计和调试,有利于程序的优化和分工,提高了程序的阅读性和可靠性,使程序的构造层次一目了然。
应用系统的程序由包含多个模块的主程序和各种子程序组成。各程序模块都要完成一个明确的任务,实现某个具体的功能,如:加计数、暂停、清零,显示等,在具体需要时调用相应的模块即可。
功能描述:用4位LED数码显示"秒表",显示时间为00~9分59.9秒,每秒自动加1;一个"开场"键,一个"复位"键,一个"清零"键。
3.2程序流程图
开场
系统初始化
数码管显示
按键判断
定时启动位取反
按键2
关闭定时器时间清零
按键1
N
Y
Y
N
定时中断
开场
T0初始化
程序处理〔分、秒、毫秒自动增加〕
退出中断
四、Proteus软件仿真
4.1软件功能简介
Proteus ISIS是英国Labcenter公司开发的电路分析与实物仿真软件。它运行于Windows操作系统上,可以仿真、分析(SPICE)各种模拟器件和集成电路。
该软件的特点是:
〔1〕全部满足我们提出的单片机软件仿真系统的标准,并在同类产品中具有明显的优势。
〔2〕具有模拟电路仿真、数字电路仿真、单片机及其外围电路组成的系统的仿真、RS-232动态仿真、I2 C调试器、SPI调试器、键盘和LCD系统仿真的功能;有各种虚拟仪器,如示波器、逻辑分析仪、信号发生器等。
〔3〕目前支持的单片机类型有:ARM7系列、68000系列、8051系列、AVR系列、PIC12系列、PIC16系列、PIC18系列、Z80系列、HC11系列以及各种外围芯片。
〔4〕支持大量的存储器和外围芯片。
总之,该软件是一款集单片机和SPICE分析于一身的仿真软件,功能极其强大 ,可仿真ARM、51、AVR、PIC。
Proteus启动画面:
4.2 Proteus运行流程
Proteus ISIS的工作界面是一种标准的Windows界面,如下图。
包括:标题栏、主菜单、标准工具栏、绘图工具栏、状态栏、对象选择按钮、预览对象方位控制按钮、仿真进程控制按钮、预览窗口、对象选择器窗口、图形编辑窗口。
运行Proteus程序后,进入软件的主界面。通过左侧工具栏中的P(从库中选择元件命令)命令,在Pick Devices 左侧窗口中选择所需元件的关键字,然后放置元件并调整方向和位置以及参数设置,最后进展连线。
运行图如下:
初始状态
中间状态
最终状态
经过protues仿真,实现了题目的要求,并且增加了扩展局部单片机与电脑通信授时的任务。并且经过测试硬件运行稳定,秒表计时时间准确。完成了设计题目的全部内容。
五、课程设计体会
课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术开展的日新日异,单片机已经成为当今计算机应用中空前活泼的领域,在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握单片机的开发技术是十分重要的。
回忆起此次单片机课程设计,仍感慨颇多,确实,从选题到定稿,从理论到实践,在接近四星期的日子里,可以说得是苦多于甜,但是可以学到很多很多的的东西,同时不仅可以稳固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我们懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会效劳,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的缺乏之处,对以前所学过的知识理解得不够深刻,掌握得不够结实,比方说不懂一些元器件的使用方法,对单片机汇编语言掌握得不好……通过这次课程设计之后,一定把以前所学过的知识重新温故。
在做课程设计的日子里得到了教师的悉心指导和同学的帮助,在此向他们致以诚挚的谢意。感谢提供相关技术帮助的教师和同学,你们的支持和鼓励使我们对这次的设计完成有了信心和动力,在此深表谢意。
课程小结
通过这两周程设计,我对一些专业知识和电子设计有了更深的
了解,同时也尝试着去应用自己的所掌握的知识。本次电子课程设计主要是对已学习的模拟电子技术、数字电子技术和单片机的综合应用,同时加上电路等知识,设计完成了利用软件模拟的秒表。经过几天的奋战,我感受很深.
我们一小组四个人一块儿讨论设计了此次试验,在设计过程中深感自己在培养动手能力这方面还需很大的努力。同时,通过这次我们积极的通过网络,书籍等资源,在同学的帮助下,把这个课程设计作为一次锻炼,为以后生活学习中培养善于动手,乐于动手的习惯。 单片机课程设计不仅给我们提供了一个良好的应用自己所掌握的知识的平台,又是检验自己所学知识的一次考核。 我们运用各自在各方面的优势中和起来,形成了一个团队.通过团队力量,才使设计得以完成.可以说,我们三个人是一个不可或缺的整体,少了任何一个人都是无法完成任务的。在设计的过程中我们也不可防止的遇到了很多的问题。尤其是在调试过程中,会因为某些原因出不来结果,或三个人之间出现了意见分歧,但在最后都达成一致。通过这次的课程设计,我们也发现了不少自己不会的知识,通过查询各方面资料,我们也进步了很多,有学会了很多上课时没掌握的东西, 最后在调试结果出来后,我们更是无比的兴奋,无比的自豪。总之,通过这次电子课程设计,我不仅对自己的知识有了更好的掌握和应用,更了解到团队精神的力量.在以后的学习和生活中受用终身。
参考文献
[1] 余发山主编.单片机原理及应用技术.XX:中国矿业大学.2003.76-94,152-157
[2] 杨凌霄编著.微型计算机原理及应用.XX:中国矿业大学,2004.36-52
附1 源程序代码
#include<STC12C5A.h>
#include<intrins.h>
#define duan P0//段选
#define wei1 P1//计时器位选,只接前四口
#define wei2 P2//年月日位选
#define uchar unsigned char
#define uint unsigned int
sbit start=P3^2;//开场按钮
sbit reset=P3^3;//暂停复位按钮
sbit DSIO=P3^4;//ds1302 DSIO接口
sbit RET=P3^5;//ds1302 RET接口
sbit SCLK=P3^6;//ds1302 SCLK接口
sbit date=P3^7;//日期时间转换按钮
void DigDisplay();
void delays(unsigned ms);
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();
void UsartConfiguration();
unsigned char code duanxuan[21] = {
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12,
0x02,0x78,0x00,0x10,0xbf};//段选{0,1,3,4,5,6,7,8,9,0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,-}
//---DS1302写入和读取时分秒的地址命令---//
unsigned char code weixuan[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0, 0x30, 0x16, 0x21, 0x12, 0x01, 0x15};
unsigned char second[4]={0};
unsigned char clock[8]={0};
unsigned char i=0;
void main()
{
unsigned char c;
char flag=1;
bit temp=1;
//unsigned char receiveData[15]={0};
Ds1302Init();
UsartConfiguration();
TMOD=0x21;
TL0=0xF0;
TH0=0xD8;
EA=1;
ET0=1;
while(1)
{
if(temp==1)
{
Ds1302ReadTime();
clock[0] = TIME[2]/16; //时
clock[1] = TIME[2]&0x0f;
clock[2] = 20;
clock[3] = TIME[1]/16; //分
clock[4] = TIME[1]&0x0f;
clock[5] = 20;
clock[6] = TIME[0]/16; //秒
clock[7] = TIME[0]&0x0f;
}
else if(temp==0)
{
Ds1302ReadTime();
clock[0] = 2; //年
clock[1] = 0;
clock[2] = TIME[6]/16;
clock[3] = (TIME[6]&0x0f)+10;
clock[4] = TIME[4]/16;
clock[5] = (TIME[4]&0x0f)+10;
clock[6] = TIME[3]/16;
clock[7] = (TIME[3]&0x0f)+10;
}
DigDisplay();
if(date==0)
{
delays(1);
if(date==0) {temp=~temp; while(!date) DigDisplay();}
}
DigDisplay();
if(start==0)
{
delays(1);
if(start==0) {TR0=1; flag=1; while(!start) DigDisplay();}
}
DigDisplay();
if(flag==0)
{
if(reset==0)
{
delays(1);
if(reset==0)
{
i=0;
second[0]=0;
second[1]=0;
second[2]=0;
second[3]=0;
TL0=0xF0;
TH0=0xD8;
while(!reset) DigDisplay();
}
}
}
else if(flag==1)
{
if(reset==0)
{
delays(1);
if(reset==0) {TR0=0; flag=0; while(!reset) DigDisplay();}
}
}
DigDisplay();
if(RI == 1)//查看是否接收到数据
{
for(c=0;c<15;c++)
{
//receiveData[i] = SBUF; //读取数据
//RI = 0;
}//去除标志位
//second[1]=receiveData[5];
/*TIME[1]=(receiveData[11]-0x30)*0x10+(receiveData[12]-0x30);
TIME[2]=(receiveData[9]-0x30)*0x10+(receiveData[10]-0x30);
TIME[3]=(receiveData[6]-0x30)*0x10+(receiveData[7]-0x30);
TIME[4]=(receiveData[4]-0x30)*0x10+(receiveData[5]-0x30);
TIME[6]=(receiveData[2]-0x30)*0x10+(receiveData[3]-0x30); */
//Ds1302Init();
}
//DigDisplay();
}
}
void DigDisplay()
{
unsigned char k;
unsigned int j;
for(k=0;k<4;k++)
{
P1M0=0xff;
wei1 = weixuan[k]; //发送位选
duan = duanxuan[second[k]]; //发送段码
j = 2000; //扫描间隔时间设定
while(j--);
duan = 0xff;//消隐
P1M0=0x00;
}
for(k=0;k<8;k++)
{
P2M0=0xff;
wei2 = weixuan[k]; //发送位选
duan = duanxuan[clock[k]]; //发送段码
j = 2000; //扫描间隔时间设定
while(j--);
duan = 0xff;//消隐
P2M0=0x00;
}
}
void delays(unsigned ms)
{ int j,k;
for(j=0;j<ms;j++)
{
for(k=0;k<100;k++);
}
}
void T0_INT()interrupt 1
{
TL0=0xF0;
TH0=0xD8;
i++;
if(i==500)
{
i=0;
second[0]=second[0]+1;
}
if(second[0]==10)
{
second[1]=second[1]+1;
second[0]=0;
}
if(second[1]==6)
{
second[2]=second[2]+1;
second[1]=0;
}
if(second[2]==10)
{
second[3]=second[3]+1;
second[2]=0;
}
}
void Ds1302Write(uchar addr, uchar dat)
{
uchar n;
RET = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RET = 1; //然后将RET(CE)置高电平。
_nop_();
for (n=0; n<8; n++)//开场传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开场传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++)//写入8位数据
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RET = 0;//传送数据完毕
_nop_();
}
/*******************************************************************************
* 函 数 名 : Ds1302Read
* 函数功能 : 读取一个地址的数据
* 输 入 : addr
* 输 出 : dat
*******************************************************************************/
uchar Ds1302Read(uchar addr)
{
uchar n,dat,dat1;
RET = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RET = 1;//然后将RET(CE)置高电平。
_nop_();
for(n=0; n<8; n++)//开场传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开场传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n<8; n++)//读取8位数据
{
dat1 = DSIO;//从最低位开场接收
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RET = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/*******************************************************************************
* 函 数 名 : Ds1302Init
* 函数功能 : 初始化DS1302.
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8E,0X00); //制止写保护,就是关闭写保护功能
for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80); //翻开写保护功能
}
/*******************************************************************************
* 函 数 名 : Ds1302ReadTime
* 函数功能 : 读取时钟信息
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日--月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
void UsartConfiguration()
{
SCON=0X50; //设置为工作方式1
PCON=0X80; //波特率加倍
TH1=0XFA; //计数器初始值设置,注意波特率是9600的
TL1=0XF3;
TR1=1; //翻开计数器
}
附2 系统原理图
小组成员:杨晓博 尹序鑫 罗恩勇 陈晓峰
小组各成员:讨论并确定秒表要实现哪些功能
各成员分工:
罗恩勇 陈晓峰:硬件电路的设计仿真,查阅资料
尹序鑫 杨晓博:编写程序,焊接电路,设计原理图,填写大报告
. .word.zl.
展开阅读全文