基于51单片机的电子钟万年历农历数码管显示DS12C887时钟芯片

基于51单片机的DS12C887电子钟万年历( proteus仿真+程序+讲解视频)

仿真图proteus 7.8及以上

程序编译器:keil 4/keil 5

编程语言:C语言

设计编号:S0028

主要功能:

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

DS12C887时钟芯片,LED显示、独立键盘、农历显示、温度显示。

具体功能:

1、采用DS12C887记录日历和时间。

2、 通过数码管显示,可以显示新历年月日时分秒,农历和星期,带有温度显示。

3、可以按照实际,通过按键设置日期、时间。

资料下载链接(可点击):

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

以下为本设计资料展示图:

仿真图

主图

img

开始仿真

img

开始显示程序设置的初始时间,三组数码管分别显示年月日,时钟分钟秒、农历日期和温度。可以通过按键调整时间。

设置键按下第一下设置分钟,第二下设置时钟,第三下设置星期,第四下设置日期,第五下设置月份,第六下设置年份,第七下退出设置。通过按键DOWN和按键UP调整数值加减。如果已经调整好日期时间,按OUT按键可以退出设置。

程序(提供源文件源码):

img

img

ds12c887初始化和调用

#include "main.h"
#include "ds12c887.h"



void DS12C887_write(uchar add,uchar dat)  //写
{
	DS12C887_CS=0;
    DS12C887_AS=1;
	DS12C887_DS=1;
	DS12C887_WR=1;
	DS12C887_DATA=add;
	DS12C887_AS=0;
	DS12C887_WR=0;
	DS12C887_DATA=dat;
	DS12C887_WR=1;
	DS12C887_AS=1;
	DS12C887_CS=1;	
} 

uchar DS12C887_read(uchar add)	//读
{
	uchar ds_date;
	DS12C887_AS=1;
	DS12C887_DS=1;
	DS12C887_WR=1;
	DS12C887_CS=0;
	DS12C887_DATA=add;
	DS12C887_AS=0;
	DS12C887_DS=0;
	DS12C887_DATA=0xff;
	ds_date=DS12C887_DATA;
	DS12C887_DS=1;
	DS12C887_AS=1;
	DS12C887_CS=1;
	return ds_date;		
}

void DS12C887_Gettime()	   //获取DS12C887时间
{

	time_year  =DS12C887_read(0x09);	//年	
	time_month =DS12C887_read(0x08);	//月
	time_day  = DS12C887_read(0x07);	//日
	time_week  =DS12C887_read(0x06);	//周
	time_hour  =DS12C887_read(0x04);	//是
	time_min  = DS12C887_read(0x02);	//分
	time_sec =  DS12C887_read(0x00);	//秒
}

void DS12C887_Settime() ///设置初始时间
{
	DS12C887_write(0x09,0x16);	//年22	0x16->22
	DS12C887_write(0x08,0x0C);	//月12	0x0C->12
	DS12C887_write(0x07,0x0C);	//日11	0x0B->11
	DS12C887_write(0x06,0x01);	//周1	
	DS12C887_write(0x04,0x17);	//时23					 
	DS12C887_write(0x02,0x3B);	//分59
	DS12C887_write(0x00,0x32);	//秒50
}  

void DS12C887_init()	//DS12C887初始化
{
	DS12C887_write(0x0a,0x20); //DS12CR887寄存器A功能设置,开启时钟振荡器
	DS12C887_write(0x0b,0x06); //寄存器B功能设置,不开启闹钟中断使能,数据模式为二进制,24小时模式。		
} 		   

阴历计算

 /*
 函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)
 调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)
 如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);
 c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世
 纪,c_sun=1为19世纪
 调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据
 */
 
 /*子函数,用于读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0*/
