STC89C51单片机实时时钟
基于89C51系列单片机的电子钟设计

电子钟原理框图
主要器件:
• STC89C51
• 电源
稳压芯片:7805、LM1117-2.85
• USB转串口芯片:PL2303HX • 通讯芯片:MAX232 • 储存芯片:IIC协议控制芯片AT24C02 (EEPROM) • 时钟芯片:SPI协议控制芯片DS1302 • 温度传感器:1-WIRE协议控制芯片DS18B20 • 液晶显示芯片:1602
储存芯片:EEPROM (AT24C02)
AT24C02是一个2K位串行CMOS E2PROM, 内部含有256个8位字节, CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有 一个16字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门 的写保护功能。
PL2302(USB转RS232控制器)
//显示温度、秒、时、分数据: write_temp(12,flag);//显示温度,从第二行第12个字符后开始显示 write_sfm(8,miao); write_sfm(5,fen); write_sfm(2,shi);
//显示日、月、年数据: write_nyr(9,ri);//日期,从第二行第9个字符后开始显示 write_nyr(6,yue); write_nyr(3,nian); write_week(week);}
液晶显示1602
LCD1602初始化流程图
液晶写入指令、数据函数
液晶写入有关函数会在DS1302的函数中调用,所以液晶程序要放在前面 • • • • • • • • • • write_1602com(uchar com)//****液晶写入指令函数**** { rs=0;//数据/指令选择置为指令 rw=0; //读写选择置为写 P0=com;//送入数据 delay(1); en=1;//拉高使能端,为制造有效的下降沿做准备 delay(1); en=0;//en由高变低,产生下降沿,液晶执行命令 }
单片机的实时时钟设计》

单片机的实时时钟设计》引言:实时时钟是嵌入式系统中常用的功能之一,可以实现对时间的准确计时和显示功能。
本文将以数码管显示为例,介绍单片机实时时钟的设计过程。
一、硬件设计1.单片机选择实时时钟通常需要较强的计算能力和丰富的IO口,方便与其他外设进行通信。
常用的单片机有STC89C52、AT89C51等。
本设计选择STC89C52单片机。
2.数码管显示选择常用的共阴极数码管进行显示。
数码管可以通过74HC595芯片进行驱动,将单片机的IO口扩展为8位,方便控制多个数码管的显示。
3.时钟芯片本设计选择DS1302时钟芯片作为实时时钟的核心。
DS1302芯片具有低功耗、精度高、抗干扰能力强等特点。
二、软件设计1.引入头文件#include <reg52.h> // 引入单片机头文件#include "DS1302.h" // 引入DS1302头文件,包含了DS1302芯片的驱动函数2.数码管显示函数void display(unsigned char *t)unsigned char i;unsigned char code table[] = { // 0-9的显示码0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};for(i = 0; i < 6; i++) // 依次显示年、月、日、时、分、秒P0=0xFF;//所有数码管熄灭P2=0x01<<i;//选择一些数码管P0 = table[t[i]]; // 数码管显示对应的数字Delay(1); // 延时一段时间}3.主函数void mainwhile(1)Delay(100); // 延时一段时间,例如100ms}4.初始化函数void InitDS1302_Init(; // DS1302芯片初始化5.主函数调用void mainInit(; // 调用初始化函数while(1)Display(; // 显示函数Count(; // 计数函数}结论:通过以上的硬件设计和软件编写,我们可以实现单片机的实时时钟功能,并通过数码管进行显示。
基于STC89C51单片机的数字时钟设计

基于STC89C51单片机的数字时钟设计基于STC89C51单片机的数字时钟设计现代社会,时间对每个人来说都是至关重要的。
无论是日常生活还是工作学习,我们都需要精确地掌握时间。
为了满足人们对时间的需求,数字时钟应运而生。
数字时钟以数字形式显示时间,具有读取清晰、显示准确等特点,成为了人们生活不可或缺的一部分。
本文将介绍一种基于STC89C51单片机的数字时钟设计。
首先,我们先了解一下STC89C51单片机。
STC89C51单片机是华中科技大学开发的一款单片机,具有性能优越、嵌入式功能强大等特点。
它集成了强大的CPU、周边模块和大容量存储器,能够实现各种功能。
在数字时钟设计中,我们选择STC89C51单片机作为核心控制器。
数字时钟设计主要分为两个模块,一个是时钟芯片,用于计时和存储时间信息;另一个是显示模块,用于显示时间。
首先,我们需要连接时钟芯片。
我们选择DS1302时钟芯片,它具有低功耗、精确性高等特点,能够满足数字时钟的需求。
通过将时钟芯片连接到STC89C51单片机的I/O口,我们可以通过单片机来读取时钟芯片中存储的时间信息。
接下来,我们需要设计显示模块。
我们选择了数码管作为显示元件,因为它具有读取清晰、显示准确等优点。
通过将数码管连接到STC89C51单片机的I/O口,我们可以通过控制单片机输出信号的方式来实现数字的显示。
在时钟的设计中,我们还需要考虑一些功能,比如时间调整功能、闹钟功能等。
我们可以通过增加按钮来实现时间调整功能。
当我们按下按钮时,单片机会接收到相应的信号,并做出相应的调整。
通过设置定时器,我们可以实现闹钟功能。
当定时器计数到预设时间时,单片机会触发相应的操作,比如发出声音或者控制其他设备。
数字时钟的设计不仅要考虑硬件部分,还需要编写相应的程序来控制单片机。
在这个设计中,我们需要实现时钟芯片的读取和显示模块的控制。
我们可以使用C语言来编写程序,并使用Keil C51开发环境进行开发。
#基于单片机89c51的电子时钟设计

目录摘要 ............................................................. 错误!未定义书签。
1 电子时钟 (2)1.1电子时钟简介 (2)1.2电子时钟的基本特点 (2)1.3电子时钟的原理 (2)2 单片机的相关知识 (3)2.1单片机简介 (3)2.2 PROTEUS软件简介 (3)2.3单片机的特点 (3)2.489C51单片机介绍 (3)3 控制系统的硬件设计 (5)3.1单片机型号的选择 (5)3.2数码管显示工作原理 (5)3.3键盘电路设计 (5)3.4整个电路原理图 (5)4 控制系统的软件设计 (6)4.1程序设计 (6)4.2程序流程图 (11)4.3仿真图 (13)4.4仿真结果分析.................................................... 错误!未定义书签。
5 结束语 (14)6 附录 (15)参考文献 ........................................................... 错误!未定义书签。
摘要:单片计算机即单片微型计算机。
由RAM ,ROM,CPU构成,定时,计数和多种接口于一体的微控制器。
它体积小,成本低,功能强,广泛使用于智能产业和工业自动化上。
而51系列单片机是各单片机中最为典型和最有代表性的一种。
这次课程设计通过对它的学习,使用,从而达到学习、设计、开发软、硬件的能力。
本设计主要设计了一个基于AT89C51单片机的电子时钟。
并在数码管上显示相应的时间。
并通过一个控制键用来实现时间的调节和是否进入省电模式的转换。
使用Proteus的ISIS软件实现了单片机电子时钟系统的设计和仿真。
该方法仿真效果真实、准确,节省了硬件资源。
关键字:单片机;子时钟;键盘控制1.电子时钟1.1 电子时钟简介1957年,Ventura发明了世界上第一个电子表,从而奠定了电子时钟的基础,电子时钟开始迅速发展起来。
基于at89c51的电子时钟设计

