简易数字钟的设计与制作陈勇强.docx
《简易数字钟的设计与制作陈勇强.docx》由会员分享,可在线阅读,更多相关《简易数字钟的设计与制作陈勇强.docx(25页珍藏版)》请在冰豆网上搜索。
简易数字钟的设计与制作陈勇强
心之所向,所向披靡
明达职业技术学院
毕业设计(论文)
2009-2010学年度
信息工程系系 电子信息工程技术专业
班级07电信
(1)学号43073117
课题名称简易数字钟的设计与制作
学生姓名 陈勇强
指导教师 陈慕铭
2009年12月25日
前言
随着电子技术的迅猛发展和超大集成电路设计和制造工艺的进一步提高,单片机也有了迅速的发展,各种新颖的单片机产品层出不穷,令人目不暇接。
当前单片机技术已渗透到国防尖端、工业、农业、日常生活的各个领域,成为当今世界现代化不可缺少的工具和强有力的武器。
单片机技术是当代理工科大学生必会的技能之一。
单片机的学习和掌握是当前迫切的任务和要求,为此进行了本次设计,本次设计旨在提高对单片机的内部硬件电路的理解和软件编程能力的提高,真正体验一下产品的研发和制造的各部分流程,在一定程度上加强了对工程设计的理解和实际操作。
简易数字钟是对单片机的一次综合的应用,对单片机中至关重要的中断概念的理解有着十分重要的意义,简易数字钟不仅需要时间的准确跟需要有廉价的电路组成即将部分硬件用软件编程的方法加以代替,降低成本以提高市场的竞争力,这是对单片机设计的最高要求。
本次设计就是针对以上问题的一种解决策略,希望通过后面的设计对读者有所启发和鼓励,单片机其实很简单,天下无难事,勇者必胜之。
简易数字钟的设计与制作
作者:
陈勇强
【摘要】:
数字钟已经广泛应用于车站、广场、家庭等场所,本次设计中的简易数子钟是采用单片机的定时功能并结合单片机的强大的控制功能;利用先进的计算机仿真软件对采用单片机做的数字钟进行先期的模拟测试以达到加快设计周期,节约成本的目的;在仿真通过及参数确定以后进行实际的制作完成设计,单片机采用AT89C51经74LS373的驱动,通过六个数码管进行显示,时间通过键盘可以任意调整,时间误差小于200ms,性能比较稳定。
【关键词】数字钟单片机计算机仿真数码管
第一章方案论证
一设计要求:
(1)该数字钟应具有基本时钟功能;
(2)24小时制;(3)时间可以任意调整;(4)时间用数码管显示。
二方案的论证与选择:
方案一
本方案采用数子电路来实现功能,应用多谐振荡器产生固定频率为1HZ的方波信号作为计数器的计数脉冲,并经过译码驱动电路驱动数码管,达到时间显示。
本方案的特点是电路结构复杂,时间精度较低,且成本较高。
硬件电路系统框图如图1所示。
图1方案一系统框图
方案二
本方案采用单片机控制系统用来定时1S信号,经数码驱动电路驱动数码管,显示当前时间,并可以通过键盘调整时间。
本方案的优点是时间精确,成本低,但断电时间会丢失,编程复杂。
硬件电路系统框图如图2所示。
图2方案二系统框图
方案比较与选择
方案一与方案二相比电路复杂,无需编程,但成本较高,时间精度不及后者,不利于推广和普及。
方案二时间精度较高,可以节约元器件,成本低。
本着提高动手能力,加强对单片机的内部原理的进一步的理解,降低成本,提高编程能力;决定采用方案二,由于程序较为复杂,故采用国际较为通用的C语言编程。
第二章硬件电路设计
一硬件电路总体框图:
硬件电路由电源电路、单片机最小应用系统、复位电路、振荡电路、显示电路、时间调整电流组成。
硬件电路系统框图如图2所示。
二单元电路设计:
1单片机最小应用系统的设计
单片机最小应用系统是单片机能正常工作的最小应用系统,其由单片机、复位电路、振荡电路三个模块组成,如图3所示。
图3单片机最小应用系统
1.1单片机
本次设计所使用的单片机是ATMEL公司的AT89C51单片机,这种单片机功能比较强大,价格低,性价比较高。
1.2复位电路
在给单片机通电时,其内部电路处于不确定的工作状态。
为了使单片机工作时内部电路有一个确定的工作状态,单片机在工作之前要有一个复位过程。
单片机复位电路工作原理:
当通电瞬间稳压电源给电容充电。
RST为复位输入端,当RST引脚持续两个机器周期以上的高电平时,使单片机完成复位操作。
随着电容充电结束,将使电容与电阻之间将呈现低电平,单片机复位结束。
复位操作的主要功能是把PC初始化为0000H,使单片机程序存储器从0000H单元开始执行程序。
此外,复位操作使P0-P3这些引脚变为高电平,还会对内部的一些单元产生影响.
1.3振荡电路
单片机是一种时序电路,必须有脉冲信号才能工作,在它的内部有一个时钟产生电路,有两种振荡方式,一种是内部振荡方式,只要接上两个电容和一个晶振即可;另一种是外部振荡方式,采用外部振荡方式时,需在XTAL2上加外部时钟信号。
本文论文选择的方案中采用的是内部振荡方式,外接晶振为12MHZ,震荡周期=1/12us时钟周期=1/6us机器周期=1us指令周期=1-4us。
2显示及驱动电路
显示电路的主要作用是对时间进行显示,显示器件可以是LCD液晶显示器、数码管等;本次设计采用七段数码管作为显示的器件,数码管具有亮度高,功耗低,寿命长,夜间显示无需背光,价格低等优点。
数码管根据驱动方式的不同可以分为共阴极数码管和共阳极数码管,其驱动的方式这里不再做叙述;数码管的驱动电流为3—10mA,本次设计所采用的单片机的最大输出电流为2.5mA,最大输入电流为1.6mA。
故单片机无法驱动数码管的显示需加驱动电路加以驱动。
驱动电路的主要作用是对数码管进行驱动,本次设计采用集成块74LS373来对数码管进行驱动,74LS373的使用方法和工作原理这里不再叙述;74LS373的输出电流大于3mA,足以驱动数码管。
数码管在工作时的最大电压为1.7V,而单片机的输出电压为5V,直接将数码管接在单片机上将烧坏数码管,因此需加限流电阻,根据理论计算和以往使用数码管的经验,本次设计采用100Ω的电阻。
本次设计中采用六个共阳的数码管。
电路如图4所示。
图4显示及驱动电路
3时间调整电路
时间调整电路的主要作用是完成时间的调整,本次设计用键盘进行相应的操作。
按照键盘按键的结构形式,可分为独立式键盘和矩阵式键盘。
本次设计主要采用独立式键盘。
独立式键盘就是各个按键是相互独立的,分别接一根输入线,各条输入线上的按键工作状态不会影响其他输入线的工作状态。
因此,通过检测输入线的电平状态,可以判断哪个按键被按下。
独立式按键电路配置灵活,软件设计简单。
缺点是每个按键需要一根输入口线,在按键数量较多时,占用大量的输入口资源,电路结构显得很繁杂,只适用于按键较少或操作速度较高的场合。
键盘一般采用弹性按键,按键在按下和弹起的过程中存在着抖动,消抖的方法有两种,一种是采用硬件消抖电路,另一种是采用软件延时消抖。
本次设计采用软件消抖。
本次设计中采用独立式键盘因为P3口中已经有上拉电阻故不再加上拉电阻如图5所示。
图5时间调整电路
三总体电路的工作原理
总体电路的工作原理中涉及到硬件电路的工作原理和软件程序的工作原理,软件程序的工作原理将在下一章中作详细的说明,在此对硬件电路的工作原理作详细的说明。
本电路的核心元件是单片机,单片机负责产生相应的时间信号由不同的端口进行输出,数码管的驱动需要段码信号和位选信号,段码信号由单片机的P1口经限流电阻传输至各个数码管的段码输入端,位选信号由单片机的P2口经74LS373处理传送至各个数码管的位选端,本次设计中数码管的显示方式采用动态扫描显示。
单片机P1口先输出段码信号,紧接着P2口输出位选信号,相应的数码管被点亮;依次循环输出段码和位选信号点亮相应的数码管,利用人眼的滞留效应就可以看到六个数码管同时显示,配以LED的闪烁装饰,一个精美的数字钟展现在眼前。
总电路图见附录A。
第三章程序设计
程序设计即单片机的软件部分的设计,是单片机能正常工作的指令的集合;程序也被称为单片机的灵魂。
本次设计中采用C语言编程,程序中包括主函数、延时模块、定时模块、时间调整模块、时间计算模块、显示模块、键盘识别模块。
一程序流程图:
程序流程图如图6所示
N
Y
YN
图6程序流程图
二各部分程序的设计:
1主函数
主函数的作用是完成程序中相关变量的初始化,其中包括定时器的初始化以及外部中断的初始化。
程序如下:
voidmain()//主函数
{
TMOD=0x02;
TH0=6;
TL0=6;
ET0=1;
EA=1;
EX0=1;
IT0=0;
PX0=1;
TR0=1;
js();
while
(1)
{
if(nuk!
=0)
{
tz();
}
if(nuk==0)
{
display();
}
}
}
2延时模块
延时模块的主要作用是对程序中的显示部分进行相应的时间延迟,程序如下:
voiddelay(ucharm)//延时模块
{ucharn;
for(;m>0;m--)
for(n=0;n<80;n++)
{;}
}
3定时程序模块
定时程序是利用单片机的定时器T0产生1S,定时的方式采用方式2,方式2可以在定时时间到达后自动重新装入初值,这样的方式可以减小误差。
程序中TH0和TL0的均为
6,即中断一次为250us,产生一秒需中断4000次。
程序如下:
voidT0_time()interrupt1//定时器0中断
{
num++;
if(num/4000)
{
ss=~ss;
js();
num=0;
}
}
4时间调整模块
时间调整程序模块的主要作用是完成对时间的外部手动调整,主要功能有时间调整位的选择,时间的加减。
程序如下:
intkz(intd)//手动时间调整
{
jia=1;
jian=1;
if(jia==0)
{
delay(10);
if(jia==0)
{
while(!
jia);
d++;
}
}
if(jian==0)
{
delay(10);
if(jian==0)
{
while(!
jian);
d--;
}
}
return(d);
}
voidtz()//时间调整位选择
{
TR0=0;
switch(nuk)
{case1:
P2=0x20;P1=table[h1];h1=kz(h1);if(h1<0)h1=2;if(h1>2)h1=0;break;
case2:
P2=0x10;P1=table[h2];h2=kz(h2);if(h2<0){if(h1==2)h2=3;elseh2=9;}if(h1==2){if(h2>3)h2=0;}if(h1!
=2){if(h2>9)h2=0;}numh=h1*10+h2;break;
case3:
P2=0x08;P1=table[m1];m1=kz(m1);if(m1<0)m1=5;if(m1>5)m1=0;break;
case4:
P2=0x04;P1=table[m2];m2=kz(m2);if(m2<0)m2=9;if(m2>9)m2=0;numm=m1*10+m2;break;
case5:
P2=0x02;P1=table[s1];s1=kz(s1);if(s1<0)s1=5;if(s1>5)s1=0;break;
case6:
P2=0x01;P1=table[s2];s2=kz(s2);if(s2<0)s2=9;if(s2>9)s2=0;nums=s1*10+s2;break;
}
}
voidint0()interrupt0//外部中断0
{
delay(10);
if(aa==0)
{
while(!
aa);
nuk++;
}
if(nuk==7)
{
nuk=0;
TR0=1;
}
}
5时间计算模块
时间计算模块的主要功能是对定时时间到达后相应的时、分、秒进行计算;必要时可以加入时间补偿程序以提高时间的精确性。
程序如下:
js()//时间计算模块
{
nums++;
if(nums==60)
{
nums=0;
numm++;
}
if(numm==60)
{
numm=0;
numh++;
}
if(numh==24)
{
numh=0;
}
h1=numh/10;
h2=numh%10;
m1=numm/10;
m2=numm%10;
s1=nums/10;
s2=nums%10;
}
6显示模块
显示模块的主要功能是驱动数码管显示出相应的时间,因为本次设计中采用动态显示所以程序中P1口负责输出段码,紧接着P2口输出位选信号,相应的数码管被点亮,依次循环,人眼就能看见一排亮着的数码管,为防止各个数码管之间出现互相干扰的情况,程序中特意加入了消影指令;因为采用的是共阳极的数码管,所以在数码管的公共端加高电平,数码管的段码端加低电平,数码管才能显示。
程序如下:
voiddisplay()//显示模块
{
P1=table[h1];//段码输出
P2=0x20;//位选输出
delay(YS);//延时
P2=0x00;//消影
P1=table[h2];
P2=0x10;
delay(YS);
P2=0x00;
P1=table[m1];
P2=0x08;
delay(YS);
P2=0x00;
P1=table[m2];
P2=0x04;
delay(YS);
P2=0x00;
P1=table[s1];
P2=0x02;
delay(YS);
P2=0x00;
P1=table[s2];
P2=0x01;
delay(YS);
P2=0x00;
}
7键盘识别模块
键盘识别模块的作用是完成时间调整的输入,键盘识别的一般步骤是判断是否有键按下,有无抖动,有键按下是哪个键被按下及键码的值。
程序如下:
voidint0()interrupt0//键盘识别
{
delay(10);//软件消抖
if(aa==0)
{
while(!
aa);
nuk++;
}
if(nuk==7)
{
nuk=0;
TR0=1;
}
}
三总程序:
见附录B
第四章电路的组装与调试
硬件电路组装完成以后,将在仿真软件中调试过的程序用仿真器在硬件电路上进行仿真,当外部电源接通,仿真器启动后电路的基本功能都可以实现,但发现数码管在黑暗中有小的抖动现象产生;根据动态显示的原理初步判断是延时时间存在问题,在多次改变延时间后,现象未得到有效地处理。
据此改变调试的方法,由改延时时间变为改变消影的方法,由原来的消除段码的消影方法换成消除位选的方法;经调试后数码管闪烁消除。
将程序烧录到单片机后,将单片机安装到电路板上,通电测试时数码管出现乱码和时亮时不亮的情况,且复位电路无法正常复位,根据以往的经验怀疑是单片机的时钟电路没有工作机外围的振荡电路没有正常工作,遂对外围的振荡电路进行检查,检查发现是晶振的引脚接触不良,重新安装以后问题解决。
电路可以完成正常的工作。
用Keil软件编译产生HEX文件,将HEX文件烧录到单片机中,用单片机取代仿真器,电路工作一切正常。
心得体会
我通过本次的设计深深体会到电子产品的设计确实不容易,借助单片机强大的控制和定时能力,我的硬件设计略显简单,但就是这样简单的硬件电路里面也包含着很多的知识。
需要把三年来学的知识加以融合消化才能设计出电路来。
在软件编程方面,我采用的是C语言,C语言是我掌握的第一个计算机编程语言,在此能得到应用我感到非常高兴;在高兴之余我对我的设计上的欠缺感到一些遗憾,我的数字钟不具有断电时间保护的功能,由于我的知识方面的欠缺导致设计上存在相应的缺陷,我在今后的人生中一定会学习更多的知识来进一步完善我的设计。
致谢
毕业设计,也许是我大学生涯交上的最后一个作业了。
想借此机会感谢三年以来给我帮助的所有老师、同学,你们的友谊是我人生的财富,是我生命中不可或缺的一部分。
感谢实验时期指导我的所有老师,他们给了我太多的帮助,在此非常谢谢你们,非常感谢我的指导老师陈慕铭老师在毕业设计中不厌其烦的给我讲解有关知识,并且精心指导我一些重要问题。
在此,特向他道声谢谢。
在此也感谢我的搭档给了我很大的帮助,让我们顺利完成毕业设计。
也感谢信息工程系所有老师这些年来对我的教育!
参考文献
【参考文献】:
【1】《单片机C语言入门》主编:
郭天祥电子工业出版社2005.1出版
【2】《单片机原理与运用》主编:
董少明中国铁道出版社2007.11出版:
【3】《8051单片机实践与应用》主编:
吴金戌沈庆阳清华大学出版社2002.8出版
【4】《模拟电路》主编:
杨毅德重庆大学出版社2004.3年出版
附录A:
附录B:
#include
#defineuintunsignedint
#defineucharunsignedchar
#defineYS1
sbitss=P3^4;
sbitaa=P3^2;
sbitjia=P3^3;
sbitjian=P3^5;
ucharcodetable[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
inth1,h2,m1,m2,s1,s2,numh=15,numm=59,nums=0,nuk;
intnum,b;
voiddelay(ucharm)//延时模块
{ucharn;
for(;m>0;m--)
for(n=0;n<80;n++)
{;}
}
intkz(intd)//手动时间调整
{
jia=1;
jian=1;
if(jia==0)
{
delay(10);
if(jia==0)
{
while(!
jia);
d++;
}
}
if(jian==0)
{
delay(10);
if(jian==0)
{
while(!
jian);
d--;
}
}
return(d);
}
voidtz()//时间调整位选择
{
TR0=0;
switch(nuk)
{
case1:
P2=0x20;P1=table[h1];h1=kz(h1);if(h1<0)h1=2;if(h1>2)h1=0;break;
case2:
P2=0x10;P1=table[h2];h2=kz(h2);if(h2<0){if(h1==2)h2=3;elseh2=9;}if(h1==2){if(h2>3)h2=0;}if(h1!
=2){if(h2>9)h2=0;}numh=h1*10+h2;break;
case3:
P2=0x08;P1=table[m1];m1=kz(m1);if(m1<0)m1=5;if(m1>5)m1=0;break;
case4:
P2=0x04;P1=table[m2];m2=kz(m2);if(m2<0)m2=9;if(m2>9)m2=0;numm=m1*10+m2;break;
case5:
P2=0x02;P1=table[s1];s1=kz(s1);if(s1<0)s1=5;if(s1>5)s1=0;break;
case6:
P2=0x01;P1=table[s2];s2=kz(s2);if(s2<0)s2=9;if(s2>9)s2=0;nums=s1*10+s2;break;
}
}
voiddisplay()//显示模块
{
P1=table[h1];//段码输出
P2=0x20;//位选输出
delay(YS);//延时
P2=0x00;//消影
P1=table[h2];
P2=0x10;
delay(YS);
P2=0x00;
P1=table[m1];
P2=0x08;
delay(YS);
P2=0x00;
P1=table[m2];
P2=0x04;
delay(YS);
P2=0x00;
P1=table[s1];
P2=0x02;
delay(YS);
P2=0x00;
P1=table[s2];
P2=0x01;
delay(YS);
P2=0x00;
}
js()//时间计算模块
{
nums++;
if(nums==60)
{
nums=0;
numm++;
}
if(numm==60)
{
numm=0;
numh++;
}
if(numh==24)
{
numh=0;
}
h1=numh/10;
h2=numh%10;
m1=numm/10;
m2=numm%10;
s1=nums/10;
s2=nums%10;
}
voidmain()//主函数
{
TMOD=0x02;
TH0=6;
TL0=6;
ET0=1;
EA=1;
EX0=1;
IT0=0;
PX0=1;
TR0=1;
js();
while
(1)
{
if(nuk!
=0)
{
tz();
}
if(nuk==0)
{
display();}
}}
voidT0_time()interrupt1//定时器0中断
{
num++;
if(num/4000)
{
ss=~ss;
js();
num=0;
}
}
voidint0()interrupt0//键盘识别
{
delay(10);
if(aa==0)
{
while(!
aa);
nuk++;
}
if(nuk==7)
{
nuk=0;
TR0=1;}
}