// /* static*/ unsigned char /*bit*/ get_moon_day(uchar month_p,uint table_addr)
//   {
//   uchar temp;
//       switch (month_p){
//           case 1:{temp=year_code[table_addr]&0x08;
//                if (temp==0)return(0);else return(1);}
//           case 2:{temp=year_code[table_addr]&0x04;
//                if (temp==0)return(0);else return(1);}
//           case 3:{temp=year_code[table_addr]&0x02;
//                if (temp==0)return(0);else return(1);}
//           case 4:{temp=year_code[table_addr]&0x01;
//                if (temp==0)return(0);else return(1);}
//           case 5:{temp=year_code[table_addr+1]&0x80;
//                if (temp==0) return(0);else return(1);}
//           case 6:{temp=year_code[table_addr+1]&0x40;
//                if (temp==0)return(0);else return(1);}
//           case 7:{temp=year_code[table_addr+1]&0x20;
//                if (temp==0)return(0);else return(1);}
//           case 8:{temp=year_code[table_addr+1]&0x10;
//                if (temp==0)return(0);else return(1);}
//           case 9:{temp=year_code[table_addr+1]&0x08;
//                if (temp==0)return(0);else return(1);}
//           case 10:{temp=year_code[table_addr+1]&0x04;
//                if (temp==0)return(0);else return(1);}
//           case 11:{temp=year_code[table_addr+1]&0x02;
//                if (temp==0)return(0);else return(1);}
//           case 12:{temp=year_code[table_addr+1]&0x01;		  
//                if (temp==0)return(0);else return(1);}
//           case 13:{temp=year_code[table_addr+2]&0x80;
//                if (temp==0)return(0);else return(1);}
//       }
//	 return(0);
//   }


/*月份数据表-----------------------------------------------------------------------------*/
static unsigned char  code day_code1[9]={0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3};
static unsigned short code day_code2[3]={0x111,0x130,0x14e};