课程设计2:设计一个数字时钟。
要求如下:1.利用51开发板上LED数码管,LED灯,按键等设备,设计一个电子时钟。
2.电子钟使用4位数码管显示小时(24小时制)和分钟,秒可以使用LED灯或其他形式表现。
3.具有设置时钟功能,设置时间时,时间停止计时。
需要设置的位置数码管处于闪烁状态,如你想设置小时的数值时,显示小时的数码管需要处于闪烁状态,而显示分钟的数码管不可以处于闪烁状态,应处于正常显示状态。
4.按键可以选择独立键盘或矩阵键盘。
5.其他扩展功能(选做,能力强的可以做):如闹钟,时制切换等。
一.key.c#include "reg52.h"#include "key.h"extern unsigned char min_flag ;//标志位,控制分数码管闪烁extern unsigned char hour_flag ;//标志位,控制时数码管闪烁extern unsigned char shi ;extern unsigned char fen ;unsigned char key_flag = 0;//标志位,有按键被按下unsigned char key_con = 0;//控制位,控制按键(K1)被按下/*独立按键P12连接到51单片机P1端口k1对应的端口为P1.3k2对应的端口为P1.2k3对应的端口为P1.1k4对应的端口为P1.0*/code unsigned char arr[]={0xf7,0xfb,0xfd,0xfe};unsigned char read_key(unsigned char key){unsigned char i;for(i=0;i<8;i++){if(!(key & 1)){return i+1;}key>>=1; //key = key >> 1 ;}return 0;}void key_scan2(void){unsigned char temp;//键盘扫描temp = key4_scan();if(temp){if(!key_flag){if(temp==4)//K1被按下{key_con++;if(key_con==1) //第一次按下调整小时的数值{hour_flag=1;min_flag =0;}else if(key_con==2) //第二次按下调整分的数值{hour_flag=0;min_flag =1;}else //第三次按下取消调整{hour_flag=0;min_flag =0;key_con = 0;}}if(temp == 3) //增加数值{if(hour_flag){shi++;if(shi>23){shi = 0;}}else if(min_flag){fen++;if(fen>59){fen = 0;}}}if(temp == 2) //减少数值{if(hour_flag){shi--;if(shi>250){shi = 23;}}else if(min_flag){fen--;if(fen>250) //非负数,减的时候不会小于0{fen=59;}}}}key_flag = 1;}else{key_flag = 0;}}/*扫描独立键盘,输入参数:无返回值:有键按下时:返回对应的数字没有按键:返回0*/unsigned char key4_scan(void){unsigned char temp;P1 = 0xf;if(P1 != 0xf)//有按键被按下{temp = P1 & 0xf;//1110return read_key(temp);}return 0;}unsigned char sub_key_scan(unsigned char key) {unsigned char temp;P1 = key; //判断第一行temp = P1 >> 4;if(temp != 0xf){return read_key(temp);}return 0;}/*矩阵键盘硬件连接:P13连接到51单片机P1端口P1.0对应P13的1脚P1.1对应P13的2脚P1.2对应P13的3脚……P1.7对应P13的8脚输入参数:无返回值:有键按下时:返回对应的数字没有按键:返回0*/unsigned char key16_scan(void){unsigned char temp;unsigned char i=0;P1 = 0xf0;if(P1 != 0xf0)//有按键被按下{for(i=0;i<4;i++)//用函数扫描4行{temp = sub_key_scan(arr[i]);if(temp){return temp+(i*4);}}}return 0;}二.Key.h#ifndef KEY_H#define KEY_Hunsigned char key4_scan(void); unsigned char key16_scan(void);void key_scan2(void);#endif三.Led_reg.c#include "reg52.h"/*P2连接位码,P2.0连接Q4B,P2.1连接Q3B,P2.2连接Q2B,P2.3连接Q1B P0端口连接段码,P0.0连接A,。
基于STC89C51制作的具有记录天亮天黑时间功能的时钟

测 量 定值 电 阻上 的分 压 比就行 了 ,不 用考 虑 电压源 的 稳 定性 。在 为2 ,实 际上天 彻底 黑 的值 为0 O A 转 换上 采用A C 82 片就0 ,还 多 出来 一个通 道呢 。 D D0 3- K 在 通过 电脑 串 口上传 数 据时 候发 现每 次上 传一 位 需要 延时 一
功 能分 布如 下 :
x 缓 冲 区和 其 任意 边 界进 行 跳 变 时候 不进 行 触 发 ,唯i 或 者 在 l(
K :按 动 一 次 可 以进 行 小时 的调 整 ,且 小 时位 闪 烁 给 出提 X )跨 越 缓冲 区进 入X ( 1 2 2 或者 x ) 时候触 发记 录程 序 ,记 录下 当 1 示 ,按 动第 二次 可 以对 分钟 调整 ,同样 给 出提示 ,按下 第三 次 时 时 的 时间 。考 虑 到干 扰发 生 ,并进行 延 时再判 断 。
s i k = 3: b t l P2 s t bi k2 P 4: =2 s t 3= 2 bi k P 5;
s t D0 32 L P1 bi Nhomakorabea 8 C K= 0:
s t D0 32 D O= l: bi A 8 I PI
一
s t DO 32 C P1 bi A 8 S= 2:
令键。
在 E P O 进 行 写 的 时候 先 查 找 空 白 区 ,在 空 白 区进 行 按 组 ERM 写 入 ,本程 序 只写 入 了小 时分钟 秒 ,如 果扩 展 可 以加入 月份 和 日
期 。擦除 的时 候逐 个熄 灭数 码管 提示进 度 。 其余 的设 计细 节请 参考程 序 注释 。
U i ne c ar HS g d h i:
v i e o d st 0
基于89C51系列单片机的电子钟设计

目录1设计要求 (2)2设计方案和论证 (2)2.1总设计原理框图 (2)2.2设计方案的选择 (2)2.2.1计时方案 (2)2.2.2显示系统的方案 (3)3硬件部分 (3)3.1主要器件 (3)3.2 IO口分配说明 (3)3.3详细器件介绍 (4)3.3.1 STC89C51单片机介绍 (4)3.3.2电源 (6)3.3.3复位电路 (7)3.3.4 ULN2003(大电流驱动阵列) (7)3.3.5储存芯片:EEPROM (AT24C02) (8)3.3.6 PL2302(USB转RS232控制器) (8)3.3.7液晶显示1602 (10)3.3.8时钟芯片DS1302 (11)4 软件部分 (13)4.1主程序流程图 (13)4.2液晶初始化流程图 (14)4.3时间与日期显示流程图 (15)4.4温度显示流程图 (16)4.5键扫描流程图 (17)5调试和结果分析 (19)5.1调试 (19)5.2问题和结果分析 (20)6心得体会 (20)1.设计要求设计产品实现一个依据时段可变显示亮度电子钟,具体如下:(1)能够实现基本时钟的走时,显示范围是00:00:00——23:59:59。
能够实现时钟的调整, 通过按键可以对“时”位和“分”位进行加1调节,并能当加至最大值时能重新归零。
(2)能够实现当前室温的测量功能,并在数码管上予以显示(3)能够实现年月日的显示与切换。
(4)能够实现温度的显示与切换。
(5)能够实现根据时段自动改变显示亮度。
2.设计方案和论证本次设计时钟电路,使用了STC89C51单片机芯片控制电路,单片机控制电路简单且省去了很多复杂的线路,使得电路简明易懂,使用键盘键上的按键来调整时钟的时、分、秒、年、月、日、星期。
使用C 语言程序来控制整个时钟显示,主要这样通过四个模块:键盘、时钟芯片、温度传感器、1602lcd 显示即可满足设计要求。
2.1总设计原理框图 如下图所示:2.2 设计方案的选择2.2.1 计时方案方案一:采用实时时钟芯片现在市场上有很多实时时钟集成电路,如DS1287、DS12887、DS1302等。
基于51单片机的温度上下限控制(实时显示时间、温度)

