基于51单片机的数字电子钟万年历闰年判断闹钟设计

视频

1 开发环境

仿真图:proteus8.9以上

程序代码:KEIL4/KEIL5

原理图:AD

设计编号:A0009

2 功能说明介绍

结合实际情况,基于51单片机设计一个电子钟万年历闹钟设计。该系统应满足的功能要求为:

功能:

由51单片机、DS1302时钟芯片、按键模块、LCD1602显示、电源构成。

1、可以显示年、月、日、时、分、秒、星期、农历;

2、按键可以设置闹钟及报警;

3、按键可以调整时间,显示是平年还是闰年。

4、共4个按键可以实现设置时间/闹钟、时间加、时间减、设置切换。

3 仿真图

AT89C51可以替换为AT89C52,实物可以换做STC89C51,STC89C52

AT89C51是美国ATMEL公司生产的低电压,高性能CMOS16位单片机,片内含4k bytes的可反复擦写的只读程序存储器和128 bytes的随机存取数据存储器,期间采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用16位中央处理器和Flash存储单元,功能强大的AT89C51单片机可灵活应用于各种控制领域。

AT89C51提供以下标准功能:4k字节Flash闪速存储器,128字节内部RAM,32个I/O口线,两个1 6位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。

本系统中央控制器采用的AT89C51单片机,复位电路采用上电复位电路。外接的晶振为12MHz晶振。

img

闰年平年显示

img

4 程序

工程文件使用Keil4/keil5打开。编译产生hex加载到对应的单片机中。实物代码和仿真代码略有不同。分别的工程文件。

img

部分代码

//*******************主函数**************************
//***************************************************
void main()
{
	init_eeprom();  //开始初始化保存的数据
	P1=0xff;
//	delay(2000);
	lcd_init();      //调用液晶屏初始化子函数
	ds1302_init();   //调用DS1302时钟的初始化子函数
	init();          //调用定时计数器的设置子函数
	led1=0;           //打开LCD的背光电源
    buzzer=0;		 //蜂鸣器长响一次
    delay(100);
    buzzer=1;
	init_eeprom();
	while(1)  //无限循环下面的语句:
	{		
   	 	keyscan();      //调用键盘扫描子函数
		led=led1;		
		if(timerOn==1)
			alarm();	//闹钟输出
		if((fen==0)&&(miao==0))
		{
			if(shi>12)
				temp_hour=shi-12;
			else
			{
				if(shi==0)
					temp_hour=12;
				else
					temp_hour=shi;
			}
			shangyimiao=miao;
			baoshi=1;
		}
		if(baoshi==1)
		{
			ZD_baoshi();
			do 
				keyscan();
			while(shangyimiao==miao);	
			shangyimiao=miao;
		}
    }
}
void timer0() interrupt 1  //取得并显示日历和时间
{
  //读取秒时分周日月年七个数据(DS1302的读寄存器与写寄存器不一样):
	
  miao = BCD_Decimal(read_1302(0x81));
	fen = BCD_Decimal(read_1302(0x83));
	shi  = BCD_Decimal(read_1302(0x85));
	ri  = BCD_Decimal(read_1302(0x87));
	yue = BCD_Decimal(read_1302(0x89));
	nian=BCD_Decimal(read_1302(0x8d));
	//week=BCD_Decimal(read_1302(0x8b));     //不读取,直接通过日期计算得到
	if((led1==0))
	{
		if(temp_miao!=miao)
		{
			temp_miao=miao;
			bltime++;
		}
		if(bltime==10)
		{
			led1=1;
			bltime=0;
		}
	}
    if(T_NL_NZ==1)							//显示农历
	{
		uint nian_temp,temp12;
		temp12=nian;
		nian_temp=2000+(temp12&0xF0)*10+temp12&0x0F;
		if((nian_temp%400==0)||((nian_temp%100!=0)&&(nian_temp%4==0)))  //判断是否为闰年
			p_r=1;
		else
			p_r=0;
		Conversion(0,nian,yue,ri);
		write_1602com(er);//时间显示固定符号写入位置?
		for(a=0;a<16;a++)
		{
			if(p_r==0)
				write_1602dat(nlp[a]);//写显示时间固定符号,两个冒号
			else 
				write_1602dat(nlr[a]);
		}

	  write_nl(3,year_moon);//农历 年
		write_nl(6,month_moon);//农历 月
		write_nl(9,day_moon);//农历 日

		do
			keyscan();
		while(T_NL_NZ==1);

		write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示
		for(a=0;a<16;a++)
		{
			write_1602dat(qk[a]);//写显示时间固定符号,两个冒号
		}

		write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示
		for(a=0;a<8;a++)
		{
			write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号
		}
	}

	if(T_NL_NZ==2)								//显示闹钟时间,
	{
		write_1602com(er);//时间显示固定符号写入位置?
		for(a=0;a<16;a++)
			write_1602dat(NZd[a]);//写显示时间固定符号,两个冒号
		write_sfm(7,nz_shi);//农历 年
		write_sfm(10,nz_fen);//农历 月
		write_1602com(er+13);
		if(timerOn==1)
		{
			write_1602dat('O');
			write_1602dat('N');
			write_1602dat(' ');
		}
		else
		{
			write_1602dat('O');
			write_1602dat('F');
			write_1602dat('F');
		}

		do
			keyscan();
		while(T_NL_NZ==2);

		write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示
		for(a=0;a<16;a++)
		{
			write_1602dat(qk[a]);//写显示时间固定符号,两个冒号
		}

		write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示
		for(a=0;a<8;a++)
		{
			write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号
		}
	}
	
	else
	{	
			/*write_1602com(er+12);
			for(a=0;a<4;a++)
			{
				write_1602dat(tm[a]);
			}*/
	  write_sfm(6,miao);//秒,从第二行第8个字后开始显示(调用时分秒显示子函数)
		write_sfm(3,fen);//分,从第二行第5个字符后开始显示
		write_sfm(0,shi);//小时,从第二行第2个字符后开始显示
	}	
		//显示日、月、年数据:
		write_nyr(9,ri);//日期,从第二行第9个字符后开始显示
	  write_nyr(6,yue);//月份,从第二行第6个字符后开始显示
		write_nyr(3,nian);//年,从第二行第3个字符后开始显示
		Conver_week(nian,yue,ri);
		write_week(week);
}


