简易数字时钟Word文档格式.docx
《简易数字时钟Word文档格式.docx》由会员分享,可在线阅读,更多相关《简易数字时钟Word文档格式.docx(25页珍藏版)》请在冰豆网上搜索。
利用分分离门电路和集成块电路设计简易数字时钟;
主要可分为五个功能模块:
毫秒脉冲发生器、计数器、译码显示电路、时序控制电路,存储电路。
555振荡器可作为脉冲发生电路,计数器和控制电路是系统的主要部分,计数器是用可加(减)的计数方法,分别采用60进制,31进制,30进制,29进制,28进制,24进制,10进制,7进制计数的方式,可选用74LS192,计时器完成计时功能;
控制电路具有直接控制计数器的启动计数、暂停/连续计数、查询所计数、译码显示电路显示,存储等功能。
设计框图如二所示;
方案二:
利用STC89C51单片机设计简易数字时钟。
单片机软件编程灵活、自由度大,可用软件编程实现各种控制算法和逻辑控制。
单片机系统可分别在时钟模式,日历模式,闹钟模式,秒表模式下用数码管显示相应的值,能用按键实现复位,调整等。
本方案选用了STC89C51芯片(内部含有4KB的flash及高低各128位的RAM),不需要外扩展存储器,可使系统整体结构更为简单。
设计框图如图三所示;
1.3.2方案论证
方案一是用逻辑门搭建的,基本也能满足电路设计要求,但要做好是有很大的难度的,线非常之多,元件分散、多,容易把线接错,而且浪费;
所以考虑采用了方案二以STC89C51芯片为中心控制系统,实现显示、键盘控制、响铃等功能,大大提高了系统的智能化,也使得系统所测结果精度大大提高。
二硬件设计
2.1控制芯片的介绍
STC89C51单片机的外型如图四所示。
单片机可分为通用型和专用型,种类繁多。
这里我们主要介绍STC89C51是一种低功耗、高性能、超抗干扰的单片机,指令代码完全兼容传统的8051单片机。
12时钟/机器周期和6时钟/机器周期可以任意选择,能处理8位数据的通用型单片机,具有CMOS工艺、芯片内集成了通用8位中央处理器,片内含4k可反复擦写的Flash只读程序存储器(ROM),支持ISP(In-systemprogrammable)功能。
STC89C51内部有256RAM(高128和低128),8个中断源,4个中断优先级,3个16位可编程定时计数器,2个全双工串行通信口,看门狗(WDT)电路,片内时钟振荡器。
兼容标准MCS-51指令系统及80C51引脚结构。
STC89C51有40个引脚,32个外部双向输入/输出(I/O)口。
该芯片还具有PDIP40、TQFP44和PLCC44三种封装形式,以适应不同产品的需求。
外型
图四
和封装形式如图四所示。
从外观上看单片机就是一块集成电路,它与在模拟电路和数字电路中学习过的集成电路电路最主要的区别是:
普通集成电路电路的引脚功能基本上固定的,而单片机的一些引脚的功能是可以通过编程进行控制,一些引脚既可作输入又可作输出。
由于STC89C51不仅支持程序的并行写入,而且支持ISP在线可编程的串行写入,利用下载线将计算机将原程序编译后进行串行写入到STC89C51,速度快、稳定性好,同时不需要VPP烧写高压,只要4~5V供电即可完成写入。
单片机广泛用于工业控制、智能仪器仪表、计算机设备及网络、通信领域、家用电器、医用设备、军用设备等各个方面。
对于单片机这样的集成电路,要设计让它完成一个特定的工作任务,除完成设计相关的硬件电路外,还要设计相应的控制软件,才能使整个电路按照设计要求自动地进行工作。
所以,电子电路学习到单片机这个知识层次时,除要学习相关硬件知识,还学习相关软件设计知识,才能对单片机进行控制和应用。
单片机的开发和应用,是利用硬件和软件的结合来实现的。
由于单片机的功能强大,充分理解各引脚功能,灵活编写控制程序去控制引脚功能,完成各种需要的设计。
2.2单片机最小系统
2.2.1振荡电路
STC89C51是内部具有振荡电路的单片机,只需在18脚和19脚之间接上石英晶体给单片机加上工作所需直流电源,振荡器就开始振荡起来。
振荡电路就为单片机工作提供了所需要的时钟脉冲信号,使单片机的内部电路,单片机的内部程序(若有)开始工作起来。
振荡电路不工作,整个单片机电路都不能正常工作。
STC89C51常外接6MHz、11.0592MHz、12MHz的石英晶体,本电路接入的是12MHz的石英晶体。
18脚和19脚分别对地接了一个30PF的电容,目的是防止单片机自激。
如果从18脚输入外部时钟脉冲,则19脚接地。
2.2.2复位电路
复位电路就是在RST端(9脚)外接的一个电路,目的是当单片机上电开始工作时,内部电路从初始状态开始工作,或者在工作中要想人为的让单片机重新从初始状态开始工作。
在时钟工作的情况下,只要STC89C51的复位引脚高电平保持两个机器周期以上的时间,STC89C51便能完成系统重置的各项动作,使得内部特殊功能寄存器之内容均被设成已知状态,并且从地址0000H处开始读入程序代码而执行程序。
该电路具有上电自动复位和手动复位功能,当上电时,根据电容两端电压不能突变,使RST有一个高电位,电路实现复位,在很短一段
图六单片机双复位电路
时间后电容充满,RST通过电阻接地恢复低电位,单片机内部程序正常工作,同时在开关按下时,RST直接与5V电压相连可实现高电平复位,而正常情况下通过电阻连接GND,单片机内部程序可正常工作。
具体电路如图六所示,由C3和R0构成上电自动复位电路,S实现手动开关复位。
2.3显示电路设计
实验电路设计了一组数码管显示电路,电路如图七所示。
八只数码管动态驱动显示。
通过插接口P0接数码管七段显示段码端,通过插接口P2接每位数码管的位选端。
单片机在输出七段显示码到P0的同时,提供哪一位数码显示的控制信号也输到P2上,通过延时1—2毫秒,在使下一个数码管点亮,一次类推,可利用余光效应,给人以八位数码管同时点亮的视觉效果。
实现数码管的显示。
同时需要注意的是STC89C51端口输出电流很小,不足以驱动八位数码管和蜂鸣器,所以需要通过三极管扩流,以下电路采用的是NPN型三极管S9012进行扩流,是共阳数码管点亮。
采用三极管扩流时P2应反相)
图七数码管显示电路
2.4控制电路设计
控制电路主要由6个独立的按键组成,我们可以用按键来控制计时的开始、暂停、清零和查询。
所有按键的一端接地,另一端与单片机的P2口的几个引脚相连。
具体电路如下图八所示。
图九
图八按键
2.5元件清单
元件名
数量
STC89C51
1
八段4位共阳数码管
2
NPN三极管(9012)
9
1K电阻
17
无极性电容(22PF)
电解电容22uf
排针
有源蜂鸣器
10K排阻
轻触按键
5
三位拨码开关
晶振12MHZ
三.软件设计
3.1程序设计思路
在硬件的基础上,可以通过软件完成时钟的设计。
我用7个独立按键作为控制键。
其中P10,P11(11,10,01,00)用于切换电路分别在时钟,万年历,闹钟,秒表模式下显示,P12用于控制秒表开始暂停,P13至P16分别用于调节时钟,闹钟时分秒及万年历年月日星期,在秒表计时模块,长按P14,通过P15可以进行最多60组记录时间的重复调数,P16为秒表清零键。
其中时钟在四钟工作状态下都能正常计时,闹钟在秒表模式下不工作,是设计更加符合要求。
3.2C语言程序代码
#include<
reg51.h>
absacc.h>
#defineucharunsignedchar
#defineuintunsignedint
/*七段共阳管显示定义*/
ucharcodedispcode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x40,0x79,
0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xbf,0xff};
//此表为LED的字模,共阳数码管不带小数点0-9,带小数点0-9,_和灭灯
ucharxhaomiao[61]={0};
//此数组用于秒表中记录60次的时间。
ucharxmmiao[61]={0};
ucharxfenzhong[61]={0};
ucharLED0,LED1,LED2,LED3,LED4,LED5,LED6,LED7;
//各个数码管从左至右编号
/*定义并初始化变量*/
ucharseconde=0;
//秒
ucharminite=30;
//分
ucharhour=9;
//时
ucharweek=7;
//星期
ucharday=25;
//日
ucharmonth=3;
//月
uintyear=12;
//年
ucharhaomiao=0;
//秒表毫秒
ucharmmiao=0;
//秒表秒
ucharfenzhong=0;
//秒表分钟
ucharmstcnt=0;
//定时器计数,定时10ms,mstcnt满100,秒加1
ucharstopwatch=0;
//定时器好秒表计数,定时10ms,满1,毫秒加1
ucharshi=0;
//闹铃功能时
ucharfen=0;
//闹铃功能分
ucharmiao=0;
//闹铃功能秒
ucharbjcs;
//报警次数
uchary=1;
//定义一个y,使得当时,分,秒,都为0时,日只自加一次
ucharz=1;
//定义一个z,使得当整点时只报时一次
ucharx=0;
//定义一个x,用于显示秒表时间中调用组数
ucharf=0;
//定义一个f,用于显示秒表时间中循环调用组数
ucharP13=0;
ucharP14=0;
ucharP15=0;
ucharP16=0;
sbitP1_0=P1^0;
//P1_3为1,P1_5为1时,显示时间,P1_3为0,P1_5为1时,显示闹钟
sbitP1_1=P1^1;
//P1_3为1,P1_5为0时,显示日历,P1_3为0,P1_5为0时,显示秒表
sbitP1_2=P1^2;
//秒表开始暂停
sbitP1_3=P1^3;
//时钟秒,闹钟秒调整定义
sbitP1_4=P1^4;
//时钟分,闹钟分调整定义
sbitP1_5=P1^5;
//时钟时,闹钟时,日历年调整定义
sbitP1_6=P1^6;
//星期调整定义
sbitP1_7=P1^7;
//接蜂鸣器,0响,1不响/*函数声明*/
voiddelay(uintk);
//延时子程序
voidtime_pro();
//时间处理子程序
voiddisplay();
//时间显示调整子程序
voiddingshi();
//闹钟显示调整子程序
voidnaozhong();
//时间到,闹铃
voidzhengdian();
//整点报时
voidday_pro();
//日历处理子程序
voidcalendar();
//日历显示调整子程序
voidmiaobiao();
//秒表显示子程序
voidxianshi();
//显示总程序
/*延时子程序*/
voiddelay(uintk)//延时程序,此处大约为0.8ms
{
ucharj;
while(k--)
{for(j=0;
j<
100;
j++)
{;
}
}}
voidxianshi(void)//显示总程序
{
P0=0Xff;
//消影
P2=0Xfe;
P0=dispcode[LED0];
//LED0
delay
(1);
P2=0Xfd;
P0=dispcode[LED1];
//LED1
P2=0Xfb;
P0=dispcode[LED2];
//LED2
P2=0Xf7;
P0=dispcode[LED3];
//LED3
P2=0Xef;
P0=dispcode[LED4];
//LED4
P2=0Xdf;
P0=dispcode[LED5];
//LED5
P2=0Xbf;
P0=dispcode[LED6];
//LED6
P2=0X7f;
P0=dispcode[LED7];
//LED7
P0=0Xff;
}
/*时间处理子程序*/
voidtime_pro(void)
if(seconde==60)
{z=0;
seconde=0;
minite++;
if(minite==60)
minite=0;
hour++;
if(hour==24)
{y=0;
hour=0;
}}}}
/*时间显示调整子程序*/
voiddisplay(void)
if((P1_0==1)&
&
(P1_1==1))
/*时间调整键盘扫描子程序*/
if(P1_3!
=P13)//秒位的调整
delay(10);
if(P1_3==0)
seconde++;
if(seconde==60)
}}
P13=P1_3;
if(P1_4!
=P14)//分位的调整
if(P1_4==0)
P14=P1_4;
if(P1_5!
=P15)//时位的调整
if(P1_5==0)
P15=P1_5;
/*时间显示子程序*/
LED0=hour/10;
//时十位
LED1=hour%10;
//时个位
LED2=20;
//间隔符-
LED3=minite/10;
//分十位
LED4=minite%10;
//分个位
LED5=20;
LED6=seconde/10;
//秒十位
LED7=seconde%10;
//秒个位
/*定时闹钟*/
voiddingshi(void)
if((P1_0==0)&
(P1_1==1))
/*闹钟调整键盘扫描子程序*/
=P15)//设定时
shi++;
if(shi==24)
shi=0;
=P14)//设定分
fen++;
if(fen==60)
fen=0;
if(P1_3!
=P13)//设定秒
miao++;
if(miao==60)
miao=0;
}
/*闹钟显示子程序*/
LED0=shi/10;
//时十位
LED1=shi%10;
//时个位
//间隔符-
LED3=fen/10;
//分十位
LED4=fen%10;
//分个位
LED6=miao/10;
//秒十位
LED7=miao%10;
//秒个位
/*整点报警*/
voidzhengdian(void)
if((seconde==0)&
(minite==0)&
(seconde==0)&
(z==0))//整点报时
if((P1_0==1)||(P1_1==1))
{
P1_7=0;
delay(100);
P1_7=1;
z=1;
}}}
/*响闹钟程序*/
voidnaozhong(void)//时间到,响铃
if((hour==shi)&
(minite==fen)&
(seconde==miao))
for(bjcs=0;
bjcs<
5;
bjcs++)
{P1_7=0;
delay(300);
delay(600);
/*日历处理子程序*/
voidday_pro(void)
if((hour==0)&
(y==0))
day++;
week++;
if(week==8)
week=1;
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12))
if(day==32)
day=1;
month++;
if((month==4)||(month==6)||(month==9)||(month==11))
if(day==31)
if(month==2)
if((year%4)==0)
{if(day==30)
}}
else
if(day==29)
day=1;
month++;
}}}
if(month==13)
month=1;
year++;
if(year==100)
year=0;
y=1;
/*日历显示调整模块*/
voidcalendar(void)
if((P1_0==1)&
(P1_1==0))
/*日历调整键盘扫描子程序*///日期调整,p1_0日,p1_月,p1_4年p1_6调整星期
=P13)//日的调整
if(P1_3==0)
{
if(day<
31)
else
{day=1;
}
if((month==4)||(month==6)||(month==9)||(month==11))
if(day<
30)
if(month==2)
29)
28)
day++;
if(P1_6!
=P16)//星期调整
{delay(10);
if(P1_6==0)
{week++;
P16=P1_6;
=P14)//月的调整
month=1;
if(P1_5!
=P15)//年的调整
year++;
if(year==100)
year=0;
/*日历显示模块*/
LED0=year/10;
//年十位
LED1=(year%10)+10;
//年个位
LED2=month/10;
//月十位
LED3=(month%10)+10;
//月个位
LED4=day/10;
//日十位
LED5=day%10;
//日个位
LED6=20;
//-
LED7=week;
/*秒表显示计时模块*/
voidmiaobiao(void)
if((P1_0==0)&
/*秒表计时模块*/
if(haomiao==99)
haomiao=0;
mmiao++;
if(mmiao==60)
mmiao=0;
fenzhong++;
if(fenzhong==60)
fenzhong=0