delay(5);
if(K1==0)
{
th4++;
while(!K1);
if(th4==10)th4=0;
}
}
if(K2==0)
{
delay(5);
if(K2==0)
{
th4--;
while(!K2);
if(th4==-1)th4=9;
}
}
write_cmd(0xcc);
write_dat(th4+0x30);
{
if(K4==0)
{
delay(5);
if(K4==0)
{
while(!K4);
keynum++;
if(keynum==5)keynum=1;
}
}
return keynum;
}
void key_lcd()
{
if(flag1==1&&k==3)
{
if(K3==0)
{
delay(5);
if(K3==0)
#include"STC89C51RC.H"
#include<absacc.h>
#include"ds18b20.h"
#include"lcd1602.h"
#include"ds1302.h"
#include"2402.h"
uchar data datadis[]={0x00,0x00,0x00,0x00,0x00};
}
return dat;
}
/**写一个字节**/
void write_byte(uchar dat)
89C51单片机时钟程序

SECOND EQU 40H ;给内存RAM空间中40H单元起名SECOND MINUTE EQU 41H ;给内存RAM空间中41H单元起名MINUTE HOUR EQU 42H ;给内存RAM空间中42H单元起名HOUR SECONDGEWEI EQU 43H ;给43H单元起名SECONDGEWEI存秒的个位SECONDSHIWEI EQU 44H ;给44H单元起名SECONDSHIWEI存秒的十位MINUTEGEWEI EQU 45H ;给45H单元起名MINUTEGEWEI存分的个位MINUTESHIWEI EQU 46H ;给46H单元起名MINUTESHIWEI存分的十位HOURGEWEI EQU 47H ;给47H单元起名HOURGEWEI存小时的个位HOURSHIWEI EQU 48H ;给48H单元起名HOURSHIWEI存小时的十位ORG 0000H ;复位时程序从此开始SJMP START ;跳到START进行初始化ORG 000BH ;定时器0中断入口AJMP TIMER0 ;跳转到TIMER0处ORG 0030H ;初始化程序从30H开始;---------------初始化START------------------------------START:MOV SECOND, #0 ;给秒存储单元SECOND赋初始值0MOV MINUTE, #0 ;给分存储单元MINUTE赋初始值0MOV HOUR , #12 ;给小时存储单元HOUR赋初始值12MOV DPTR , #TAB ;给数据指针赋值,将DPTR指向TAB数据表头处MOV 30H, #0 ;给30H单元赋初始值0(用于计20次的50ms中断)MOV TH0,#3CH ;给计数容器的高8位TH0赋初始值3CHMOV TL0,#0B0H ;给计数容器的低8位TL0赋初始值B0HMOV TMOD,#00000001B ; C/T位设置为0,M1M0设置位10,即模式1定时MOV TCON,#00010000B ;TR0设置为1,即启动定时器0开始工作SETB ET0 ;IE中的ET0位设置为1,开定制器中断0SETB EA ; IE中的EA位设置为1,开总中断;-----------------------主程序MAIN-----------------------------MAIN:CALL KEY ;调按键子程序KEYCALL PROCESS ;调数据处理子程序PROCESSCALL DISPLAY ;调显示子程序DISPLAYSJMP MAIN ;跳转到MAIN标号处;------------------------------按键子程序KEY调时-------------------KEY:MOV P1,#0FEH ; 行扫描LCALL DELAY ;JNB P1.4,HOURJIA ; P1.4引脚如果是低电平就跳到HOURJIA处JNB P1.5,HOURJIAN ; P1.5引脚如果是低电平就跳到HOURJIAN处JNB P1.6,MINUTEJIA ; P1.6引脚如果是低电平就跳到MIMUTEJIA处JNB P1.7,MINUTEJIAN ; P1.7引脚如果是低电平就跳到MIMUTEJIAN处FANHUI:RET ;子程序返回(如果没有按键按下)HOURJIA:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.4,FANHUI ; P1.4如果是高电平就跳到FANHUI处(没键按) JNB P1.4,$ ;如果P1.4是低电平就停在当前位置等键释放MOV R4,HOURCJNE R4,#23,A1 ;判断时数字是否为23AJMP A2A1:INC HOUR ;把小时位加1MOV SECOND, #0 ;小时进位,秒归0RETA2:MOV HOUR,#0 ;小时数为23时加一为0MOV SECOND, #0 ; 小时进位,秒归0RET ;子程序返回HOURJIAN:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.5,FANHUI ; P1.5如果是高电平就跳到FANHUI处(没键按) JNB P1.5,$ ;如果P1.5是低电平就停在当前位置等键释放MOV R5,HOURCJNE R5,#0,A3 ;判断时数字是否为23AJMP A4A3:DEC HOUR ;把小时位减1MOV SECOND, #0RETA4:MOV HOUR,#23 ;小时数为0时减一为23MOV SECOND, #0RET ;子程序返回MINUTEJIA:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.6,FANHUI ; P1.6如果是高电平就跳到FANHUI处(没键按) JNB P1.6,$ ;如果P1.6是低电平就停在当前位置等键释放MOV R6,MINUTECJNE R6,#59,A5 ;判断分钟数是否为59AJMP A6A5:INC MINUTE ;把分钟位加1MOV SECOND, #0 ;给秒存储单元SECOND赋初始值0RETA6:MOV SECOND, #0MOV MINUTE, #0 ;分钟数为59则分钟归0MOV R4,HOURCJNE R4,#23,A10 ;判断时数字是否为23MOV HOUR,#0 ;23时增1归0RETA10:INC HOUR ;分钟数为59 自增1后小时增1RET ;子程序返回MINUTEJIAN:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.7,FANHUI ; P1.7如果是高电平就跳到FANHUI处(没键按) JNB P1.7,$ ;如果P1.7是低电平就停在当前位置等键释放MOV R7,MINUTECJNE R7,#0,A7 ;判断分钟数是否为0AJMP A8A7:DEC MINUTE ;分钟不为0把分钟位减1MOV SECOND, #0RETA8:MOV MINUTE, #59 ;分钟数为0时减一为59MOV R4,HOURCJNE R4,#0,A9 ;判断时钟数是否为0MOV HOUR,#23 ;时钟数为0减1为23MOV SECOND, #0RETA9:DEC HOUR ;时钟数不为0则减1MOV SECOND, #0RET ;子程序返回;-------------------处理子程序PROCESS-----------------------PROCESS:MOV A, SECOND ;把SECOND中的秒值拷贝给AMOV B, #10 ;给寄存器B赋值10DIV AB ;A除以B,结果存入A中,余数存入B中MOV SECONDSHIWEI , A ;结果即秒的十位数拷贝给SECONDSHIWEIMOV SECONDGEWEI , B ;余数即秒的个位拷贝给SECONDGEWEIMOV A, MINUTE ;把MINUTE中的分值拷贝给AMOV B, #10 ;给寄存器B赋值10DIV AB ;A除以B,结果存入A中,余数存入B中MOV MINUTESHIWEI , A ;结果即分的十位拷贝给MINUTESHIWEIMOV MINUTEGEWEI , B ;余数即分的个位拷贝给MINUTEGEWEIMOV A, HOUR ;把HOUR中的小时值拷贝给AMOV B, #10 ;给寄存器B赋值10DIV AB ;A除以B,结果存入A中,余数存入B中MOV HOURSHIWEI , A ;结果即小时的十位拷贝给HOURSHIWEIMOV HOURGEWEI , B ;余数即小时的个位拷贝给HOURGEWEIRET ;子程序结束返回到主程序;-----------------显示子程序DISPLAY--------------DISPLAY:MOV A, HOURSHIWEI ;小时的十位拷贝给AMOVC A, @A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(小时的十位)送到P0CLR P2.0 ;将P2.0置低电平,对应的三极管导通CALL DELAY ;调延时(让显示小时十位的数码管持续亮一段时间)SETB P2.0 ;将P2.0置高电平,对应三极管截止,对应数码管灭MOV A, HOURGEWEI ;小时的个位拷贝给AMOVC A,@A+DPTR ; 到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(小时的个位)送到P0CLR P2.1 ;将P2.1置低电平,对应的三极管导通CALL DELAY ;调延时(让显示小时个位的数码管持续亮一段时间)SETB P2.1MOV P0,#7FHCLR P2.1CALL DELAYSETB P2.1 ;将P2.1置高电平,对应三极管截止,对应数码管灭MOV A, MINUTESHIWEI ;分钟的十位拷贝给AMOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(分钟的十位)送到P0CLR P2.2 ;将P2.2置低电平,对应的三极管导通CALL DELAY ;调延时(让显示分钟十位的数码管持续亮一段时间)SETB P2.2 ;将P2.2置高电平,对应三极管截止,对应数码管灭MOV A, MINUTEGEWEI ;分钟的个位拷贝给AMOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(分钟的个位)送到P0CLR P2.3 ;将P2.3置低电平,对应的三极管导通CALL DELAY ;调延时(让显示分钟个位的数码管持续亮一段时间)SETB P2.3 ;将P2.3置高电平,对应三极管截止,对应数码管灭MOV P0,#7FHCLR P2.3CALL DELAYSETB P2.3MOV A, SECONDSHIWEI ;秒的十位拷贝给AMOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(秒钟的十位)送到P0CLR P2.4 ;将P2.4置低电平,对应的三极管导通CALL DELAY ;调延时(让显示秒钟十位的数码管持续亮一段时间)SETB P2.4 ;将P2.4置高电平,对应三极管截止,对应数码管灭MOV A, SECONDGEWEI ;秒的个位拷贝给AMOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(秒钟的个位)送到P0CLR P2.5 ;将P2.5置低电平,对应的三极管导通CALL DELAY ;调延时(让显示秒钟个位的数码管持续亮一段时间)SETB P2.5 ;将P2.5置高电平,对应三极管截止,对应数码管灭RET ;显示子程序结束返回主程序;--------------------中断服务子程序----------------------------TIMER0:MOV R3, A ;把A中的数据送入R3保护起来INC 30H ;30H单元中的数加1MOV A, 30H ;30H单元中的数据拷贝给ACJNE A,#20,JIXU ;A中的数据与20比较不相等就跳转到JIXU处MOV 30H,#0 ;(如果30H单元计满20了)给30H赋值0INC SECOND ;把SECOND中的秒钟数加1MOV A,SECOND ;把SECOND中的数据拷贝给ACJNE A, #60, JIXU ;A中的数据与60比较不相等就跳转到JIXU处MOV SECOND, #0 ;给秒SECOND赋值0INC MINUTE ;把MINUTE中的分钟数加1MOV A, MINUTE ;把MINUTE中的数据拷贝给ACJNE A, #60, JIXU ;A中的数据与60比较不相等就跳转到JIXU处MOV MINUTE, #0 ;给分钟MINUTE赋值0INC HOUR ;把HOUR中的小时数据加1MOV A, HOUR ;把HOUR中的数据拷贝给ACJNE A, #24, JIXU ;A中的数据与24比较不相等就跳转到JIXU处MOV HOUR, #0 ;给小时HOUR赋值0JIXU: MOV A,R3 ;把刚才送入R3中的数据还给AMOV TH0,#3CH ;给计数容器的高8位TH0赋初始值3CHMOV TL0,#0B0H ;给计数容器的低8位TL0赋初始值B0HRETI ;中断子程序返回主程序;---------------------------延时子程序----------------------------DELAY:MOV R0, #50 ;给R0赋值50D2:MOV R1, #10 ;给R1赋值10D1:DJNZ R1, D1 ;R1减1不等于0跳到D1处DJNZ R0, D2 ;R0减1不等于0跳到D2处RET ; 延时子程序结束返回调用该程序的下一条;---------------下面的数据表中存储的是显示段码(共阳)-------------------TAB:DB 0C0H,0F9H,0A4H,0B0H,99H ;从TAB处开始存储0、1、2、3、4 DB 92H ,82H ,0F8H,80H ,90H ;5、6、7、8、9对应的显示段码END ;程序结束。
单片机课程设计89C51数字时钟

单片机课程设计报告课题:基于89C51的数字时钟学院:理学院专业:光信息科学与技术**:***学号:*************:**淮海工学院2010年12月23日摘要单片机自20世纪70年代问世以来,以其极高的性能价格比,受到人们的重视和关注,应用很广、发展很快。
而51单片机是各单片机中最为典型和最有代表性的一种。
本实验是基于MCS51系列单片机所设计的,可以实现键盘按键与数字动态显示并可以用音乐倒数的计数器。
本设计基于单片机技术原理,以单片机芯片AT89C51作为核心控制器,通过硬件电路的制作以及软件程序的编制,设计制作出一个计数器,包括以下功能:输出时间。
一、设计目的1、学会掌握KeilC51汇编语言程序的设计和调试。
2、学会将所学的单片机原理的有关知识应用于实践,提高单片机应用于技术的实践操作技能,掌握单片机应用系统设计、研制的方法,培养理论联系实际的学习作风,提高动手能力、分析并解决实际问题的能力。
3、使我们进一步了解掌握所学的专业知识,巩固和深化对单片机的结构、指令系统、中断系统、键盘/显示系统、接口技术、系统扩展、定时/控制、程序设计、应用开发、等基本理论知识的理解。
4、通过设计、分析、调试,培养我们工程意识,激发大家对产品开发的兴趣,及培养对科技革新、开发和创新的基本能力。
二、设计要求1.开机时,显示12:00:00的时间开始计时;2.P3.0/ AD0控制”秒”的调整,每按一次加1秒;3.P3.1/ AD0控制”分”的调整,每按一次加1分;4.P3.2/ AD0控制”时”的调整,每按一次加1小时;5.用protues画出原理图并仿真实现,写出源程序;6.在万用板上焊接元件调试;7.写出详细的实验报告。
三、所需电子元器件单片机89C51. 1个非门74LS04. 1个缓冲器74 LS373. 1个LG3611AH数码管. 6个电阻1(1KΩ). 8个电阻2(10KΩ). 1个电阻3(510Ω). 3个电容.(33pf) 2个电解电容. 1个四设计原理及其框图1.数字钟的构成数字钟实际上是一个对标准频率(1HZ)进行计数的计数电路.由于计数的起始时间不可能与标准时间一致,故需要在电路上加一个校时电路,同时标准的1HZ时间信号必须做到准确稳定.通常使用石英晶体振荡器电路构成数字钟.⑴晶体振荡器电路晶体振荡器电路给数字钟提供一个频率稳定准确的32768Hz的方波信号,可保证数字钟的走时准确及稳定.不管是指针式的电子钟还是数字显示的电子钟都使用了晶体振荡器电路.⑵分频器电路分频器电路将32768Hz的高频方波信号经32768()次分频后得到1Hz的方波信号供秒计数器进行计数.分频器实际上也就是计数器.⑶时间计数器电路时间计数电路由秒个位和秒十位计数器,分个位和分十位计数器及时个位和时十位计数器电路构成,其中秒个位和秒十位计数器,分个位和分十位计数器为60进制计数器,而根据设计要求,时个位和时十位计数器为24进制计数器.⑷译码驱动电路译码驱动电路将计数器输出的8421BCD码转换为数码管需要的逻辑状态,并且为保证数码管正常工作提供足够的工作电流.⑸数码管数码管通常有发光二极管(LED)数码管和液晶(LCD)数码管,本设计提供的为LED数码管.2.数字钟的工作原理设计原理主要利用AT89C51单片机,由单片机的p2口控制数码管的位显示,p1口控制数码管的段显示,p3.0——p3.2与按键相接用于时间校正。
基于单片机STC89C516RD+的电子钟设计

单片机课程设计实验报告——基于STC89C516RD+的电子钟设计学院:电气与电子工程学院班级:姓名: ===学号:时间: 2015.06目录1.实验内容及要求………………………………………………/012.课题研究目的和意义及介绍……………………………../013.设计思路及描述………………………………………………/024.硬件设计………………………………………………………../035.软件设计………………………………………………………../066.实验心得及体会………………………………………………/107.总结………………………………………………………………./11一、实验内容及要求1.实验内容用STC89C516RD+设计一个用电子屏显示的电子钟,可以显示年、月、日以及时、分、秒,且时间时时刻刻在变化,秒数每秒加一且可以进行分钟进位小时进位。
另外该电子钟还可以设置闹钟,闹钟到达指定时刻时便自动进行闹铃,间断响铃持续一分钟后停止,而在其过程中若是按下键盘上的#号键可以将闹钟关闭,不仅如此#号键就是闹钟的总开关,按下一次闹钟关闭,再按一次闹钟开启。
对应键盘上的*号键功能为设置闹钟,按下*号键再用键盘输入四位数字如“0909”,9时9分就成为了电子钟的闹铃时间。
2.实验要求了解89C51系列芯片的工作原理和工作方式,使用该种芯片对LCD数字显示屏进行显示控制,实现用单片机的端口控制显示屏,显示时间年月日时分秒,并且能通过按键来设置一个闹钟,并可以控制开启和关闭闹钟。
要求选用定时器的工作方式,画出使单片机控制LCD显示屏的电路图,并实现硬件电路,最后用软件编程完成闹钟设置、闹钟提醒、闹钟开关功能。
二、课题研究目的和意义及介绍1.目的意义1)通过本次课程设计加深对单片机课程的全面认识复习和掌握,对单片机课程的应用进一步的了解。
2)掌握定时器、外部中断的设置和编程原理。
3)通过此次课程设计能够将单片机软硬件结合起来,对程序进行编辑,校验。
根据单片机STC89C516RD的电子钟设计

