基于51单片机的时钟秒表.docx
《基于51单片机的时钟秒表.docx》由会员分享,可在线阅读,更多相关《基于51单片机的时钟秒表.docx(17页珍藏版)》请在冰豆网上搜索。
![基于51单片机的时钟秒表.docx](https://file1.bdocx.com/fileroot1/2022-12/30/c5349c42-ed47-4879-ace8-7d2d48b78747/c5349c42-ed47-4879-ace8-7d2d48b787471.gif)
基于51单片机的时钟秒表
摘要
本设计的数字秒表系统采用STC89C52单片机为中心器件,利用其定时器/计数器原理,结合LED数码管以及按键电路来设计计时器。
将软、硬件有机地结合起来,使得系统能够实现四位LED显示,显示时间为00.00~99.99秒,计时精度为0.01秒,能正确地进行计时。
同时,我在此基础上,又设计了时钟秒表定时器,可以显示年、月、日、星期、时间进制、时、分、秒、、以及闹钟启/停状态,可以实现时间的调整,时钟/秒表功能的转换,闹钟的启/停。
其中软件系统采用C语言编写程序,包括显示程序,定时中断服务,延时程序等,并在keil中调试运行,硬件系统利用PROTEUS强大的功能来实现,简单切易于观察,在仿真中就可以观察到实际的工作状态,利用单片机开发板可下载程序,实现硬件实现。
关键词:
秒表,时钟,定时/计数器
1设计目的及要求
1.1设计目的
本设计主要是应用Proteus软件和嵌入式C语言编程工具,结合单片机原理及应用、微机原理与接口技术等专业课程,强化和巩固专业理论基础,掌握Proteus仿真的技巧和嵌入式C语言编程工具,提高单片机开发能力,并为嵌入式开发打下基础。
1.2设计要求
试用定时器/计数器设计一个简单的秒表,能显示计时状态和结果。
要求进行电路仿真实验,并使用C语言进行程序的开发。
2设计方案选择
2.1芯片简介
本设计选择采用STC89C52单片机为核心。
STC89C52是一个低电压、高性能CMOS8位单片机带有64K字节的可反复擦写的程序存储器。
和128字节的存取数据存储器RAM,这种器件采用ATMEL公司的高密度、不容易丢失存储技术生产,并且能够与MCS-52系列的单片机兼容。
片内含有8位中央处理器和闪烁存储单位,有较强的功能的STC89C52单片机能够被应用到控制领域中。
STC89C52提供以下的功能标准:
4K字节闪烁存储器,128字节随机存取数据存储器,32个I/O口,2个16位定时/计数器,1个5向量两级中断结构,1个串行通信口,片内振荡器和时钟电路。
另外,STC89C52还可以进行0HZ的静态逻辑操作,并支持两种软件的节电模式。
闲散方式停止中央处理器的工作,能够允许随机存取数据存储器、定时/计数器、串行通信口及中断系统继续工作。
2.2总体设计思路
本设计使用89C52芯片作为控制芯片,复位电路和时钟电路构成单片机最小系统。
利用P1口8个引脚接上拉电阻,然后连接四位共阴极数码管段选段即P0.0—P0.7分别连接共阴极数码管的A—DP脚,P1.0—P1.3分别反相器74HC04再与数码管的位选端1—4脚连接,实现秒表的显示。
利用P3.2和P3.3分别连接了2个按键,分别用来控制秒表复位、开始/暂停。
单片机控制原理图如下:
图2.2单片机控制原理图
2.3单元电路设计
本设计主要分为时钟电路模块,复位电路模块,显示模块和控制模块。
设计方案如下:
2.3.1时钟模块
图2.3时钟电路
如上图所示,89C52单片机的时钟信号通常用内部振荡方法得到,在引脚XTAL1和XTAL2外接晶体振荡器(简称晶振)或陶瓷谐振器,就构成了内部振荡方法。
由于单片机内部有一个高增益反相放大器,当外接晶振后,就构成了自激振荡器并产生振荡时钟脉冲。
晶振通常选择6MHz、12MHz、24MHz。
本设计采用12MHz晶振。
图中电容C1、C2起到稳固振荡频率、快速起振的作用。
电容值一般为5—30pF。
本设计选用22pF电容。
2.3.2复位电路模块
图2.4复位电路
复位操作完成电路的初始化,使单片机从一种确定的状态开始运行。
由上图可知,控制模块实际上就是单片机的最小系统。
本设计采用常用的上电且开关复位电路。
上电后,由于电容的充电,使RST持续一段高电平时间。
当单片机已在运行中时,按下复位键也能使RST持续一段时间的高电平,从而实现上电且开关复位的操作。
此处,C3电容取20uF,R1=1K。
2.3.3控制模块
控制部分电路连接如下图所示:
图2.5控制电路
单片机检测按键的原理是:
单片机的I/O口既可作为输出也可作为输入使用,当检测按键时,用的是它的输入功能,我们把按键的一端接地,另一端与单片机的某个I/O口相连,开始时先给该I/O口赋一高电平,然后让单片机不断的检测该I/O口是否变为低电平,当按键闭合时,即相当于该I/O口通过按键与地相连,变成低电平,程序一旦检测到I/O口变为低电平则说明按键被放下,然后执行相应的指令。
本设计如图2.5所示,1个独立按键K2接到P3口的P3.2端,K2键即既可以当作开始键又可以当作暂停键,同时也可当复位键。
同时借助于复位电路中按键K1也可以实现秒表的复位,当需要秒表重新计时,利用K1键复位,当程序出现错误时,可以随时使电路复位。
2.3.4显示模块
显示部分电路设计如下图:
图2.6显示模块电路图
显示电路我们采用的是数码管显示电路。
用4个共阴极LED显示,LED是七段式显示器,内部有7个条形发光二极管和1个小圆点发光二极管组成,根据各管的亮暗组合成字符。
在用数码管显示时,我们有静态和动态两种选择,静态显示程序简单,显示稳定,但是占用端口比较多;动态显示所使用的端口比较少,可以节省单片机的I/O口。
在设计中,我们采用LED动态显示,用P0口驱动显示。
由于P0口的输出级是开漏电路,用它驱动时需要外接上拉电阻才能输出高电平。
P1.O—P1.3提供位选择。
共阴极数码管用非门74HC04反相驱动。
3软件设计
(1)实现计时。
利用单片机内部T0计时器实现计时,首先给定时器工作方式寄存器TMOD赋值0x01选定T0定时器工作在方式1。
接着确定定时初值TH0=(65536—10000)/256;TL0=(65536—10000)%256实现10ms的定时,利用中断一次实现0.01秒定时。
(2)实现时间显示。
利用单片机P1端口控制数码管的位选,利用P0端口控制数码管的段选,只要两个数码管位选段选间隔的时间适当,就可以实现动态显示时间。
(3)实现按键控制。
利用单片机P3复用端口输入按键控制命令,可以将与P3.2端口相连的按键定义为启动/暂停按键,复位按键。
3.1整体程序设计思路
此次设计中,定时/计数器选择定时/计数器T0,工作于工作方式1,即16位定时/计数器。
利用定时器定时中断,每定时10ms即产生一次中断。
每发生一次中断即定时0.01s,没发生100次中断即定时1s。
P3.2口为秒表启动/暂停控制按键,在键值处理子程序中,每检测到一次低电平,按键K1计数值加一,当此值为奇数时,秒表启动,当此值为偶数时,秒表暂停。
P3.3口为秒表复位控制按键,每检测到一次低电平,秒表停止计时,显示恢复为00.00。
另外,独立按键在闭合时存在抖动现象,所以编写键盘检测程序时,需在检测按下时加入去抖延时,检测松手时就不用了。
3.2程序流图
主程序:
中断子程序:
按键检测子程序:
3.3主要程序代码
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitk1=P3^2;//定义开始/暂停按键
//sbitk2=P3^3;//定义秒表复位按键
uintcount;
ucharcodetable[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
ucharcodetable1[]={
0xbf,0x86,0xdb,0xcf,
0xe6,0xed,0xfd,0x87,
0xff,0xef};
uintsecond;
uintmillisecond;
voiddelay(uintz)//延时0.5ms
{
uintx,y;
for(x=z;x>0;x--)
for(y=60;y>0;y--);
}
voidkeyscan()
{
if(k1==0)
{
delay(20);
if(k1==0)
{
count++;
while(!
k1);
}
}
switch(count)
{
case1:
TR0=1;break;
case2:
TR0=0;break;
case3:
TR0=0;second=0;millisecond=0;count=0;break;
}
}
voiddisply()
{
P0=table[millisecond%10];
//P0=0xff;
P1=0x08;
delay
(1);
P0=table[millisecond/10];
//P0=0xff;
P1=0x04;
delay
(1);
P0=table1[second%10];
//P0=0xff;
P1=0x02;
delay
(1);
P0=table[second/10];
//P0=0xff;
P1=0x01;
delay
(1);
}
voidmain()
{
count=0;
second=0;
millisecond=0;
disply();
TMOD=0x01;//TO工作在定时器方式1
TH0=(65536-10000)/256;//预置计数初值,定时10ms
TL0=(65536-10000)%256;
EA=1;//CPU开中断
ET0=1;//T0开中断
TR0=0;//T0停
P1=P2=P3=0xFF;
while
(1)
{
keyscan();
disply();
}
}
voidtimer0()interrupt1
{
TH0=(65536-10000)/256;//计数初值重装载
TL0=(65536-10000)%256;
millisecond++;
if(millisecond==100)
{
millisecond=0;
second++;
}
if(second==60)
{
second=0;
}
}
4仿真调试
总体仿真电路图如下图所示:
图4.1整体仿真原理图
4.1keil简介
KeilC51是美国KeilSoftware公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(uVision)将这些部分组合在一起。
运行Keil软件需要WIN98、NT、WIN2000、WINXP等操作系统。
如果你使用C语言编程,那么Keil几乎就是你的不二之选,即使不使用C语言而仅用汇编语言编程,其方便易用的集成环境、强大的软件仿真调试工具也会令你事半功倍。
KeilC51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。
在开发大型软件时更能体现高级语言的优势。
4.2keil与protues联调
联调设置步骤如下:
(1)把C:
\ProgramFiles\LabcenterElectronics\Proteus6Professional\MODELS\目录下的VDM51.dll文件复制到C:
\Keil\C51\BIN文件夹下。
(目录名都是默认的,你可以根据你实际安装的目录进行复制。
)可能会没有这个VDM51.dll楼主需要网上下一个,再放到BIN里面。
(2)用记事本(其它的编辑软件也可以,如UltraEdit)打开Keil根目录下的TOOLS.INI文件,在[C51]栏目下加入TDRV8=BIN\VDM51.DLL("ProteusVSMMonitor-51Driver")。
(3)打开Proteus,画出相应电路,在Proteus的“Debug”菜单中选中“UseRemoteDebugMonitor(远程监控)”。
(4)进入Keil的Project菜单OptionforTarget‘工程名’。
在Debug选项中右栏上部的下拉菜单选中ProteusDriver。
再进入Settings,机子IP设为127.0.0.1,端口号为8000。
(5)在Keil中进行debug,同时在Proteus中查看直观的结果。
这样就可以像使用仿真器一样调试程序了。
4.3仿真实现
双击图标进入KeiluVision2编程环境,输入程序。
返回桌面双击图标,进入PROTEUS仿真环境,点击左上角选项P后根据设计的电路图调出所需元件画好硬件原理图如图4.1所示。
然后按照4.1节所写步骤,设置keil和proteus的工作环境,实现keil和proteus的连调。
设置完成后,程序开始执行即可看到数码管显示初始值00.00。
按下K1一次,秒表开始计时,再按下K1,秒表暂停,依次循环操作。
按下K2键秒表又恢复至00.00,停止计时,再按下K1键才能重新开始计时。
5硬件实现
5.1程序下载步骤
1.连接硬件:
将串口下载线一头与计算机串口相连,另一头与学习板串口相连,注意此时不要给学习板上电。
2.运行STC下载软件——STC_ISP_V3.5,出现如下界面:
图5.1STC_ISP_V3.5运行界面
第一步:
选择单片机型号STC89C52。
第二步:
打开要下载的HEX文件。
第三步:
选择串口和波特率。
波特率请选用默认值。
第四步:
点击下载按钮。
由此完成程序的下载。
5.1硬件调试
给目标板上电复位,即可按键数码管显示00.00,按下K1一次,秒表开始计时,再按下K1,秒表暂停,依次循环操作。
按下K2键秒表又从00.00开始计时。
由此可见,该设计完成了设计要求。
如下图为硬件实现照片展示:
图5.2硬件调试
6拓展
在基于定时/计数器设计的秒表的基础上,设计一个基于定时/计数器的时钟秒表计时器,可以显示年、月、日、星期、时间进制、时、分、秒、、以及闹钟启/停状态,可以实现时间的调整,时钟/秒表功能的转换,闹钟的启/停。
采用定时器T0,实现时钟定时器,定时器T1实现秒表定时器。
用LCD1602液晶显示器显示年、月、日、星期、时间进制、时、分、秒、、以及闹钟启/停状态。
使用弹性小按键,可以实现时间的调整,时钟/秒表功能的转换,闹钟的启/停。
6.1设计原理
原理图如下图所示:
图6.1时钟秒表原理图
6.2主要程序清单
voiddelay(uintz)
voiddi(uintx)//蜂鸣器发声函数
voidwrite_com(ucharcom)//给写液晶命令
voidwrite_date(uchardate)//给液晶写数据
voidinit()//初始化函数
voidwrite_nian(ucharadd,uintdate)//年显示函数
voidwrite_yue(ucharadd,uchardate)//月显示函数
voidwrite_ri(ucharadd,uchardate)//日显示函数
voidwrite_sfm(ucharadd,uchardate)//时分秒显示函数
voidwrite_week(ucharweek)//星期显示函数
voidwrite_jinzhi(ucharjinzhi)//时间进制显示函数
voidwrite_nao(ucharnao)//闹钟开关(ON/OFF)显示函数
voidkeyboard()//按键扫描函数
voidmbiao()//秒表函数
voidmain()//主函数
voidtimer0()interrupt1//时钟定时器
voidtimer1()interrupt3//秒表定时器
6.3仿真实现
设置完成后,程序开始执行即可看到液晶显示器显示初始时间,如图6.2所示;当时钟走至整点时(如图6.3所示),进行整点报时,如图6.4所示;当按动K1键,进行调时控制,并由K2,K3键进行加、减调时控制,可以任意调整时间,如图6.5所示;当按动K4键,可以实现时钟/秒表功能转换,并可以实现秒表的启/停控制,如图6.6所示。
由此可见,本设计完成了基本的时钟秒表定时器设计要求。
图6.2初始时间
图6.3时钟模式(整点)图6.4整点报时
图6.5调时图6.6秒表模式
7心得体会
经过几天不懈的努力,此次能力拓展训练终于拉下帷幕,回想这几天的经历,受益颇多。
这次设计,我所做的题目为秒表的设计,虽然在大一就学习了C语言,但是很少将它应用于实践中,再加之,在单片机课程中老师以汇编语言授课,所以在一开始时,由于对C语言的使用不是很熟练,我感到极大地困惑,无从下手。
但是,通过查阅书籍及上网搜集资料,我渐渐地拾起了以前的C语言知识。
同时,这次设计,让我对C51单片机的结构有了更清楚的了解,尤其是对定时/计数器以及中断的使用更加的熟练。
通过这次课程设计,我明白了独立思考重要性,因为从头到尾,都是自己一个人完成。
从原理的最终敲定,到程序的编写,到仿真的实现,至最后的程序下载调试,这都是我一个人独立完成结果。
期间,在我调试程序时,曾遇到了问题,任凭我用尽各种办法也查不出问题所在,但是,我并没有放弃,休息了一会,继续静下来思考,最终发现了问题的所在。
最后,要感谢学校给我这次学习的机会,感谢老师的指导,要感谢我的同学的帮助与鼓励。
我想这次能力拓展训练,必将是我学习道路上的一次宝贵经历。
参考文献
[1]李群芳,张士军,黄建.单片微型计算机与接口技术.北京:
电子工业出版社,2010
[2]郭天祥.51单片机C语言编程.北京:
电子工业出版社,2009
[3]张迎新.单片微型计算机原理、应用及接口技术.北京:
国防工业出版社,1999
[4]谭浩强.C程序设计.北京:
清华大学出版社,1991
[5]王守中.51单片机发入门与经典实例.北京:
人民邮电出版社