AT89C51数字电子时钟和proteus仿真(74HC573)

概要

`主控芯片为AT89C51,锁存器74HC573控制数码管点亮。
(注:免费源码链接,请点赞关注私信)

使用流程

开启仿真按下按键5显示时间,按键5可选择修改时间模式增,减,闹钟模式。按键1,2,3为修改时间,闹钟定时精度为分钟。

在这里插入图片描述

程序设计

#include<regx52.h>
#include"BUZZER.h"
#include"Key.h"
#include"Delay.h"
void _yuanze();
void _shu_ma_guan();
                //自定义时间初始量
#define S  13
#define F  57
#define M  58
#define N  2    //闹钟响铃时长
sbit duan=P2^0; //段选
sbit wei=P2^1;  //位选
sbit K1=P2^3;   //按键1   小时自增   
sbit K2=P2^4;   //按键2   分钟自增
sbit K3=P2^5;   //按键3   秒自增
sbit K4=P2^6;   //按键4   时间暂停
sbit BUZZER=P2^7;
sbit K5=P3^2;   //按键5显示 闹钟/时间

//段选的断码数码管显示的数字     0    1    2    3    4    5    6    7    8    9
           unsigned duan_[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
          
					 unsigned gong_neng[]={0xff,0xfe,0xfd,0xfb};
						 
					 unsigned  int miao=M,fen=F,shi=S,Keynum;
					 
					 unsigned int a=0,x,y;
	//闹钟提示音				 
void nao_z()
{
	 
		if(shi==x && fen==y && miao<=N)
		{
			BUZZER=1;
			BUZZER=0;
		}
		
		else
			BUZZER=1;
		
}

 //按键控制 自增函数
void yuanze()  
{
		Keynum=Key();   //接引按键扫描模块“Key.c”函数的返回值Keynumber
	
		//通过分支语句对不同按键对 秒K1, 分K2, 时K3, 启动计时器K1, 关闭计时器K4 实行调节
		switch(Keynum)
		{
			case 3:miao++;Keynum=0;if (miao>=60) miao=0;break ;
			case 2:fen++;Keynum=0;if (fen>=60) fen=0;break;
			case 1:shi++;Keynum=0;if (shi>=24) shi=0;break;
		  case 4:Keynum=0;TR0=~TR0;break;    //按键K4,停止定时器,启动定时器
		}
		
}


//按键控制自减函数
void yuanze1()  
{
		Keynum=Key();   //接引按键扫描模块“Key.c”函数的返回值Keynumber
	
		//通过分支语句对不同按键对 秒K1, 分K2, 时K3, 启动计时器K1, 关闭计时器K4 实行调节
		switch(Keynum)
		{
			case 3:miao--;Keynum=0;if (miao<=0) miao=59;break ;
			case 2:fen--;Keynum=0;if (fen<=0) fen=59;break;
			case 1:shi--;Keynum=0;if (shi<=0) shi=23;break;
		  case 4:TR0=~TR0;break;    //按键K4,停止定时器,启动定时器
		}
		
}
unsigned int shi_=S,fen_=F-3,miao_,Keynum_;
      //数码管,显示。
			void shu_ma_guan()
			{										
         //位选读入数据/第一个数码管/锁存数据 /段选读入数据/小时的十位/锁存数据/防止篡位 /消影 
					wei=1;P0=0xfe;wei=0;  duan=1;if(a==3)P0=duan_[shi_/10];else P0=duan_[shi/10];duan=0;Delay(1);P0=0xff;            

                                                                            				//小时的个位
					wei=1;P0=0xfd;wei=0;  duan=1;if(a==3)P0=duan_[shi_%10];else P0=duan_[shi%10];duan=0;Delay(1);P0=0xff;
					
																																										//分隔符
					wei=1;P0=0xfb;wei=0;  duan=1;P0=0x40;duan=0;Delay(1);P0=0xff;
						
																																										//分的十位
					wei=1;P0=0xf7;wei=0;  duan=1;if(a==3)P0=duan_[fen_/10];else P0=duan_[fen/10];duan=0;Delay(1);P0=0xff;
				
																																										//分的个位
					wei=1;P0=0xef;wei=0;	duan=1;if(a==3)P0=duan_[fen_%10];else P0=duan_[fen%10];duan=0;Delay(1);P0=0xff;
				
																																										//分隔符
					wei=1;P0=0xdf;wei=0;  duan=1;P0=0x40;duan=0;Delay(1);P0=0xff;
					
																																										//秒的十位
					wei=1;P0=0xbf;wei=0;	duan=1;if(a==3)P0=duan_[miao_/10];else P0=duan_[miao/10];duan=0;Delay(1);P0=0xff;
					
																																										//秒的个位
					wei=1;P0=0x7f;wei=0;  duan=1;if(a==3)P0=duan_[miao_%10];else P0=duan_[miao%10];duan=0;Delay(1);P0=0xff;
			}



void main()
{
	
		TMOD=0x01;       //选择定时器工作模式T0  0000 0001
			                   
		TH0=(65535-50000)/256;        //高位寄存器== TH0=15535/256;//65535-50000=50000us=50ms		
		
		TL0=(65535-50000)%256;        //低位寄存器== TL0=15535%256;

		//中断系统	
		EA=1;            //总中断开关
		ET0=1;           //中断允许控制位   计数器T0溢出中断允许控制位
		TF0=0;           //中断请求位
    //外部中断
	  EX0=1;
	  IT0=1;
		while(1)
		{
		
			nao_z();
			if(a==1){yuanze();shu_ma_guan();}	        //按键控制自增模式
			if(a==2){yuanze1();shu_ma_guan();}        //按键控制自减函数
			if(a==3){_yuanze();shu_ma_guan();}       //按键闹钟定时模式
		}
		
}

//中断服务子程序            定时器0
void Timer1_Routine() interrupt 1
{		 
		static unsigned int n;//静态储存
		
	//进行中断重新赋值,下次运行也为1ms
		TR0=1;
		TH0=(65535-50000)/256;          //高位寄存器
		TL0=(65535-50000)%256;          //低位寄存器
		n++;
		if(n>=20)        //每隔一秒运行
		{
			n=0;
			miao++;              //秒自增
		
			if(miao>=60)         //秒为60,秒清零,分自增1
			{			
				miao=0;
				fen++;
						
				if(fen>=60)        //分为60,分清零,小时自增1
				{
					
					fen=0;
					shi++;
					Buzzer_Time(100);  //整点提醒蜂鸣器工作
			
					if(shi>=24)        //小时为24时,小时清零
					{
						shi=0;
					
				 }
				}
			}
	
		}
		
} 
//中断服务程序          外部中断0
void Init0_Routine() interrupt 0
{
	++a;	
	if(a>=4) a=1;
	P1=gong_neng[a];
}


//unsigned int shi_=S,fen_=F-3,miao_,Keynum_;

 //按键控制闹钟 自增函数
void _yuanze()  
{
		Keynum_=Key();   //接引按键扫描模块“Key.c”函数的返回值Keynumber
	
		//通过分支语句对不同按键对 秒K1, 分K2, 时K3, 启动计时器K1, 关闭计时器K4 实行调节
		switch(Keynum_)
		{
			
			case 2:fen_++;Keynum_=0;if (fen_>=60) fen_=0;break;
			case 1:shi_++;Keynum_=0;if (shi_>=24) shi_=0;break;
		
		}
	    x=shi_;y=fen_;	
}

小结

本章节就到此结束了,需要下载资源的话点击这里AT89C51数字时钟后期还会分享相关学习可以关注一下博主,让我们一起学习成长。

准确延时,数码管显示!用于电子时钟 #include <reg51.h> //*** 函数定义 *** void long_delay(void); // 长延时 void short_delay(void); // 短延时 void delay10ms(unsigned char); // 延时10MS void write7279(unsigned char, unsigned char);// 写入到HD7279 unsigned char read7279(unsigned char);//从HD7279读入 void send_byte(unsigned char); // 发送一个字节 unsigned char receive_byte(void); //接收一个字节 void init_timer(); /*定时器T0初始化*/ void conv(); /*时、分、秒单元及走时单元转换*/ void dirve(); /*时间显示程序*/ void time_adj(); /*时间调整设置*/ unsigned char digit[6]; unsigned char j; unsigned int tmr; unsigned long wait_cnter; unsigned char hour=0,min=0,sec=0; /*时、分、秒单元清零*/ unsigned char deda=0; /*5mS计数单元清零*/ bit sign; //设置标志位 sbit cs=P1^5; // cs at P1.5 sbit clk=P1^4; // clk 连接于 P1.4 sbit dat=P1^3; // dat 连接于 P1.3 sbit set=P3^7; // key 连接于 P3.7 //****** HD7279A 指令 ****** #define CMD_RESET 0xa4 #define CMD_TEST 0xbf #define DECODE0 0x80 #define DECODE1 0xc8 #define CMD_READ 0x15 #define UNDECODE 0x90 #define RTL_CYCLE 0xa3 #define RTR_CYCLE 0xa2 #define RTL_UNCYL 0xa1 #define RTR_UNCYL 0xa0 #define ACTCTL 0x98 #define SEGON 0xe0 #define SEGOFF 0xc0 #define BLINKCTL 0x88 //*** 主函数 *** main() { for (tmr=0;tmr<0x2000;tmr++); // 上电延时 send_byte(CMD_RESET); // 复位HD7279A //****************************************** // 测试指令演示 //****************************************** send_byte(CMD_TEST); // 指令测试 for (j=0;j<3;j++) // 延时哟3秒? { delay10ms(100); } send_byte(CMD_RESET); // 清除显示 //********************************************** //时间显示 //********************************************** init_timer();/*定时器T0初始化*/ while(1) { if(set==0) time_adj(); conv(); /*时、分、秒单元及走时单元转换*/ dirve(); /*时、分、秒单元显示*/ } } /*定时器T0 5mS初始化*/ void init_timer() { TMOD=0x01; TH0=-(4800/256); TL0=-(4800%256); IE=0x82; TR0=1; } /*5mS定时中断服务子函数*/ void zd(void) interrupt 1 { TH0=-(4800/256); TL0=-(4800%256); deda++; } /*时、分、秒单元及走时单元转换*/ void conv() { if(deda>=200){sec++;deda=0;} if(sec==60){min++;sec=0;} if(min==60){hour++;min=0;} if(hour==24){hour=0;} } void dirve() { digit[0]=sec%10; //计数个位 write7279(DECODE0,digit[0]); //显示个位 digit[1]=0x80|(sec/10); //计数十位 write7279(DECODE0+1,digit[1]); //显示十位 digit[2]=0x80|(min%10); //计数百位 write7279(DECODE0+2,digit[2]); //显示百位 digit[3]=0x80|(min/10); //计数千位 write7279(DECODE0+3,digit[3]); //显示千位 digit[4]=0x80|(hour%10); //计数万位 write7279(DECODE0+4,digit[4]); //显示万位 digit[5]=hour/10; //计数十万位 write7279(DECODE0+5,digit[5]); } void write7279(unsigned char cmd, unsigned char dta) { send_byte (cmd); send_byte (dta); } unsigned char read7279(unsigned char command) { send_byte(command); return(receive_byte()); } void send_byte( unsigned char out_byte) { unsigned char i; cs=0; long_delay(); for (i=0;i<8;i++) { if (out_byte&0x80) { dat=1; } else { dat=0; } clk=1; short_delay(); clk=0; short_delay(); out_byte=out_byte*2; } dat=0; } unsigned char receive_byte(void) { unsigned char i, in_byte; dat=1; // 设置为输入状态 long_delay(); for (i=0;i<8;i++) { clk=1; short_delay(); in_byte=in_byte*2; if (dat) { in_byte=in_byte|0x01; } clk=0; short_delay(); } dat=0; return (in_byte); } void long_delay(void) { unsigned char i; for (i=0;i<0x30;i++); } void short_delay(void) { unsigned char i; for (i=0;i<8;i++); } // ********************* 延时 n*10ms ********************** void delay10ms(unsigned char time) { unsigned char i; unsigned int j; for (i=0;i<time;i++) { for(j=0;j<0x390;j++) { } } } /*时间调整程序*/ void time_adj() { if(set==0) //有键按下,判断按键时间 { delay10ms(200); //1s延时程序 if(set==0) //大于1s,进入时间设置 { ET0=0; TR0=0; //关定时器0 while(set==0) dirve(); //等键释放 // ET1=1;TR1=1; con=0xF3; //开定时器1,让调整位闪烁 write7279(BLINKCTL,0xF3); do { while(set!=0) dirve(); //等待按键 delay10ms(100); if(set!=0) //小于0.5s,进入分钟设置 { while(set==0) dirve(); //等待按键释放 sign=1; min++; if(min==60)min=0; //分钟加1 dirve(); } else sign=0; //大于0.5s,进入小时设置 }while(sign); while(set==0)dirve(); //等待按键释放 // con=0xCF; write7279(BLINKCTL,0xCF); do { while(set!=0) dirve(); //等待按键 delay10ms(100); if(set!=0) //小于0.5s,进入小时设置 { while(set==0) dirve(); //等待按键释放 sign=1; hour++; //小时加1 if(hour==24)hour=0; dirve(); } else sign=0; //大于0.5s,结束时间设置 }while(sign); // ET1=0;TR1=0; //关定时器1 ET0=1;TR0=1; //开定时器0 write7279(BLINKCTL,0xFF); } else //小于1s,进入省电模式 { ET0=1; TR0=1; //开定时器0 while(set!=0); //等待按键 do { dirve(); //有键按下,调显示程序消抖 }while(set!=0); //是干扰则继续循环 } while(set==0) dirve(); //等待按键释放 } else ; //无键按下,跳出按键扫描程序 }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜·き

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值