单片机课程设计实验报告——基于STC89C516RD+的电子钟设计学院:电气与电子工程学院班级:姓名: ===学号:时间: 2015.06目录1.实验内容及要求………………………………………………/012.课题研究目的和意义及介绍……………………………../013.设计思路及描述………………………………………………/024.硬件设计………………………………………………………../035.软件设计………………………………………………………../066.实验心得及体会………………………………………………/107.总结………………………………………………………………./11一、实验内容及要求1.实验内容用STC89C516RD+设计一个用电子屏显示的电子钟,可以显示年、月、日以及时、分、秒,且时间时时刻刻在变化,秒数每秒加一且可以进行分钟进位小时进位。
另外该电子钟还可以设置闹钟,闹钟到达指定时刻时便自动进行闹铃,间断响铃持续一分钟后停止,而在其过程中若是按下键盘上的#号键可以将闹钟关闭,不仅如此#号键就是闹钟的总开关,按下一次闹钟关闭,再按一次闹钟开启。
对应键盘上的*号键功能为设置闹钟,按下*号键再用键盘输入四位数字如“0909”,9时9分就成为了电子钟的闹铃时间。
2.实验要求了解89C51系列芯片的工作原理和工作方式,使用该种芯片对LCD数字显示屏进行显示控制,实现用单片机的端口控制显示屏,显示时间年月日时分秒,并且能通过按键来设置一个闹钟,并可以控制开启和关闭闹钟。
要求选用定时器的工作方式,画出使单片机控制LCD显示屏的电路图,并实现硬件电路,最后用软件编程完成闹钟设置、闹钟提醒、闹钟开关功能。
二、课题研究目的和意义及介绍1.目的意义1)通过本次课程设计加深对单片机课程的全面认识复习和掌握,对单片机课程的应用进一步的了解。
2)掌握定时器、外部中断的设置和编程原理。
3)通过此次课程设计能够将单片机软硬件结合起来,对程序进行编辑,校验。
基于stc89c51单片机的数码管时钟