/*子函数,用于读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0------------------*/
static unsigned char get_moon_day(unsigned char month_p,unsigned short table_addr)
{
	switch (month_p)
	{
		case 1:
			if((year_code[table_addr]&0x08)==0)		return(0);
			else 									return(1); 
		case 2:
			if((year_code[table_addr]&0x04)==0)		return(0);
			else 									return(1);
		case 3:
			if((year_code[table_addr]&0x02)==0)		return(0);
			else 									return(1);
		case 4:
			if((year_code[table_addr]&0x01)==0)		return(0);
			else 								    return(1);
		case 5:
			if((year_code[table_addr+1]&0x80)==0)	return(0);
			else 									return(1);
		case 6:
			if((year_code[table_addr+1]&0x40)==0)	return(0);
			else 									return(1);
		case 7:
			if((year_code[table_addr+1]&0x20)==0)	return(0);
			else 									return(1);
		case 8:
			if((year_code[table_addr+1]&0x10)==0)	return(0);
			else 									return(1);
		case 9:
			if((year_code[table_addr+1]&0x08)==0)	return(0);
			else 									return(1);
		case 10:
			if((year_code[table_addr+1]&0x04)==0)	return(0);
			else 									return(1);
		case 11:
			if((year_code[table_addr+1]&0x02)==0)	return(0);
			else 									return(1);
		case 12:
			if((year_code[table_addr+1]&0x01)==0)	return(0);
			else 									return(1);
		case 13:
			if((year_code[table_addr+2]&0x80)==0)	return(0);
			else 									return(1);
	}
	return(0);
}



  /*
  函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)
  调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)
  如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);
  c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世
  纪,c_sun=1为19世纪
  调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据
  */

 void Conversion(bit c,uchar year,uchar month,uchar day)
 {                         //c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据
//     uchar c_moon,year_moon,month_moon,day_moon;
	 uchar temp1,temp2,temp3,month_p;
     uint temp4,table_addr;
     bit flag2,flag_y;
//     temp1=year/16;   //BCD->hex 先把数据转换为十六进制   这段要屏蔽掉,不然数码管显示乱码
//     temp2=year%16;
//     year=temp1*10+temp2;
//     temp1=month/16;
//     temp2=month%16;
//     month=temp1*10+temp2;
//     temp1=day/16;
//     temp2=day%16;
//     day=temp1*10+temp2;
     //定位数据表地址
   if(c==0)
  {                   
      table_addr=(year+0x64-1)*0x3;
  }
   else 
  {
     table_addr=(year-1)*0x3;
  }
     //定位数据表地址完成
     //取当年春节所在的公历月份
     temp1=year_code[table_addr+2]&0x60; 
     temp1=_cror_(temp1,5);
     //取当年春节所在的公历月份完成
     //取当年春节所在的公历日
     temp2=year_code[table_addr+2]&0x1f; 
     //取当年春节所在的公历日完成
     // 计算当年春年离当年元旦的天数,春节只会在公历1月或2月
     if(temp1==0x1)
  {  
         temp3=temp2-1;  
     }  
     else
  {
         temp3=temp2+0x1f-1;        
     }
     // 计算当年春年离当年元旦的天数完成
     //计算公历日离当年元旦的天数,为了减少运算,用了两个表
     //day_code1[9],day_code2[3]
     //如果公历月在九月或前,天数会少于0xff,用表day_code1[9],
     //在九月后,天数大于0xff,用表day_code2[3]
     //如输入公历日为8月10日,则公历日离元旦天数为day_code1[8-1]+10-1
     //如输入公历日为11月10日,则公历日离元旦天数为day_code2[11-10]+10-1
     if (month<10)
  { 
         temp4=day_code1[month-1]+day-1;
     }
     else
  {
         temp4=day_code2[month-10]+day-1;
     }
     
  if ((month>0x2)&&(year%0x4==0))
  {  
 //如果公历月大于2月并且该年的2月为闰月,天数加1
         temp4+=1;
     }
     //计算公历日离当年元旦的天数完成
     //判断公历日在春节前还是春节后
     if (temp4>=temp3){ //公历日在春节后或就是春节当日使用下面代码进行运算
         temp4-=temp3;
         month=0x1;
         month_p=0x1;  //month_p为月份指向,公历日在春节前或就是春节当日month_p指向首月
         flag2=get_moon_day(month_p,table_addr); 
 //检查该农历月为大小还是小月,大月返回1,小月返回0
         flag_y=0;
         if(flag2==0)temp1=0x1d; //小月29天
         else temp1=0x1e; //大小30天
         temp2=year_code[table_addr]&0xf0;
         temp2=_cror_(temp2,4);  //从数据表中取该年的闰月月份,如为0则该年无闰月
         while(temp4>=temp1){
             temp4-=temp1;
             month_p+=1;
             if(month==temp2){
             flag_y=~flag_y;
             if(flag_y==0)month+=1;
             }
             else month+=1;
             flag2=get_moon_day(month_p,table_addr);
             if(flag2==0)temp1=0x1d;
             else temp1=0x1e;
         }
         day=temp4+1;
     }
     else{  //公历日在春节前使用下面代码进行运算
         temp3-=temp4;
         if (year==0x0){year=0x63;c=1;}
         else year-=1;
         table_addr-=0x3;
         month=0xc;
         temp2=year_code[table_addr]&0xf0;
         temp2=_cror_(temp2,4);
         if (temp2==0)month_p=0xc; 
         else month_p=0xd; //
         /*
         month_p为月份指向,如果当年有闰月,一年有十三个月,月指向13,
 无闰月指向12
         */
         flag_y=0;
         flag2=get_moon_day(month_p,table_addr);
         if(flag2==0)temp1=0x1d;
         else temp1=0x1e;
         while(temp3>temp1){
             temp3-=temp1;
             month_p-=1;
             if(flag_y==0)month-=1;
             if(month==temp2)flag_y=~flag_y;
             flag2=get_moon_day(month_p,table_addr);
             if(flag2==0)temp1=0x1d;
             else temp1=0x1e;
          }
         day=temp1-temp3+1;
     }
//     c_moon=c;                 //HEX->BCD ,运算结束后,把数据转换为BCD数据
//     temp1=year/10;
//     temp1=_crol_(temp1,4);
//     temp2=year%10;
//     year_moon=temp1|temp2;
//     temp1=month/10;
//     temp1=_crol_(temp1,4);
//     temp2=month%10;
//     month_moon=temp1|temp2;
//     temp1=day/10;
//     temp1=_crol_(temp1,4);
//     temp2=day%10;
//     day_moon=temp1|temp2;


	c_moon=c;
	year_moon=year;
	month_moon=month;
	day_moon=day;


}

