单片机89c51的电子时钟课程设计
#include <reg52.h>
#include<stddef.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_FLAG
#define LCD1602_PORT P0
sbit lcd1602_rs=P2^0
sbit lcd1602_e=P2^2
sbit lcd1602_rw=P2^1
sbit lcd1602_busy=P0^7
sbit key_ch=P3^5
sbit key_add=P3^6
sbit key_minus=P3^7
uchar i,sec,min,h,date,month,flag
uint year
uchar *chgstr[7]={" ","sec","min","hour","date","min","year"}
uchar j,k,m,n,o,p
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71}
uchar timestr[10],datestr[10]
void init()
void delay(uint)
void time_display()
void date_display()
void control()
void time()
void lcd1602_CheckBusy()
{
do
{
lcd1602_busy=1
lcd1602_rs=0
lcd1602_rw=1
lcd1602_e=0
lcd1602_e=1
}
while(lcd1602_busy)
}
void lcd1602_WriteCmd(const uchar cmd)
{
lcd1602_CheckBusy()
lcd1602_rs=0
lcd1602_rw=0
lcd1602_e=1
LCD1602_PORT=cmd
lcd1602_e=0
}
void lcd1602_WriteData(const uchar c)
{
lcd1602_CheckBusy()
lcd1602_rs=1
lcd1602_rw=0
lcd1602_e=1
LCD1602_PORT=c
lcd1602_e=0
}
void lcd1602_Init()
{
lcd1602_WriteCmd(0x38)//显示模式为8位2行5*7点阵
lcd1602_WriteCmd(0x0c)//display enable,flag enable,flash enable,
lcd1602_WriteCmd(0x06)//flag move to right,screen don't move
lcd1602_WriteCmd(0x01)//clear screen
}
void lcd1602_Display(const uchar *ptr,uchar line,uchar xaddr)
{
uchar data i=0
uchar *data q
q=ptr
switch(line)
{
case 0:
lcd1602_WriteCmd(0x80+xaddr)
while(q!=NULL &&(*q!='\0') &&i<16)
{
lcd1602_WriteData(*q)
q++
i++
}
break
case 1:
lcd1602_WriteCmd(0xc0+xaddr)
while(q!=NULL &&(*q!='\0') &&i<16)
{
lcd1602_WriteData(*q)
q++
i++
}
break
}
}
void main()
{
lcd1602_Init()
init()
while(1)
{
time_display()
date_display()
control()
}
}
void init()
{
i=0
sec=0
min=30
h=7
date=17
month=10
year=2017
flag=0
EA=1
ET0=1
TMOD=0x01
TH0=(65536-50000)/256
TL0=(65536-50000)%256
TR0=1
}
void delay(uint z)
{
uint x,y
for(x=zx>0x--)
for(y=110y>0y--)
}
void time_display()
{
timestr[7]=0x30+sec%10
timestr[6]=0x30+sec/10
timestr[5]=':'
timestr[4]=0x30+min%10
timestr[3]=0x30+min/10
timestr[2]=':'
timestr[1]=0x30+h%10
timestr[0]=0x30+h/10
timestr[8]=0
lcd1602_Display(timestr,1,3)
}
void date_display()
{
datestr[9]=0x30+date%10
datestr[8]=0x30+date/10
datestr[7]=':'
datestr[6]=0x30+month%10
datestr[5]=0x30+month/10
datestr[4]=':'
datestr[3]=0x30+year%10
datestr[2]=0x30+year/10%10
datestr[1]=0x30+year/100%10
datestr[0]=0x30+year/1000
lcd1602_Display(datestr,0,2)
}
void control()
{
if(!key_ch)
{
delay(5)
if(!key_ch)
{
flag++
TR0=0
if(flag==7)
{flag=0TR0=1lcd1602_Init()}
lcd1602_Display(chgstr[flag],1,12)
}
}
while(!key_ch)
if(flag==1&&key_add==0)
{
while(!key_add)
sec++
if(sec==60)
sec=0
}
if(flag==1&&key_minus==0)
{
while(!key_minus)
sec--
if(sec==-1)
sec=59
}
if(flag==2&&key_add==0)
{
while(!key_add)
min++
if(min==60)
min=0
}
if(flag==2&&key_minus==0)
{
while(!key_minus)
min--
if(min==-1)
min=59
}
if(flag==3&&key_add==0)
{
while(!key_add)
h++
if(h==24)
h=0
}
if(flag==3&&key_minus==0)
{
while(!key_minus)
h--
if(h==-1)
h=23
}
if(flag==4&&key_add==0)
{
while(!key_add)
date++
if(date==29)
if((year%4!=0)&&(month==2))
date=1
if(date==30)
if((year%4==0)&&(month==2))
date=1
if(date==31)
if((month==4)||(month==6)||(month==9)||(month==11))
date=1
if(date==32)
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12))
date=1
}
if(flag==4&&key_minus==0)
{
while(!key_minus)
if(date>1)date--
}
if(flag==5&&key_add==0)
{
while(!key_add)
month++
if(month==13)
month=1
}
if(flag==5&&key_minus==0)
{
while(!key_minus)
month--
if(month==0)
month=12
}
if(flag==6&&key_add==0)
{
while(!key_add)
year++
if(year==99)
year=1
}
if(flag==6&&key_minus==0)
{
while(!key_minus)
year--
if(year==0)
year=99
}
}
void T0_rpt() interrupt 1
{
TH0=(65536-50000)/256
TL0=(65536-50000)%256
i++
time()
}
void time()
{
if(i==20)
{
i=0
sec++
if(sec==60)
{
sec=0
min++
if(min==60)
{
min=0
h++
if(h==24)
{
h=0
min=0
sec=0
date++
if(date==29)
if((year%4!=0)&&(month==2))
{
date=1
month++
if(month==13)
{
month=1
year++
}
}
if(date==30)
if((year%4==0)&&(month==2))
{
date=1
month++
if(month==13)
{
month=1
year++
}
}
if(date==31)
if((month==4)||(month==6)||(month==9)||(month==11))
{
date=1
month++
if(month==13)
{
month=1
year++
}
}
if(date==32)
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12))
{
date=1
month++
if(month==13)
{
month=1
year++
}
}
}
}
}
}
}
我可以给你一个模拟的,但是原理差不多,就是要用个单片机吗,自己要多动脑筋,肯定可以做出来的
下面是具体的设计:
数字时钟的设计与制作
摘要:本系统是采用555构成的多协振荡器、74LS90芯片组合做成的数子时钟系统。其中用555构成的多协振荡器产生震荡频率,再用74LS 90芯片组合成分频电路对震荡频率进行分频,然后对选用74LS92和74LS90分别作为时计数器和分、秒计数器,再加一个校时电路。能让该数子时钟准确计时,以数字形式显示时、分、秒的时间,小时的计时为“24翻1”分,秒的计时为60进位 ,和时间校正功能。
关键字: 震荡器分频计数器74LS90校时
一、数字时钟的总体设计
1 数字时钟的原理方框图如图1所示:
图1数字时钟的原理方框图
该电路系统由秒信号发生器、“时”、“分”、“秒”计数器、译码器及显示器等组成。秒信号产生器是整个系统是时基信号,它直接决定计数系统的精度。将标准秒信号送入“秒计数器”,“秒计数器”采用六十进制计数器,每累积60秒发出一个分脉冲信号,该信号将作为“分计数器”的时钟脉冲,“分计数器”也采用60进制计数器,每累积60分钟,发出一个“时脉冲”信号,该信号将被送入“时计数器”。“时计数器”采用24进制计数器,可实现对一天24小时的计数。译码显示电路将“时”、“分”、“秒”计数器的输出状态经7段译码显示器译码,通过7段显示器显示出来。
二、模块的设计与比较
1. 振荡电路及分频电路
方案一:
(1)采用石英晶体振荡器
石英晶体振荡器的特点是振荡频率准确,电路结构简单,频率易高调整。它还具有压电效应,在晶体某一方向加一电场,则在与此垂直的方向产生机械振动和电场互为因果,这种循环过程一直持续到晶体的机械强度限制时,才达到最后的稳定,这种压电谐振的频率就是晶体振荡的固有频率。
图2 石音晶体振荡电路
图2所示电路通过CMOS非门构成的输出为方波的数字式晶体振荡电路,这个电路中,CMOS非门U1与晶体、电容和电阻构成晶体振荡器电路,U2实现整形功能,将振荡器输出的近似于正弦波的波形转换为较理想的方波。输出反馈电阻R1为非门提供偏置,使电路工作于放大区域,即非门的功能近似于一
个高增益的反相放大器。电容C1、C2与晶体构成一个谐振型网络,完成对振荡频率的控制功能,同时提供了一个180度相移,从而和非门构成一个正反馈网络,实现了振荡器的功能。由于晶体具有较高的频率稳定性及准确性,从而保证了输出频率的稳定和准确。晶体X1的频率选为32768HZ。该元件专为数字钟电路而设计,其频率较低,有利于减少分频器级数。C1、C2均选择为30pF。当要求频率准确度和稳定度更高时,还可接入校正电容并采取温度补偿措施。由于CMOS电路的输入阻抗极高,因此反馈电阻R1可选为10MΩ。较高的反馈电阻有利于提高振荡频率的稳定性。
(2) 用CD4060计数作分频器
数字钟的晶体振荡器输出频率较高,为了得到1Hz的秒信号输入,需要对振荡器的输出信号进行分频。本实验中采用CD4060来构成分频电路。CD4060在数字集成电路中可实现的分频次数最高,而且CD4060还包含振荡电路所需的非门,使用更为方便。CD4060计数为14级2进制计数器,可以将32768HZ的信号分频为2HZ,其次CD4060的时钟输入端两个串接的非门,因此可以直接实现振荡和分频的功能。
方案二:
(1)采用555构成的多偕振荡电路
振荡器电路选用555构成的多偕振荡器,设振荡频率f=1000HZ,其中的电位器可以微调振荡器的输出频率。
图5 多偕振荡电路
(2)用74LS90作分频器
通常实现分频器的电路是计数器电路,一般采用多级10进制计数器来实现。分频器的功能有两个:一是产生标准秒脉冲信号;二是提供功能扩展电路所需的信号。选用中规模集成电路74LS90可以完成以上功能。如图所示,将3片74LS90级联,每片为1/10分频,三片级联正好获得1HZ的标准秒脉冲。
图 6 分频电路
比较: 秒信号发生器是数字电子钟的核心部分,它的精度和稳度决定了数字钟的质量,但是我们做实验考虑到用石音晶体振荡电路时分频电路用的元件较多 且价格较贵,而用555构成的电路元件容易得,电路简单且易于实现,故选方案二
2. 秒、分、时计数器设计
秒脉冲信号经过6级计数器,分别得到“秒”个位,十位、“分”个位、十位、“时”个位,十位的计时,秒分计数器为60进制,小时为24进制。
(1)60进制计数电路:秒计数器电路与分计数器电路都是60进制,它由一级10进制计数器和一级6进制计数器连接构成,如图7、8所示,采用两片中规模集成电路7490串联接起来构成的秒、分计数器。
IC2是十进制计数器,作为十进制的进位信号,7490计数器是十进制异步计数器,用反馈归零方法实现十进制计数。IC1和非门组成六进制计数。7490是在一秒时钟或进位信号的下降沿翻转计数, IC1的QA和QC相与0101的下降沿作为“分”或者“时”计数器的输入信号。IC1的QB和QC高电平1分别送到计数器的清零RO1、RO2,7490内部的RO1 和RO2与非后清零而使计数器归零,完成六进制计数。由此可见串联实现了六进制计数。
图7 秒计数电路
图8 分计数电路
(2)24进制计数电路:小时计数电路是由和组成的24进制计数电路,采用两片中规模集成电路7490串联接起来构成。如图9所示:
当“时”个位IC4计数输入端CKA来到第10个触发信号时,IC4计数器复零,进位端QD向IC3“时”十位计数器输出进位信号,当第24个“时”脉冲到达时,IC4计数器的状态为0100,IC3计数器的状态为0100,此时“时”个位计数器的QC和“时”十位计数器的QB输出为1。把它们分别送到IC4和IC3计数器的清零端RO1 和RO2通过7490内部的RO1 和RO2与非后清零,计数器复位,完成24进制计数。
图9 时计数电路
3. 校时电路
校时电路实现对时分的校准。在电路中设有正常计时和校时位置。分、时的校准开关分别通过触发器控制。通常,校正时间的方法是:首先截断正常的计数通路,然后再进行人工出触发计数或将频率较高的方波信号加到需要校正的计数单元的输入端,校正好后,再转入正常计时状态即可。根据要求,数字钟应具有分校正和时校正功能,因此,应截断分个位和时个位的直接计数通路,并采用正常计时信号与校正信号可以随时切换的电路接入其中。
图8所示为本实验所用的完整的校时电路图。
图10 校时电路
4. 显示器
本系统用七段发光二极管来显示译码器输出的数字,显示器有两种:共阳极或共阴极显示器。74LS48译码器对应的是显示器是共阴显示器。
三、调试要点
我觉得假设在实际的实验箱上组装电子钟时,注意器件管脚的连接一定要准确。“悬空端“、“清0端”、“置1端”要正确处理,调试步骤和方法如下:。
(1)、将频率为1000HZ的信号送入分频器,并用示波器检查各级分频器的输出频率是否符合设计要求。
(3)、将1秒信号分别送入“时”、“分”、“秒”计数器,检查各级计数器的工作情况。
(4)、观察校时电路的功能是否满足校时要求。
(5)、当分频器和计数器调试正常后,观察电子钟是否准确正常地工作。
四、供参考的元器件
(1)、七段显示器(共阴极)6片(2)、74LS909片 (3)、555多谐振荡器 1片(4)、74LS00 8片 (5)、74LS044片
(6)、电阻、电容、导线等。
五、收获体会
该电路的设计让我对数字钟的设计有了一定的了解。我知道了如何设计出1HZ的信号,也对时分秒的设计有了一定的了解。并且在实际电路一般步骤为由数字钟系统组成框图按照信号的流向分级安装,逐级级联,这里的每一级是指组成数字钟的各功能电路。级联时如果出现时序配合不同步,或尖峰脉冲干扰,引起逻辑混乱,可以增加多级逻辑门来延时。经过联调并纠正设计方案中的错误和不足之处后,再测试电路的逻辑功能是否满足设计要求。最后画出满足设计要求的总体逻辑电路图。
参考文献:
1.谢自美,电子线路设计*实验*测试.武汉:华中科技大学出版社,2007
2.康光华,电子技术基础(第五版)。北京:高等教育出版社,2006
3.蒋焕文,孙续。电子测量。北京:计量出版社,1998
4.P.F.格拉夫。电子电路百科全书。张殿等译。北京:科学出版社,1999
5.王兴亮主编现代音响和调音技术。西安电子科技大学出版,2006
我有现成的
LCD1602
显示的,51做的
基本思路是用单片机读取1302里面的信息,处理,然后送LCD1602显示。
有兴趣可以去我博客看,里面还上传了之前我做的实物图片和PCB,可以照着做。
LJMP START
ORG 0003H 外中断0中断程序入口
RETI
ORG 000BH 定时器T0中断程序入口
LJMP INTT0 跳至INTTO执行
ORG 0013H 外中断1中断程序入口
RETI
ORG 001BH 定时器T1中断程序入口
LJMP INTT1
ORG 0023H 串行中断程序入口地址
RETI
---------------主程序----------------------
START:MOV R0,#70H 70给R0,清70-7FH显示内存
MOV R7,#0FH
CLEARDISP:MOV @R0,#00H0给R0中的数为地址的内存中存放(70H)
INC R0
DJNZR7,CLEARDISP
MOV 78H,#2 默认时间为12:00,闹钟5:00
MOV 79H,#1
MOV 74H,#2 防止上电时数码管显示00小时
MOV 75H,#1
MOV 66H,#1 中断退出时66H为1时,分、时计时单元数据移入显存标志
MOV 68H,#1 上电默认闹钟开状态
MOV 7DH,#6 闹钟时十位
MOV 7CH,#3
MOV 69H,#0
MOV 7AH,#0AH放入"熄灭符"数据
MOV TMOD,#11H 设T0、T1为16位定时器
MOV TL0,#0B0H 50MS定时初值(T0计时用)
MOV TH0,#3CH
SETBEA 总中断开放
SETBET0 允许T0中断
SETBTR0 T0定时器开始计时
MOV R4,#14H 1秒定时用初值(50MS×20)
START1:LCALL DISPLAY 显示子程序
LCALL BEEP闹钟查询
JNB P1.7,SETTIMEP1.7口为0时转时间调整程序
JMP START1 P1.7口为1时跳回START1
-----------------------时间闹钟调整系统--------------------------
NFLAG:MOV A,68H 设置闹钟开关状态
CJNE A,#1,BEE68
MOV 68H,#0
JMP E6
BEE68:MOV 68H,#1
E6:MOV 66H,#8 中断退出66H不为1时分、时计时单元数据移入显存标志
MOV 72H,7BH
MOV 73H,7CH
MOV 74H,7DH
MOV 75H,7EH
LCALLDDL
LCALLDDL
MOV 72H,68H
MOV 73H,69H
MOV 74H,7AH
MOV 75H,7AH
LCALLDDL
LCALLDDL
MOV 66H,#1
LJMP START1
SETTIME:LCALLDDL
JB P1.7,NFLAG 键按下时间小于1秒,设置闹钟开关状态并查看闹钟时间,不关走时,确保准确,大于1秒调时
MOV TL1,#0B0H T1闪烁定时初值
MOV TH1,#3CH
MOV R2,#06H进入调时状态,赋闪烁定时初值
MOV 66H,#8 调闹钟时保持走时,关闭时钟显示数据
SETB ET1允许T1中断
SETB TR1开启定时器T1
SET1:LCALLDISPLAY调用显示,防止键按下无显示
JNB P1.7,SET1 P1.7口为0等待键释放
MOV R5,#00H清设置类型闪烁标志
SETN1:INC R5 闹钟分调整
SET5:LCALLDISPLAY
JB P1.7,SET5
SEETN1:LCALLDDL有键按下大于1秒分时间连续加(0.5秒加1),小于1秒转调时状态
JB P1.7,SET6 键释放查询,键释放自动转调时
MOV R0,#7CH
LCALL ADD1
MOV A,R3
CLR C
CJNEA,#60H,HHN1
HHN1:JCSEETN1
LCALL CLR0
JMP SEETN1
SET6:INC R5 闹钟时调整
SEET6:LCALLDISPLAY
JB P1.7,SEET6
SEETNH1:LCALLDDL
JB P1.7,SETF
MOV R0,#7EH
LCALLADD1
MOV A,R3
CLR C
CJNEA,#24H,HOUU1
HOUU1:JC SEETNH1
LCALL CLR0
JMP SEETNH1
SETF:LCALLDISPLAY
JB P1.7,SETF
LCALLDDL
JNB P1.7,SETOUT 短按调时,长按退出
CLR ET0
CLR TR0
MOV 70H,#00H设定后的时间从00秒开始走时
MOV 71H,#00H
INC R5
SET3:LCALLDISPLAY
JB P1.7,SET3
SETMM:LCALLDDL
JB P1.7,SET4
MOV R0,#77H
LCALL ADD1
MOV A,R3
CLR C
CJNEA,#60H,MMH
MMH:JC SETMM
LCALL CLR0
AJMP SETMM
SET4:INC R5
SEET4:LCALLDISPLAY
JB P1.7,SEET4
SETHH:LCALLDDL
JB P1.7,SETOUT1
MOV R0,#79H
LCALLADD1
MOV A,R3
CLR C
CJNEA,#24H,HOUU
HOUU:JC SETHH
LCALL CLR0
AJMP SETHH
SETOUT1:SETB ET0
SETB TR0 计时开始
SETOUT:MOV R5,#00H 清设置类型闪烁标志
CLRTR1 关闭T1
CLRET1 关T1中断
MOV 66H,#1
SETOUT2:LCALLDISPLAY
JNB P1.7,SETOUT2
LJMPSTART1
--------------------------延时1秒钟-----------------------
DDL:MOV 18H,#36
DDL0:MOV 17H,#239
DDL1:LCALLDISPLAY
DJNZ 17H,DDL1
DJNZ 18H,DDL0
RET
----------------------------T0中断程序------------------------
INTT0: PUSH ACC 打包
PUSH PSW
CLR ET0
CLR TR0
MOV A,#0B7H
ADD A,TL0
MOV TL0,A
MOV A,#3CH
ADDC A,TH0
MOV TH0,A
SETB TR0
DJNZ R4, OUTT0 20次中断未到中断退出
ADDSS: MOV R4,#14H 20次中断到(1秒)重赋初值
MOV R0,#71H 指向秒计时单元(70-71H)
ACALL ADD1 调用加1程序(加1秒操作)
MOV A,R3 秒数据放入A(R3为2位十进制数组合)
CLR C 清进位标志
CJNE A,#60H,ADDMM
ADDMM: JC OUTT01小于60秒退出
ACALL CLR0 等于或大于60秒清0
MOV R0,#77H 指向分计时单元(76H-77H)
ACALL ADD1
MOV A,R3
CLR C
CJNE A,#60H,ADDHH
ADDHH: JC OUTT0
ACALL CLR0
MOV R0,#79H 指向小时计时单元(78H-79H)
ACALL ADD1
MOV A,R3
CLR C
CJNE A,#24H,HOUR
HOUR: JCOUTT0
ACALL CLR0
OUTT0: MOV A,66H 查询标志
CJNE A,#1,OUTT01
MOV 72H,76H 中断退出时将分、时计时单元数据移入对应显示单元
MOV 73H,77H
MOV 74H,78H
MOV 75H,79H
OUTT01:POP PSW 出栈
POP ACC
SETB ET0 开放T0
RETI中断返回
---------------------------加1程序--------------------------
ADD1: MOV A,@R0 取当前计时单元数据到A
DEC R0 指向前一地址
SWAP A A中数据高四位与低四位交换
ORL A,@R0 前一地址中数据放入A中低四位
ADD A,#01H A加1操作
DA A 十进制调整
MOV R3,A 移入R3寄存器
ANL A,#0FH 高四位变0
MOV@R0,A 放回前一地址单元
MOV A,R3 取回R3中暂存数据
INCR0 指向当前地址单元
SWAP A A中数据高四位与低四位交换
ANL A,#0FH 高四位变0
MOV @R0,A 数据放入当削地址单元中
RET
CLR0: CLR C
CLR A 清累加器
MOV @R0,A 清当前地址单元
DEC R0 指向前一地址
MOV @R0,A 前一地址单元清0
RET 子程序返回
-------------------------调时闪烁程序----------------------
INTT1: PUSHACC
PUSHPSW
MOV TL1,#0B0H
MOV TH1,#3CH
DJNZR2,INTT1OUT0.3秒未到退出中断(50MS中断6次)
MOV R2,#06H 重装0.3秒定时用初值
CPL 02H0.3秒定时到对闪烁标志取反
JB 02H,FLASH1 02H位为1时显示单元"熄灭"
MOV A,R5
CJNEA,#01H,NL
JMP NNN1
NL:CJNEA,#02H,NL1
LJMPNNN1
NL1:CJNEA,#03H,NL2
LJMPNLL
NL2:CJNEA,#04H,INTT1OUT
LJMPNLL
NLL:MOV 72H,76H
MOV 73H,77H
MOV 74H,78H
MOV 75H,79H
AJMPINTT1OUT
NNN1:MOV 72H,7BH
MOV 73H,7CH
MOV 74H,7DH
MOV 75H,7EH
INTT1OUT:POP PSW 恢复现场
POP ACC
RETI 中断退出
FLASH1:MOV A,R5
CJNEA,#01H,ML
LJMPMNN1
ML:CJNEA,#02H,ML1
LJMPMNN2
ML1:CJNEA,#03H,MN
LJMPMLL
MN:CJNEA,#04H,INTT1OUT
LJMPMHL
MLL:MOV 72H,7AH
MOV 73H,7AH 显示单元(72-73H),将不显示分数据
MOV 74H,78H
MOV 75H,79H
AJMPINTT1OUT
MHL:MOV 72H,76H
MOV 73H,77H
MOV 74H,7AH 显示单元(74-75H),小时数据将不显示
MOV 75H,7AH
AJMPINTT1OUT
MNN1:MOV 72H,7AH
MOV 73H,7AH 显示单元(72-73H),将不显示闹钟分数据
MOV 74H,7DH
MOV 75H,7EH
AJMPINTT1OUT
MNN2:MOV 72H,7BH
MOV 73H,7CH
MOV 74H,7AH
MOV 75H,7AH 显示单元(74-75H),闹钟小时数据将不显示
AJMPINTT1OUT
-------------------------显示-------------------------------
DISPLAY:MOVDPTR,#DISDATA
MOVA,70H
MOVC A,@A+DPTR
MOVP3,A
CLRP1.0
NOP
NOP
NOP
SETB P1.0
MOVA,71H
MOVC A,@A+DPTR
MOVP3,A
CLRP1.1
NOP
NOP
NOP
SETB P1.1
MOVA,72H
MOVC A,@A+DPTR
MOVP3,A
CLRP1.2
NOP
NOP
NOP
SETB P1.2
MOVA,73H
MOVC A,@A+DPTR
MOVP3,A
CLRP1.3
NOP
NOP
NOP
SETB P1.3
MOVA,74H
MOVC A,@A+DPTR
MOVP3,A
CLRP1.4
NOP
NOP
NOP
SETB P1.4
MOVA,75H
MOVC A,@A+DPTR
MOVP3,A
CLRP1.5
NOP
NOP
NOP
SETB P1.5
RET
BEEP:MOV A,68H 查询标志
CJNE A,#1,BEERE
MOV A,78H 查询闹钟时个位
CJNE A,7DH,BEERE
MOV A,79H 查询闹钟时十位
CJNE A,7EH,BEERE
MOV A,76H 查询闹钟分个位
CJNE A,7BH,BEERE
MOV A,77H 查询闹钟分十位
CJNE A,7CH,BEERE
BB:CLR P1.6
LCALL DDL
SETB P1.6
LCALL DDL
JNB P1.7,BEERR
BEERE:RET
BEERR:SETB P1.6
MOV 68H,#0
LCALL DISPLAY
JNB P1.7,BEERR
JMP BEERE
DISDATA:DB 0C0H,0F9H,64H,70H,59H,52H,42H,0F8H,40H,50H,0FFH 0123456789空白
END
简单的时钟,不用1302即可办到。
题目要求的设计已经完成,电路图如下。
程序稍长,放在我的百度空间了。
可以用百度、网页,进行查找:
做而论道 用 LCD1602 显示的时钟
百度一下,即可查到。
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit ds1302_RST =P2^0
sbit ds1302_IO =P2^1
sbit ds1302_SCLK=P2^2
sbit ACC0=ACC^0
sbit ACC7=ACC^7
sbit A1=P3^0
sbit A2=P3^1
sbit A3=P3^2
sbit A4=P3^3
sbit A5=P3^4
sbit A6=P3^5
sbit key1=P3^6
sbit key2=P3^7
uchar now_time[3],wei,d[3]={0,0,0}
uchar code s[]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
}
void delay(uint x)
{
uchar i
for(xx>0x--)
for(i=0i<100i++)
}
void disp()
{
P1=s[now_time[2]/16]
A1=d[2]
delay(5)
A1=1
P1=s[now_time[2]%16]
A2=d[2]
delay(5)
A2=1
P1=s[now_time[1]/16]
A3=d[1]
delay(5)
A3=1
P1=s[now_time[1]%16]
A4=d[1]
delay(5)
A4=1
P1=s[now_time[0]/16]
A5=d[0]
delay(5)
A5=1
P1=s[now_time[0]%16]
A6=d[0]
delay(5)
A6=1
}
uchar read_Byte()
{
uchar i
for(i=8i>0i--)
{
ACC=ACC>>1
ACC7=ds1302_IO
ds1302_SCLK=1
ds1302_SCLK=0
}
return(ACC)
}
void write_Byte(uchar tdata)
{
uchar i
ACC=tdata
for(i=8i>0i--)
{
ds1302_IO=ACC0
ds1302_SCLK=1
ds1302_SCLK=0
ACC=ACC>>1
}
}
void write_data_ds1302(uchar taddr,uchar tdata)
{
ds1302_RST=0
ds1302_SCLK=0
ds1302_RST=1
write_Byte(taddr)
write_Byte(tdata)
ds1302_RST=0
ds1302_SCLK=1
}
uchar read_data_ds1302(uchar taddr)
{
uchar tdata
ds1302_RST=0
ds1302_SCLK=0
ds1302_RST=1
write_Byte(taddr)
tdata=read_Byte()
ds1302_RST=0
ds1302_SCLK=1
return(tdata)
}
void get_ds1302()
{
uchar k
uchar taddr = 0x81
for (k=0k<3k++)
{
now_time[k] = read_data_ds1302(taddr)
taddr+=2
}
}
void init_ds1302()
{
ds1302_RST=0
ds1302_SCLK=0
A1=1
A2=1
A3=1
A4=1
A5=1
A6=1
write_data_ds1302(0x80,0x00)
}
void Time()
main()
{
init_ds1302()
while(1)
{
disp()
get_ds1302()
if(key1==0)
{ delay(10)
if(key1==0)
Time()
}
}
}
void timer() interrupt 3
{
uchar ii++
TH1=(65535-50000)/256
TL2=(65535-50000)%256
if(i==50)
{
d[wei]=1
}
if(i==100)
{ i=0
d[wei]=0
}
}
void Time()
{
uchar temp
uint r=0,p=1
wei=2
TMOD=0x01
EA=1
ET1=1
TH1=(65535-50000)/256
TL2=(65535-50000)%256
TR1=1
for(r=0r<50r++)
disp()
while( key1 )
{
wei=2
disp()
if(key2==0)
{
disp()
if(key2==0)
{
temp=now_time[2]/16*10+now_time[2]%16
temp++
if(temp>=24)
temp=0
now_time[2]=temp/10*16+temp%10
write_data_ds1302(0x84,now_time[2])
}
while(!key2)
}
}
wei=1
d[2]=0
for(r=0r<50r++)
disp()
while(key1 )
{ disp()
if(key2==0)
{
disp()
if(key2==0)
{
temp=now_time[1]/16*10+now_time[1]%16
temp++
if(temp>=60)
temp=0
now_time[1]=temp/10*16+temp%10
write_data_ds1302(0x82,now_time[1])
}
while(!key2)
}
}
wei=0
d[1]=0
for(r=0r<50r++)
disp()
while(key1 )
{
disp()
if(key2==0)
{
now_time[0]=0
write_data_ds1302(0x80,now_time[0])
}
} TR1=0
d[0]=0
for(r=0r<30r++)
disp()
}
#include "REG52.H"
sbit SHUG_01 = P2^0 //数码管1
sbit SHUG_02 = P2^1 //数码管2
sbit SHUG_03 = P2^2 //数码管3
sbit SHUG_04 = P2^3 //数码管4
sbit SHUG_05 = P2^4 //数码管5
sbit SHUG_06 = P2^5 //数码管6
sbitKEY0_01 = P0^0 //按键 启动或停止sbitKEY0_02 = P0^1 //按键 加
sbitKEY0_03 = P0^2 //按键减
sbitKEY0_04 = P0^3 //按键菜单
#define LED_DATAP1 //P1数据端口
unsigned char value_temp = 0unsigned char value_Outk = 0
unsigned char value_shio = 8
unsigned char value_feno = 40
unsigned char value_miao = 0
unsigned char code value_tab0[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}//共阳极unsigned char code value_tab1[]={0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10}//共阳极带点
void Delay_1ms(unsigned int Time)
{
unsigned int x, y
for(x = Timex >0x--)
for(y = 120y >0y--)
}
void Disp_layledketCmd(void)
{
SHUG_01 = 1
LED_DATA = value_tab0[value_shio / 10]
Delay_1ms(5)
SHUG_01 = 0
SHUG_02 = 1
LED_DATA = value_tab1[value_shio % 10]
Delay_1ms(5)
SHUG_02 = 0
SHUG_03 = 1
LED_DATA = value_tab0[value_feno / 10]
Delay_1ms(5)
SHUG_03 = 0
SHUG_04 = 1
LED_DATA = value_tab1[value_feno % 10]
Delay_1ms(5)
SHUG_04 = 0
SHUG_05 = 1
LED_DATA = value_tab0[value_miao / 10]
Delay_1ms(5)
SHUG_05 = 0
SHUG_06 = 1
LED_DATA = value_tab0[value_miao % 10]
Delay_1ms(5)
SHUG_06 = 0
}
void Tero_Init(void)
{
TMOD = 0x01
TH0 = 0x4C
TL0 = 0x00
ET0 = 1
TR0 = 1
EA = 1
}
void Scan_keyoutCmd(void)
{
if(KEY0_01 == 0)
{
Delay_1ms(10)
if(KEY0_01 == 0)
{
TR0 = ~ TR0
}
while(KEY0_01 == 0)
}
if(KEY0_02 == 0) {
Delay_1ms(10)
if(KEY0_02 == 0)
{
value_miao--
if(value_miao == -1)
{
value_feno--
value_miao = 59
if(value_feno == -1)
{
value_shio--
value_feno = 59
if(value_shio == -1)
{
value_shio = 23
}
}
}
while(KEY0_02 == 0)
}
}
if(KEY0_03 == 0){
Delay_1ms(10)
if(KEY0_03 == 0)
{
value_miao++
if(value_miao == 60)
{
value_miao = 0
value_feno++
if(value_feno == 60)
{
value_feno = 0
value_shio++
if(value_shio == 24)
{
value_shio = 0
}
}
}
while(KEY0_03 == 0) //检测松手
}
}
}
int main(void)
{
P1 = P2 = P3 = 0x00
Tero_Init()
while(1)
{
Scan_keyoutCmd()
Disp_layledketCmd() //执行应运程序
}
}
void Tmero()interrupt 1
{
TH0 = 0x4C
TL0 = 0x00
value_temp++
if(value_temp == 20)
{
value_temp = 0
value_miao++
if(value_miao == 60)
{
value_feno++
value_miao = 0
if(value_feno == 60)
{
value_shio++
value_feno = 0
if(value_shio == 24)
{
value_shio = 0
}
}
} }
}
(2)时间以24小时为一个周期,显示时、分、秒;
(3)计时过程具有报时功能,当时间到达整点前5秒进行蜂鸣报时;
(4)为了保证计时的稳定及准确须由晶体振荡器提供表针时间基准信号。
c51单片机 晶振为11.0592MHz
#include<reg52.h>
#define HOUR1 1
#define HOUR0 0
#define MIN1 2
#define MIN0 8
#define SEC1 2
#define SEC0 0
#define uint unsigned int
#define ulint unsigned long int
#define uchar unsigned char
sbit dula=P2^6
sbit wela=P2^7
sbit beep=P2^3
int i
ulint
sharp,second,count=0,sec0=SEC0,sec1=SEC1,min0=MIN0,min1=MIN1,hour0=HOUR0,hour1=HOUR1//秒计数全局变量
uchar code segment[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}
uchar code time[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f}
void delay(uint)//程序毫秒延时
void beeper(uchar)//开蜂鸣器毫秒
void init()//初始化函数
void display()//从数码管上显示
void counter()//计算进行过程中的时、分、秒值
void scan()//扫描键盘
void main()
{
init()
while(1)
{
scan()//扫描键盘看是否有键按下
for(i=6i>0i--)//动态扫描6位数码管
{
display()//显示时、分、秒
}
}
}
void init()
{
second=hour1*36000+hour0*3600+min1*600+min0*60+sec1*10+sec0
TMOD=0x01
TH0=(65536-46080)/256
TL0=(65536-46080)%256
EA=1
ET0=1
TR0=1
}
void delay(uint z)//程序毫秒延时
{
uint x=0,y=0
for(x=zx>0x--)
for(y=110y>0y--)
}
void timer0() interrupt 1
{
TH0=(65536-46080)/256
TL0=(65536-46080)%256
count++
if(count==20)//判断是否到1秒
{
counter()//计算进行过程中的时、分、秒值
if(sharp!=hour0) beeper(1000)//判断小时的值是否改变,变则启动蜂鸣器
}
}
void beeper(uchar tt)
{
uchar t=tt
count=0
beep=0//开蜂鸣器
delay(t)
beep=1//关蜂鸣器
}
void display()
{
P0=0xff//位消影(低电平选择位)
//送位选信号
wela=1
P0=segment[i-1]
wela=0
P0=0x00//段消影(高电平选择段)
//送段选信号
dula=1
switch(i)
{
case 6 : P0=time[sec0]break
case 5 : P0=time[sec1]break
case 4 : P0=time[min0]break
case 3 : P0=time[min1]break
case 2 : P0=time[hour0]break
case 1 : P0=time[hour1]break
}
delay(1)
P0=0x00//配合上面用于消隐
dula=0
}
void counter()
{
second++
if(second==86400) second=0
count=0
sharp=hour0//设置报时检测KEY
sec0=second%10
sec1=(second%60-sec0)/10
min0=((second%3600-sec1*10-sec0)/60)%10
min1=((second%3600-sec1*10-sec0)/60-min0)/10
hour0=(second%36000-min1*600-min0*60-sec1*10-sec0)/3600
hour1=second/36000
}
void scan()
{
}