/*郑州轻工业学院——————wuzhipeng*//*共有四个按键,K1按下后时钟启动,K1断开后可以调表,其余三个按键分别调整时分秒,调整完毕按下k1确认*/#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar count=0,miao=0,fen=0,shi=0;uchar date[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf}; uchar code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};int time[10];sbit K1=P3^2;sbit K2=P3^3;sbit K3=P3^4;sbit K4=P3^5;bit K1flag=0;void delay(uint xms){uint i,j;for (i=xms;i>0;i--)for(j=115;j>0;j--); }void display(){time[0]=miao%10;time[1]=miao/10;time[2]=11;time[3]=fen%10;time[4]=fen/10;time[5]=11;time[6]=shi%10;time[7]=shi/10;P2=wei[0];P1=date[time[0]];delay(1);//P2=wei[1];P1=date[time[1]];delay(1);//P2=wei[2];P1=date[time[2]];delay(1);//P2=wei[3];P1=date[time[3]];delay(1);//P2=wei[4];P1=date[time[4]];delay(1);//P2=wei[5];P1=date[time[5]];delay(1);//P2=wei[6];P1=date[time[6]];delay(5);//P2=wei[7];P1=date[time[7]];delay(1);//}void KeyProcess()//键盘处理程序{display();if(K2==0){delay(10) ;if (K2==0){while (!K2);shi++;if (shi==11) shi=0; //小时调整}}if(K3==0){delay(1) ;if (K3==0){while (!K3);fen++;if (fen==11) fen=0;//分钟调整}}if(K4==0){delay(1) ;if (K4==0)while (!K4);miao++;if (miao==11){miao=0; }//秒调整}}}void main (){TMOD=0x01;TH0=0x4c;TL0=0x00;EA=1;ET0=1;TR0=0;while (1){if(K1==0){TR0=1;display(); }else{TR0=0; KeyProcess();}}}void timer0() interrupt 1 using 0//中断程序{TH0=0x4c;TL0=0x00;count++;if(count==20){count=0;miao++;}if(miao==11)miao=0;fen++;if(fen==11){fen=0;shi++;if(shi==11){shi=0;}}}}。
基于stc89c51的数字时钟