unsigned char count1;

void timer1() interrupt 3  //取得并显示日历和时间
{
	TH1=0x3C;
	TL1=0xB0;
//	TR1=1;
	count1++;
	if(count1==10)
	{
		count1=0;
		buzzer=!buzzer;
	}
}

流程如下所示。

主程序开始初始化,并打开中断,然后执行扫描闹钟、键盘及读取18B20值。当有S1键按下时,执行时钟设置,当有S4键按下时,则进入闹钟设置,无论是时钟还是闹钟,设置完后退出,时钟恢复实时显示。

5 原理图

原理图由AD绘制,原理图和仿真图有出入,原理图需要电源,电源开关模块。此设计资料详细,硬件手册资料图片详细,不对硬件调试负责,做实物需要一定的基本功。主控芯片可以换为STC89C51/STC89C52

img

由51单片机、DS1302时钟芯片、按键模块、LCD1602显示、电源构成。

本文是以实时时钟芯片DS1302和AT89C52单片机为主要研究对象,着重进行51单片机控制系统的设计研究和如何读取DS1302内部时钟信息的研究。主要内容包括:

年月日星期时分秒显示;

年月日星期时分秒调整;

闹钟定时小时分钟和秒;

img

6 视频讲解

代码讲解+仿真讲解+仿真演示+原理图讲解

7 设计报告

在现实我们生活中每个人都可能有自己的时钟,光阴在永不停息的流逝,有了时钟人们就能随着时间有计划的过着每一天。然而现在绝大部分的时钟有的需要不断地跟换电池,有些时钟需要外接电源,如果一旦电池没电或者外接电源无法供电,时钟就会停止计时了。而美国DALLAS 公司的新型时钟日历芯片DS1302就能解决这一问题。该器件能提供实时时钟(RTC)/日历、定时闹钟。少于31天的月份,月末日期可自动调整,其中包括闰年补偿。该器件还可以工作于24小时货代/PM指示的12小时格式。

本时钟还具有环保、走时无噪音、低功耗等非实时时钟不具有的功能。该实时时钟不但可以作为家用,而且更可以在公共场合使用,如车站、码头、商场等场所。

7.1 设计目的

本文是以实时时钟芯片DS1302和AT89C52单片机为主要研究对象,着重进行51单片机控制系统的设计研究和如何读取DS1302内部时钟信息的研究。主要内容包括:

年月日星期时分秒显示;

年月日星期时分秒调整;

闹钟定时小时分钟和秒;

7.2 概述

采用AT89C52作为主控单片机,时钟模块选用DS1302作为时钟芯片,显示模块选用LCD1602,设置部分选用按键电路。

AT89C52与MCS-51单片机产品兼容 、8K字节在系统可编程Flash存储器、 1000次擦写周期、 全静态操作:0Hz~33Hz 、 三级加密程序存储器 、 32个可编程I/O口线 、三个16位定时器/计数器 八个中断源 、全双工UART串行通道、 低功耗空闲和掉电模式 、掉电后中断可唤醒 、看门狗定时器 、双数据指针 、掉电标识符 。

DS1302 实时时钟芯片功能丰富,可以用来直接代替IBM PC 上的时钟日历芯片DS12887,同时,它的管脚也和MC146818B、DS12887 相兼容。由于DS1302 能够自动产生世纪、年、月、日、时、分、秒等时间信息,其内部又增加了世纪寄存器,从而利用硬件电路解决子“千年”问题;DS1302 中自带有锂电池,外部掉电时,其内部时间信息还能够保持10 年之久;对于一天内的时间记录,有12 小时制和24 小时制两种模式。用户还可对DS1302 进行编程以实现多种方波输出,并可对其内部的三路中断通过软件进行屏蔽。

img

8 资料清单下载链接

见文章开头视频或下方链接

img

本资料下载链接:

https://docs.qq.com/doc/DTlpoam5sYWl5aFh1

猜你喜欢

转载自blog.csdn.net/Jack_0220/article/details/128877699