AT89C51单片机万年历LCD显示实现日期时间温度闹钟功能详解

一.设计功能

1、实现日历功能,显示年月日时分秒
2、测量温度并显示
3、具有闹钟功能,可设置闹钟时间
4、温度超过上下限则启动报警
5、使用存储器芯片存储系统参数,掉电保存

二、程序流程图

三、仿真

日期 星期 时间 当前温度

下一页
闹钟时间 温度上限 温度下限

四、相关程序

sbit beep=P2^7;//蜂鸣器
sbit k1=P3^2;
sbit k2=P3^3;
sbit k3=P3^4;
sbit k4=P3^5;
//-----------------------------------显示数组
uchar ye=0;//第一页
uchar hang1[]="2000.00.00  0   ";//日期+星期
uchar hang2[]="00:00:00 T:000 C";//时间+温度
uchar hang3[]="lock 00:00      ";//第二页	  闹钟
uchar hang4[]="L:000 C  H:000 C";//温度阀值
uchar lcd_xian=0;//显示延时变量
//-----------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>光标位置
uchar cursor=0;//光标位置
uchar code cursor_num[]={1,3,1,6,1,9,1,12,2,1,2,4,2,7,1,6,1,9,2,4,2,13};//光标位置数组.行+列
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//###################################测量值变量
uchar wendu=0,wen_L=10,wen_H=30;//温度+阀值
uchar shi=6,fen=0;//闹钟
//###################################
//**************************************主函数
void main()
{
uchar two;
//11111111111111111111111111111111基本模块初始化
	hang2[14]=0xdf;
	hang4[5]=0xdf;
	hang4[14]=0xdf;
	init_1602();
	Ds1302ReadTime();//启动DS1302
	TIME[0]=0;
	Ds1302Init();
//11111111111111111111111111111111
//22222222222222222222222222222222显示初始化
	wen_L=At24c02Read(0); //读取温度阀值
	if(wen_L>200)
	{
		wen_L=10;
		At24c02Write(0,wen_L);
		Delay1ms(10);
	}
	wen_H=At24c02Read(1);
	if(wen_H>200)
	{
		wen_H=10;
		At24c02Write(1,wen_H);
		Delay1ms(30);
	}
	shi=At24c02Read(2);
	if(shi>200)
	{
		shi=6;
		At24c02Write(2,shi);
		Delay1ms(10);
	}
	fen=At24c02Read(3);
	if(fen>200)
	{
		fen=0;
		At24c02Write(3,fen);
		Delay1ms(10);
	}
//22222222222222222222222222222222
//===============定时器初始化
	TMOD|=0X01;
	TH0=0X3C;
	TL0=0XB0;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器
//===============
	while(1)
	{
		//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;判断报警
		if((wendu>wen_H)||(wendu<wen_L)||((TIME[2]==shi)&&(TIME[1]==fen)))//蜂鸣器判断
			beep=0;
		else
			beep=1;
		//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		//'''''''''''''''''''''''''''''''''''''''''''按键检测
		if(!k1)	//换页
		{
			ye=!ye;
			if(ye)
				cursor=7;//设置光标
			else
				cursor=0;
			while(!k1);
		}
		if(!k2)	   //下一个
		{
			if(ye)
			{
				if(cursor<10)
					cursor++;
				else
					cursor=7;
			}
			else
			{
				if(cursor<6)
					cursor++;
				else
					cursor=0;
			}
			while(!k2);
		}
			
			if(!k3)//加
			{
				switch(cursor)
				{
					case 0://设置年
						two=(TIME[6]>>4)*10+(TIME[6] &0x0f);
						if(two<99)
							two++;
						TIME[6]=(two/10<<4)+two%10;
						Ds1302Init();
					    break;
					case 1://设置月
						two=(TIME[4]>>4)*10+(TIME[4] &0x0f);
						if(two<12)
							two++;
						TIME[4]=(two/10<<4)+two%10;
						Ds1302Init();
						break;
					case 2://设置日
						two=(TIME[3]>>4)*10+(TIME[3] &0x0f);
						if(two<30)
							two++;
						TIME[3]=(two/10<<4)+two%10;
						Ds1302Init();
						break;
					case 3://设置星期
						if(TIME[5]<8)
							TIME[5]++;
						Ds1302Init();
					    break;
					case 4://设置时
						two=(TIME[2]>>4)*10+(TIME[2] &0x0f);
						if(two<23)
							two++;
						TIME[2]=(two/10<<4)+two%10;
						Ds1302Init();
					    break;
					case 5://设置分
						two=(TIME[1]>>4)*10+(TIME[1] &0x0f);
						if(two<59)
							two++;
						TIME[1]=(two/10<<4)+two%10;
						Ds1302Init();
						break;
					case 6://设置秒
						two=(TIME[0]>>4)*10+(TIME[0] &0x0f);
						if(two<59)
							two++;
						TIME[0]=(two/10<<4)+two%10;
						Ds1302Init();
						break;
					case 7://设置时	闹钟
						two=(shi>>4)*10+(shi &0x0f);
						if(two<23)
							two++;
						shi=(two/10<<4)+two%10;
						At24c02Write(2,shi);
						Delay1ms(10);
					    break;
					case 8://设置分
						two=(fen>>4)*10+(fen &0x0f);
						if(two<59)
							two++;
						fen=(two/10<<4)+two%10;
						At24c02Write(3,fen);
						Delay1ms(10);
						break;
					case 9://设置温度低阀值
						if(wen_L<100)
							wen_L++;
						At24c02Write(0,wen_L);
						Delay1ms(10);
					    break;
					case 10://设置温度高阀值
						if(wen_H<100)
							wen_H++;
						At24c02Write(1,wen_H);
						Delay1ms(10);
				}
				while(!k3);
			}
			if(!k4)//减
			{
				switch(cursor)
				{
					case 0://设置年
						two=(TIME[6]>>4)*10+(TIME[6] &0x0f);
						if(two>0)
							two--;
						TIME[6]=(two/10<<4)+two%10;
						Ds1302Init();
					    break;
					case 1://设置月
						two=(TIME[4]>>4)*10+(TIME[4] &0x0f);
						if(two>1)
							two--;
						TIME[4]=(two/10<<4)+two%10;
						Ds1302Init();
						break;
					case 2://设置日
						two=(TIME[3]>>4)*10+(TIME[3] &0x0f);
						if(two>1)
							two--;
						TIME[3]=(two/10<<4)+two%10;
						Ds1302Init();
						break;
					case 3://设置星期
						if(TIME[5]>2)
							TIME[5]--;
						Ds1302Init();
					    break;
					case 4://设置时
						two=(TIME[2]>>4)*10+(TIME[2] &0x0f);
						if(two>0)
							two--;
						TIME[2]=(two/10<<4)+two%10;
						Ds1302Init();
					    break;
					case 5://设置分
						two=(TIME[1]>>4)*10+(TIME[1] &0x0f);
						if(two>0)
							two--;
						TIME[1]=(two/10<<4)+two%10;
						Ds1302Init();
						break;
					case 6://设置秒
						two=(TIME[0]>>4)*10+(TIME[0] &0x0f);
						if(two>0)
							two--;
						TIME[0]=(two/10<<4)+two%10;
						Ds1302Init();
						break;
					case 7://设置时	闹钟
						two=(shi>>4)*10+(shi &0x0f);
						if(two>0)
							two--;
						shi=(two/10<<4)+two%10;
						At24c02Write(2,shi);
						Delay1ms(10);
					    break;
					case 8://设置分
						two=(fen>>4)*10+(fen &0x0f);
						if(two>0)
							two--;
						fen=(two/10<<4)+two%10;
						At24c02Write(3,fen);
						Delay1ms(10);
						break;
					case 9://设置温度低阀值
						if(wen_L>0)
							wen_L--;
						At24c02Write(0,wen_L);
						Delay1ms(10);
					    break;
					case 10://设置温度高阀值
						if(wen_H>0)
							wen_H--;
						At24c02Write(1,wen_H);
						Delay1ms(10);
				}
				while(!k4);
		}
		//''''''''''''''''''''''''''''''''''''''''''''	
	}
}
//*******************************************
//-----------------------------------------显示
void Timer0() interrupt 1
{
	if(lcd_xian<5)
		lcd_xian++;
	else
	{
		lcd_xian=0;
		//==============================显示计算
		//()()()()()()()()测量
		wendu=Ds18b20ReadTemp();//温度
		Ds1302ReadTime();//读取时间
		//()()()()()()()()
		hang1[2]=(TIME[6]>>4)+0X30;	//年
		hang1[3]=(TIME[6]& 0X0F)+0X30;
		hang1[5]=(TIME[4]>>4)+0X30;	//月
		hang1[6]=(TIME[4]& 0X0F)+0X30;
		hang1[8]=(TIME[3]>>4)+0X30;	//日
		hang1[9]=(TIME[3]& 0X0F)+0X30;
		hang1[12]=TIME[5]+0X2f;	//星期
		hang2[0]=(TIME[2]>>4)+0X30;	//时
		hang2[1]=(TIME[2]& 0X0F)+0X30;
		hang2[3]=(TIME[1]>>4)+0X30;	//分
		hang2[4]=(TIME[1]& 0X0F)+0X30;
		hang2[6]=(TIME[0]>>4)+0X30;//秒
		hang2[7]=(TIME[0]& 0X0F)+0X30;
		hang2[11]=wendu/100+0x30;//温度
		hang2[12]=wendu%100/10+0x30;
		hang2[13]=wendu%10+0x30;
		//阀值显示计算
		hang3[5]=(shi>>4)+0x30;//时	 闹钟
		hang3[6]=(shi &0x0f)+0x30;
		hang3[8]=(fen>>4)+0x30;//分
		hang3[9]=(fen &0x0f)+0x30;
		hang4[2]=wen_L/100+0x30;//温度低
		hang4[3]=wen_L%100/10+0x30;
		hang4[4]=wen_L%10+0x30;
		hang4[11]=wen_H/100+0x30;//温度高
		hang4[12]=wen_H%100/10+0x30;
		hang4[13]=wen_H%10+0x30;
		//===============================
		//+++++++++++++++++++++++++++++++显示
		write_com(0x0c);
		if(ye==0)
		{
			write_string(1,0,hang1);//显示第一页
			write_string(2,0,hang2);
		}
		else
		{
			write_string(1,0,hang3);//显示第二页
			write_string(2,0,hang4);
		}
		write_com(0x0e);
		write_sfm(cursor_num[2*cursor],cursor_num[2*cursor+1]);//设置光标位置		
		//+++++++++++++++++++++++++++++++
	}
	TH0=0X3C;//给定时器赋初值,定时50ms
	TL0=0XB0;
}
物联沃分享整理
物联沃-IOTWORD物联网 » AT89C51单片机万年历LCD显示实现日期时间温度闹钟功能详解

发表评论