基于stc89c51的数字时钟配件:ds1302,cap,cap-pol,res,crystal,1602,button下面是所有程序:#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define DB P0/**********宏定义***************/#define write_second 0x80#define read_second 0x81#define write_minute 0x82#define read_minute 0x83#define write_hour 0x84#define read_hour 0x85#define write_day 0x86#define read_day 0x87#define write_month 0x88#define read_month 0x89#define write_week 0x8a#define read_week 0x8b#define write_year 0x8c#define read_year 0x8d#define write_protect 0x8e#define s_left 0x10#define s_right 0x14#define s_reset 0x02#define s_shuton 0x0f#define s_shutdown 0x0cuchar sj[18]={2,0,1,2,00,0,5,00,0,8,1,0,00,4,4,00,5,3}; //年月日时分秒uchar sec,min,hou,day,mon,week,year;uchar flog=0; // 时间标志,为0代表正常走时,为1代表按键调整时间/************接口定义*******************/sbit RW=P2^6;sbit RS=P2^7;sbit E=P2^5;sbit SCLK=P2^0;sbit IO=P2^1;sbit RST=P2^2;sbit beep=P2^3;sbit button_set=P1^0;sbit button_add=P1^1;sbit button_dec=P1^2;sbit button_save=P1^3;void delay_ms(uchar x){unsigned char a,b,c;for(c=x;c>0;c--)for(b=142;b>0;b--)for(a=2;a>0;a--); }bit lcd_busy(void){ uchar result;RS=0;RW=1;E=1;_nop_();_nop_();_nop_();_nop_();result=(bit)(DB&0x80);E=0;return(result);}void lcd_wcmd(uchar cmd) {while(lcd_busy());RS=0;RW=0;E=0;DB=cmd;_nop_();_nop_();_nop_();_nop_();E=1;_nop_();_nop_();_nop_();_nop_();E=0;}void lcd_wdat(uchar dat){ while(lcd_busy());RS=1;RW=0;E=0;DB=dat;_nop_();_nop_();_nop_();_nop_();E=1;_nop_();_nop_();_nop_();_nop_();E=0;}void lcd_clear(void){lcd_wcmd(0x01);delay_ms(5);}void Initial_LCD(void) //LCD初始化{delay_ms(15);lcd_wcmd(0x38); //16*2显示delay_ms(5);lcd_wcmd(0x38);delay_ms(5);lcd_wcmd(0x38);delay_ms(5);lcd_wcmd(0x0c); //显示开,光标关delay_ms(5);lcd_wcmd(0x06); //移动光标写一个字符光标右移,整屏显示不移动delay_ms(5);lcd_clear(); //清屏}void buzzer(void) //蜂鸣器响,频率20hz { beep=0;delay_ms(50);beep=1;delay_ms(50);}void write_1302_byte(uchar addr){uchar i;for(i=0;i<8;i++){ IO=addr&0x01;SCLK=0;SCLK=1;addr>>=1;}}void write1302(uchar addr,dat){ RST=0;SCLK=0;RST=1;write_1302_byte(addr);write_1302_byte(dat);RST=0;}uchar read_1302_byte(void){ uchar i,temp=0x00;for(i=0;i<8;i++){ if(IO) temp|=0x80;SCLK=1;SCLK=0;temp>>=1;}return(temp);}uchar read1302(uchar addr){ uchar date;RST=0;SCLK=0;RST=1;write_1302_byte(addr);date=read_1302_byte();return(date);}void gettime(void) //读取时间{sec=read1302(read_second);sj[16]=((sec>>4)&0x0f)|0x30; //1302中的数值是以压缩BCD码形式保sj[17]=sec&0x0f|0x30; //存,要转换成16进制才能正常显示if(sec==0){ min=read1302(read_minute);sj[13]=((min>>4)&0x0f)|0x30;sj[14]=min&0x0f|0x30;if(min==0){ hou=read1302(read_hour);sj[10]=((hou>>4)&0x0f)|0x30;sj[11]=hou&0x0f|0x30;if(hou==0){ day=read1302(read_day);sj[8]=((day>>4)&0x0f)|0x30;sj[9]=day&0x0f|0x30;if(day==1){ mon=read1302(read_month);sj[5]=((mon>>4)&0x0f)|0x30;sj[6]=mon&0x0f|0x30;}if(mon==1){ year=read1302(read_year);sj[2]=((year>>4)&0x0f)|0x30;sj[3]=year&0x0f|0x30;}}}}if(min==0&&flog==0) buzzer(); //整点报时}void Initial_time(void) //日期初始化{ year=read1302(read_year); //转换成LCD对应的数码sj[2]=((year>>4)&0x0f)|0x30; //不能做数值加减sj[3]=year&0x0f|0x30;mon=read1302(read_month);sj[5]=((mon>>4)&0x0f)|0x30;sj[6]=mon&0x0f|0x30;day=read1302(read_day);sj[8]=((day>>4)&0x0f)|0x30;sj[9]=day&0x0f|0x30;hou=read1302(read_hour);sj[10]=((hou>>4)&0x0f)|0x30;sj[11]=hou&0x0f|0x30;min=read1302(read_minute);sj[13]=((min>>4)&0x0f)|0x30;sj[14]=min&0x0f|0x30;sec=read1302(read_second);sj[16]=((sec>>4)&0x0f)|0x30;sj[17]=sec&0x0f|0x30;}void Initial_1302(void) //1302初始化、时间初始化{ write1302(write_protect,0x80); /************************/write1302(write_second,0x32); /**********不能删********/ write1302(write_minute,0x24); /************************/ write1302(write_hour,0x16); /************************/ write1302(write_protect,0x00); /************************/ }void LCD_DISPLAY(void) //显示{ lcd_wcmd(0x00|0x80);delay_ms(5);lcd_wdat(sj[0]|0x30);delay_ms(5);lcd_wdat(sj[1]|0x30);delay_ms(5);lcd_wdat(sj[2]);delay_ms(5);lcd_wdat(sj[3]);delay_ms(5);lcd_wdat(0x3a);delay_ms(5);lcd_wdat(sj[5]);delay_ms(5);lcd_wdat(sj[6]);delay_ms(5);lcd_wdat(0x3a);delay_ms(5);lcd_wdat(sj[8]);delay_ms(5);lcd_wdat(sj[9]);delay_ms(5);lcd_wcmd(0x40|0x80);delay_ms(5);lcd_wdat(sj[10]);delay_ms(5);lcd_wdat(sj[11]);delay_ms(5);lcd_wdat(0x3a);delay_ms(5);lcd_wdat(sj[13]);delay_ms(5);lcd_wdat(sj[14]);delay_ms(5);lcd_wdat(0x3a);delay_ms(5);lcd_wdat(sj[16]);delay_ms(5);lcd_wdat(sj[17]);}void time_control(void) //设置时间{ uchar dat;lcd_wcmd(s_shuton); //开显示,有光标,闪烁delay_ms(5);dat=sj[18-flog];if(!button_add){ delay_ms(20);if(!button_add){ while(!button_add);dat++;}}if(!button_dec){ delay_ms(20);if(!button_dec){ while(!button_dec);dat--;}}switch(flog) /*设置显示函数,使修改后的数值能立即显示在1602上*/{ case 1:case 4: if(dat>0x39) dat=0x30;break;case 2:case 5: if(dat>0x35) dat=0x30;break;case 8: if(dat>0x32) dat=0x30;break;case 7: if(sj[10]==0x32){ if(dat>0x34) dat=0x30;}else if(dat>0x39) dat=0x30;break;}sj[18-flog]=dat;if(flog>8) lcd_wcmd(0x00|0x80+18-flog);else lcd_wcmd(0x40|0x80+8-flog);delay_ms(5);lcd_wcmd(s_shutdown); //关光标delay_ms(5);lcd_wdat(dat);delay_ms(5);lcd_wcmd(s_left);delay_ms(5);}void save_time(void){ sec=((sj[17]&0x0f)|(sj[16]<<4)); /*需要把LCD显示模式的数修改成十六进制普通数*/min=((sj[14]&0x0f)|(sj[13]<<4));hou=((sj[11]&0x0f)|(sj[10]<<4));day=((sj[9]&0x0f)|(sj[8]<<4));mon=((sj[6]&0x0f)|(sj[5]<<4));year=((sj[3]&0x0f)|(sj[2]<<4));write1302(write_protect,0x80);write1302(write_second,sec);write1302(write_minute,min);write1302(write_hour,hou);write1302(write_day,day);write1302(write_month,mon);write1302(write_year,year);write1302(write_protect,0x00);}main(){ Initial_1302();Initial_LCD();Initial_time();while(1){ if(!flog){ gettime();LCD_DISPLAY();}if(!button_set){ delay_ms(20);if(!button_set){ while(!button_set);lcd_wcmd(s_reset);delay_ms(5);lcd_wcmd(0x40|0x80+8);delay_ms(5);flog++; //flog!=0进入调时模式if(flog==17){ lcd_wcmd(s_shutdown); //关闭光标save_time(); //保存时间flog=0; //进入时间模式}if(flog==1) //只有第一次进入设置时对LCD进行设置{ lcd_wcmd(s_shuton); //开显示,有光标,闪烁delay_ms(5);}lcd_wcmd(s_left); //光标向左滚动if(flog==3||flog==6||flog==11||flog==14){ lcd_wcmd(s_left); //补移位flog++;}if(flog==9){ lcd_wcmd(s_reset); //光标复位delay_ms(5);lcd_wcmd(s_right); //光标向右滚动delay_ms(5);lcd_wcmd(s_right); //delay_ms(5);lcd_wcmd(s_right); //delay_ms(5);lcd_wcmd(s_right); //delay_ms(5);lcd_wcmd(s_right); //delay_ms(5);lcd_wcmd(s_right); //delay_ms(5);lcd_wcmd(s_right); //delay_ms(5);lcd_wcmd(s_right); //delay_ms(5);lcd_wcmd(s_right); //delay_ms(5);lcd_wcmd(s_right); // 光标向右滚动共10次}}}if(flog!=0) //修改时间{ time_control();}if(!button_save) //保存修改值{ delay_ms(20);if(!button_save){ while(!button_save);lcd_wcmd(s_shutdown); //关闭光标save_time(); //保存时间flog=0; //回到时间模式}}}}电路图附带整点报时功能,四个按键从上到下分别是,设置,加,减,保存。
STC89C51单片机实时时钟