资料下载链接:

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
洛 阳 理 工 学 院 课 程 设 计 报 告 课程名称 单片机原理与应用   设计题目 基于STC89C51万年历的设计与实现 专 业 物联网工程       班 级 学 号 姓 名 完成日期 大约在冬季 "课 程 设 计 任 务 书 " "设计题目: 基于STC89C51万年历的设计与实现  " "设计内容与要求: " "设计内容 " "利用STC89C51单片机、专用时钟芯片DS1302、DS18B20数字温度采集器及1602 " "显示器件设计一个万年历,要求实现:(1)正确显示年月日,时分秒,星期 " "等信息;(2)显示环境温度;(3)具有闹功能,可以整点报时;(4)能 " "够通过按键调整时间和设置闹。 " "二、设计要求 " "1.分析系统功能,确定系统设计方案,掌握总体设计的方法与思路。 " "2.系统硬件设计,确定外设与单片机的硬件接口。掌握单片机系统外部接口的" "扩展设计方法。 " "3.系统软件设计,结合硬件设计,编写相应控制程序,并进行Protuse仿真执 " "行。 " "4.熟练掌握程序烧录及调试过程。 " "5.按照要求撰写课程设计论文。 " "指导教师: " "2019年 11 月 26 日 " "课 程 设 计 评 语 " " " " " " " "成绩: 指导教师:_______________ " "年 月 日 " 目录 摘 要 2 一、设计目标与内容 3 1.1设计目标 3 1.2 设计内容 3 1.3设计要求 3 1.4 本章小结 3 二、系统设计 3 2.1 电路设计框图 3 2.2 系统硬件概述 4 2.3 主要单元电路的设计 4 2.3.1 时钟电路模块的设计 4 2.3.2温度传感器电路设计 6 2.3.3显示模块的设计 8 2.4本章小结 8 三、系统的软件设计 9 3.1程序流程图 9 3.1.1 系统总流程图 9 3.1.2 温度程序流程图 9 3.1.3 DS1302时钟程序流程图 10 3.1.4 LCD显示程序流程图 11 3.2程序的设计 11 3.2.1 DS18B20测温程序 11 3.2.2 DS1302读写程序 13 3.2.3液晶显示程序 14 3.3本章小结 15 四、仿真与调试 15 4.1 Keil软件调试流程 15 4.2 Proteus软件运行流程 17 4.3本章小结 18 总结 18 基于STC89C51万年历的设计与实现 摘 要 古人依靠日冕、漏刻记录时间,而随着科技的发展,电子万年历已经成为日渐流行的 日常计时工具。 本文研究的万年历系统拟用STC89C52单片机控制,以DS1302时钟芯片计时、DS18B20 采集温度、1602液晶屏显示。系统主要由温度传感器电路,单片机控制电路,显示电路 以及校正电路四个模块组成。本文阐述了系统的硬件工作原理,所应用的各个接口模块 的功能以及其工作过程,论证了设计方案理论的可行性。系统程序采用C语言编写,经Ke il软件进行调试后在Proteus软件中进行仿真,可以显示年、月、日、星期、时、分、秒 和温度并具有校准功能和与即时时间同步的功能。 实验结果表明此万年历实现后具有读取方便、显示直观、功能多样、电路简洁等诸多 优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。 关键词:万年历 单片机 仿真 一、设计目标与内容 1.1设计目标 制作出可以检测温度并报警的的电子万年历。 1.2 设计内容 用keilC51编译程序。 用proteus仿真电路图。 将电路图使用万用板或其他电路板焊接实物图。 1.3设计要求 具备在液晶上显示年、月、日、星期、时、分、秒的功能。 具备年、月、日、星期、时、分、秒校准功能。 具有与即时时间同步的功能。 1.4 本章小结 通过设计程序,制作仿真,焊接实物三个步骤,以小组合作的方式来设计满足设计要 求的万年历并简单描述可以实现的功能,制作结束后,进行课程设计答辩并编写一份课 程设计报告。 二、系统设计 1. 2. 2.1 电路设计框图 根据上章确定的方案给出了系统整体的设计框图: 图1.1系统结构框图 为使时钟走时与标准时间一致,校时电路是必不可少的,键盘模块用来校正液晶上显 示的时间;温度传感器则用来检测当前的环境温度;STC89C52单片机通过输出各种电脉 冲信号来驱动控制各部分正常工作;而系统的时间、温度等数据则最终通过液晶模块显 示出来。 2.2 系统硬件概述 本电路是以STC89C52单片机为控制核心,该芯片具有在线编程功能,功耗低,能在3 .3V的超低压下工作;时钟芯片采用DS1302,它是一款高性能、低功耗、自带RAM的实时 时钟芯片,具有使用寿命长,精度高和功耗低等特点,同时具有掉电自动保存功能,可以 对年、月、日、星期、时、分、秒进行计时,具有

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值