STC89C51单片机实时时钟设计
设计时间: 设计人员:
原件清单:
1:主控CPU(STC89C52) 2:时钟芯片(ds12C887),外部ram。 3:电阻、电容、USB接口、DC9.0接口。
程序思路
开机上电初始I/O口,延时 20ms,稳定系统。
检测是否存在温度控件, 时间控件。
检不存在温度检测, 时间控件。
存在温度检测, 时间控件。 初始化液晶屏或 LED点阵系统, 当前无显示状态。 检测当前开机画面编号, 按编号调去开机画面显 示。 读取时间,读取温度, 进行位处理,送交液 晶屏或LED点阵显示。
单片机课程设计_基于89C51的数字电子时钟的设计

单片机系统课程设计成绩评定表设计课题基于89C51的数字电子时钟设计学院名称:电气工程学院专业班级:学生姓名:学号:指导教师:设计地点:设计时间:单片机系统课程设计课程设计名称:基于89C51的数字电子时钟设计专业班级:学生姓名:学号:指导教师:课程设计地点:课程设计时间:2014-01-01~2015-01-12单片机系统课程设计任务书目录1 引言 (5)2 设计目的 (5)3 系统方案与总体结构设计 (5)3.1系统方案设计 (5)3.2数字时钟框图设计 (6)4数字时钟的硬件构成 (8)4.1 选用芯片简介 (8)4.2 LED数码显示器简介 (12)5各个模块工作原理及原理图 (12)5.1计时模块 (13)5.2数字时钟控制模块 (13)5.3振荡模块 (14)5.4显示模块 (14)6系统软件设计 (15)6.1软件设计的要点 (15)6.2 AT89C51内部定时器/计数器0的使用方法 (15)6.3 程序设计流程图 (16)7系统调试与总结 (17)7.1电路调试 (17)7.2软件调试 (17)8结论与心得 (18)附录A系统原理图 (18)附录B 源程序 (20)参考文献 (26)1 引言数字时钟是一种用数字电路技术实现时、分、秒计时的装置,与机械式时钟相比具有更高的准确性和直观性,无机械装置,具有更长的使用寿命。
数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字时钟的精度,远远超过老式钟表,使其得到了广泛的使用。
该课程设计为数字电子钟的设计。
以AT89C51为核心,配合8位7段共阴极LED数码管显示实时数据,按键可以进行数据调整,为用户提供长期、连续、可靠、稳定的工作环境。
该数字电子钟有时分秒显示功能以及时间的调整的功能。
系统软件设计主要实现参数设置、串行口数据接收、指令发送以及数据的显示和存储,并且实现键盘、液晶显示器等各模块的功能,采用汇编语言编程。
关键词:数字电子钟单片机汇编语言2 设计目的深化和扩充在单片机原理及相关课程方面的基本知识、基本理论和基本技能熟悉设计过程,了解设计步骤,掌握设计内容,培养设计电路、实现软件编程和编写设计说明书能力的目的,为今后从事相关方面的实际工作打下良好基础。
89c51单片机数码管时钟例程

//data: 2010-07-06//writer: wu xian dian//fame: wan nian li//function:a时分秒的精确显示及设定;b定时的精确显示及设定;c定时时刻不影响时钟精确走时;// d当输入数值有误将蜂鸣报警且数值归1或0;e可以进行定时时间的查看;// f可进行星期的设定及查看g可进行年月日的设定及查看// h可进行平、闰年的分辨;i拥有定时时间到报时1分及整点提示,显示不会闪烁;// j定时、调时为移位显示,设定万年历为单显;星期、定时、调时、年、月日分屏显示;// k可进行数码管和蜂鸣器的检验;L当闹钟响起可随时关闭;#include<at89x51.h>void control(void);//判断是否进行键盘操作;void display(char,char);//显示,位控和段控;void delayms(unsigned int x);//延时;void common(void);//定时、调时显示控制;void fixed_times(void);//定时,进行时分秒输入。
先按11号键,再按六位数字键,自动返回运行;void swap_times(void);//调时,进行时分秒输入。
先按12号键,再按六位数字键,自动返回运行;void fixed_show(void);//全显示,检查数码管和蜂鸣器好坏,按零号键;void week(void);//星期设定8返回7;void week_show(void);//星期显示6返回5;void calendar_show(void);//日历显示4显示年,3显示月日,2返回;void calendar(void);//日历设定2显示年,3显示月日,4返回;char key(void);//键盘;void initial(void);//初始化;定时中断char hour1=1,hour0=2,min1=0,min0=0,sec1=0,sec0=0,n=0,w=1,v=1,//主显示全局变量;n循环次数w星期显示v闹铃判断位;fhour1=0,fhour0=0,fmin1=0,fmin0=0,fsec1=0,fsec0=0,//定时、调时共用全局变量;t6=0,t5=6,t4=0,t3=0,t2=0,t1=0,//定时显示全局变量;year3=2,year2=0,year1=1,year0=0,mouts1=0,mouts0=7,day1=0,day0=7;//年月日全局变量;int a1[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年;int a0[12]={31,29,31,30,31,30,31,31,30,31,30,31};//闰年;int *p;//为a1.a0设置指针;//********************************************************************定义和声明;void main(void){initial();//初始化while(1){P1=0x0f;if(P1!=0x0f)//判位进入调控程序;control();P1=0xff;display(5,hour1);///主显示程序;delayms(150);display(4,hour0);delayms(150);display(3,min1);delayms(150);display(2,min0);delayms(150);display(1,sec1);delayms(150);display(0,sec0);delayms(150);}}//*************************************************判位操作显示;void control(void){P1=0xbf;if(P1==0xbe)// 1显示数码管和蜂鸣器,自动返回;{P2=0x00;P0=0xff;delayms(2000);}else if(P1==0xb7)//4显示某年,3显示某月日,2返回;calendar_show();else if(P1==0xbb)// 3定时年,2定时月日,1返回;calendar();P1=0xef;if(P1==0xeb)// 11定时,自动返回;fixed_times();else if(P1==0xe7)// 12调时,自动返回;swap_times();else if(P1==0xed)// 10显示定时9返回;fixed_show();P1=0xdf;if(P1==0xd7)// 8星期设置7返回;week();else if(P1==0xdd)// 6星期显示5返回;week_show();else if(P1==0xde)//关闭闹铃;v=1;}//******************************************************中断入口;void time0(void) interrupt 1//定时中断0;{ unsigned int q;if(v==0)//盘闹铃是否工作;P2_7=0;elseP2_7=1;q=year3*1000+year2*100+year1*10+year0;//平、闰年判别;if((q%4==0&&q%100!=0)||(q%400==0))p=a0;//闰年指针指向;else p=a1;//平年指针指向;TH0=0xb8;//20ms定时;TL0=0x00;n==50? n=0:++n;//循环次数;if(n==0)//时分秒的进位;{++sec0;if(sec0==10){sec0=0;++sec1;if(sec1==6){sec1=0;++min0;if(hour1==t6&&hour0==t5&&min1==t4&&min0==t3)//判蜂鸣器响,v=0;//闹铃标志位;else//判蜂鸣器,虽然雍杂,但蜂鸣时数码管不闪烁;v=1;if(min0==10){min0=0;++min1;if(min1==6){min1=0;++hour0;P2_7=0;delayms(8000);if(hour0==10){hour0=0;++hour1;}}}}}}if((hour1==2)&&(hour0==4))//判是否大于24点{hour1=0;hour0=0;++w;if(w>7||w<1)//星期控制1-7天;w=1;if(++day0==10)//日的判断进位;{day0=0;++day1;}if(day1*10+day0>*(p+(mouts1*10+mouts0-1))){day0=1;day1=0;++mouts0;}if(mouts0==10)//月的判断进位;{mouts0=0;++mouts1;}if(mouts1*10+mouts0>12){mouts0=1;mouts1=0;++year0;}if(year0==10)//年的判断进位;{year0=0;++year1;if(year1==10){year1=0;++year2;if(year2==10){year2=0;++year3;if(year3==10){year3=0;}}}}}}////*****************************************************************显示程序;void display(char m,char n){unsigned char y[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsigned char z[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};P2=z[m];P0=y[n];}///*********************************************************************延时程序;void delayms(unsigned int x){unsigned int y;for(y=0;y<x;++y);}////****************************************************************键盘程序;char key(void){P1=0x0f;loop: if(P1==0x0f)goto loop;delayms(3350);if(P1==0x0f)goto loop;while(1){ P1=0xbf;if(P1_0==0) {while(P1!=0xbf); return 0;}if(P1_1==0) {while(P1!=0xbf); return 1;}if(P1_2==0) {while(P1!=0xbf); return 2;}if(P1_3==0) {while(P1!=0xbf); return 3;}P1=0xdf;if(P1_0==0) {while(P1!=0xdf); return 4; }if(P1_1==0) {while(P1!=0xdf); return 5;}if(P1_2==0) {while(P1!=0xdf); return 6;}if(P1_3==0) {while(P1!=0xdf); return 7;}P1=0xef;if(P1_0==0) {while(P1!=0xef); return 8;}if(P1_1==0) {while(P1!=0xef); return 9;}}}//*************************************************************定时时间程序;void fixed_times(void){P2=0xfe;P0=0x71;common();t6=fhour1;t5=fhour0;t4=fmin1;t3=fmin0;t2=fsec1;t1=fsec0;}///************************************************************调时程序;void swap_times(void){P2=0xfe;P0=0x6d;common();hour1=fhour1;hour0=fhour0;min1=fmin1;min0=fmin0;sec1=fsec1;sec0=fsec0;}//************************************************************初始化程序;void initial(void){TH0=0xb8;TL0=0x00;IE=0x82;TMOD=0x01;TR0=1;}//*******************************************调时、定时共用设定和显示程序;void common(void){char f=0,j=0,k;for(k=0;k<6;++k){switch(++f){case 1:{for(fsec0=key();fsec0>2;fsec0=0){P2_7=0;delayms(3000);}P2_7=1;break;}case 2:{fsec1=fsec0;for(fsec0=key();fsec1>=2&&fsec0>=4;fsec0=0){P2_7=0;delayms(3000);}P2_7=1;break;}case 3:{fmin0=fsec1;fsec1=fsec0;for(fsec0=key();fsec0>5;fsec0=0){P2_7=0;delayms(3000);}P2_7=1;break;}case 4:{fmin1=fmin0;fmin0=fsec1;fsec1=fsec0;fsec0=key();break;}case 5:{fhour0=fmin1;fmin1=fmin0;fmin0=fsec1;fsec1=fsec0;for(fsec0=key();fsec0>5;fsec0=0){P2_7=0;delayms(3000);}P2_7=1;break;}case 6:{fhour1=fhour0;fhour0=fmin1;fmin1=fmin0;fmin0=fsec1;fsec1=fsec0;fsec0=key();break;}}for(P1=0x0f;(P1==0x0f)&&(f<=6);j=0){if(++j<=f){display(0,fsec0);delayms(200);if(++j<=f){display(1,fsec1);delayms(200);if(++j<=f){display(2,fmin0);delayms(200);if(++j<=f){display(3,fmin1);delayms(200);if(++j<=f){display(4,fhour0);delayms(200);if(++j<=f){display(5,fhour1);delayms(200);}}}}}}}}}///********************************************************定时显示程序;void fixed_show(void){do{P1=0xef;display(5,t6);delayms(150);display(4,t5);delayms(150);display(3,t4);delayms(150);display(2,t3);delayms(150);display(1,t2);delayms(150);display(0,t1);delayms(150);}while(P1!=0xee);}//*****************************************星期设定程序;void week(void){delayms(5000);for(w=key();w>7||w<1;w=1);P1=0xdf;dodisplay(5,w);while(P1!=0xdb);P1=0xff;}//******************************************星期显示程序;void week_show(void){P1=0xdf;dodisplay(5,w);while(P1!=0xde);P1=0xff;}///*****************************************万年历显示程序;void calendar_show(void){do{display(4,year3);//年显示;delayms(150);display(3,year2);delayms(150);display(1,year1);delayms(150);display(0,year0);delayms(150);}while(P1!=0xbb);do{display(4,mouts1);//月日显示;delayms(150);display(3,mouts0);delayms(150);display(1,day1);delayms(150);display(0,day0);delayms(150);}while(P1!=0xbd);P1=0xff;}//*******************************************万年历设定程序;void calendar(void){P2=0xfe;P0=0x6e;do{}while(P1==0xbb);display(4,year3=key());//年设定;display(3,year2=key());display(1,year1=key());display(0,year0=key());do{P1=0xbf;}while(P1!=0xbd);P2=0xfe;P0=0x63;do{}while(P1==0xbd);//月日设定;display(4,mouts1=key());display(3,mouts0=key());if(mouts1*10+mouts0>12||mouts1*10+mouts0<1) {mouts1=0;mouts0=1;P2_7=0;delayms(1200);}P2_7=1;display(1,day1=key());display(0,day0=key());if(day1*10+day0>*p||day1*10+day0<1){day1=0;day0=1;P2_7=0;delayms(1200);}P2_7=1;do{P1=0xbf;}while(P1!=0xbe);P1=0xff;}。