⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 基于液晶显示的万年历.c

📁 一个实用的万年历程序
💻 C
字号:
/*
实验项目:基于AT89S52单片机的时钟,日历,整点报时及温度显示
 描述:本实验通过单片机内部晶振实现时钟,由DS18B20实现温度采集.实验中采用10位键输入方式,利用AT89S52编码键盘输入.
 全部输出由LCD1602显示,电源部分采用掉电工作方式,实现了时间信息的掉电保护,使在掉电状态下单片机时钟仍然工作。
 
 操作说明:

 键盘中 P3.0,P3.1,P3.2,P3.3	端口依次为LCD背光输出,报时接口,闹钟接口
		 
		 P1端口为输入调整键盘

		 P0口为液晶数据输出口中

		 P2.0,P2.1,P2.2 依次为液晶RS,RW,E 接口
*/
#include <reg51.h>
#include <intrins.h>
sbit lcd_led=P3^0;
sbit alarm_time=P3^1;
sbit alarm=P3^2;
bit scan_key(void);
void proc_key0(void);
void proc_key1(void);
extern void LCD_WriteCommand(unsigned char cmd);	 //写指令数据到LCD
extern void LCD_DisplayOneString(unsigned char X,unsigned char Y,unsigned char a[]);//显示一个字符串
extern void LCD_DisplayNum(unsigned charX,unsigned char Y,unsigned char num);       //显示一个数字 //外部函数声明区
extern void LCD_DisplayoneNum(unsigned char X,unsigned char num);
extern void LCD_Init(void);	//LCD初始化
extern void delayus(unsigned int num);  //液晶延时
void delayms(unsigned char ms);  //键盘延时
extern void LCD_DisplayOneChar(unsigned char X,unsigned char Y,unsigned char Z);//显示一个字符
extern unsigned char ReadTemperature(void);
void readkey(unsigned char date);
unsigned char keyscan(void);
unsigned char hour,min,sec,year,mon,day,week0,temp0,ahour,amin;
unsigned char atime,time,enter;  		//调整控制变量
unsigned char s0,s1,x0,x1;
unsigned char num,record;
unsigned char sec100;
unsigned int lcd;
unsigned char math;
unsigned char dis_time[11];	//时间调整保留数组
unsigned char code week[]={"week"};
unsigned char code temp[]={"temp"};
 unsigned char Init,show2;
void main(void)
{   unsigned char show3,show1;
    lcd=0;
    alarm_time=0;
	alarm=0;
    TMOD = 0x11;		// 定时器0, 1工作模式1, 16位定时方式
	TH0 =(65536-50000)/256;
	TL0 =(65536-50000)%256;
	TH1 = 0xFC;
	TL1 = 0x17;
    hour =12;
	min =0;
	sec =0;
	year=0;
	mon=10;
	day=1;
	ahour=12;
	amin=0;
	week0=1;
	sec100 = 0;
	IE = 0x8A;				// 使能timer0,1 中断
	TR0=1;
	TR1=1;
			 
	record=15;
	LCD_Init();
	LCD_WriteCommand(0x00);
	x0=0;
	x1=3;
	s0=0;
	atime=0;
	time=0;
	Init=0;
	while(1)
	{ 
	  temp0=ReadTemperature();//读温度 
	 
	  if(atime==0)
	  {
		  if(time==0)
	      {	
		   	if(show2)
			{  
			LCD_Init();LCD_WriteCommand(0x01);show2=0;
			}
		    LCD_WriteCommand(0x0c);
	        LCD_WriteCommand(0x06);
	        LCD_DisplayOneString(9,0,temp);
	        LCD_DisplayOneChar(13,0,0x3a);
	        LCD_DisplayNum(14,0,temp0); 				  
	        LCD_DisplayOneString(9,1,week);
	        LCD_DisplayNum(0,0,hour);			
	        LCD_DisplayOneChar(2,0,0xB0); 
            LCD_DisplayNum(3,0,min);
	        LCD_DisplayOneChar(5,0,0xB0); 				  //正常显示时间,月历,星期及当前温度
            LCD_DisplayNum(6,0,sec);
		    LCD_DisplayNum(0,1,year);
	        LCD_DisplayOneChar(2,1,0x2f); 
	        LCD_DisplayNum(3,1,mon);
	        LCD_DisplayOneChar(5,1,0x2f);
	        LCD_DisplayNum(6,1,day);
	        LCD_DisplayOneChar(13,1,0x3a); 
	        LCD_DisplayOneChar(14,1,(week0+0x30));
			show3=1;
			show1=1;
	      }
		  if(time) 
		  { dis_time[0]=hour/10;
		    dis_time[1]=hour%10;
			dis_time[2]=min/10;
			dis_time[3]=min%10;
			dis_time[4]=year/10;
			dis_time[5]=year%10;
			dis_time[6]=mon/10;
			dis_time[7]=mon%10;
			dis_time[8]=day/10;
			dis_time[9]=day%10;
			dis_time[10]=week0%10;
			//显示初始化
			if(show1)
			{  
			LCD_Init();LCD_WriteCommand(0x01);show1=0;
			}
		    LCD_WriteCommand(0x0c); 
			LCD_WriteCommand(0x06);
			LCD_DisplayNum(0,0,hour);
			LCD_DisplayOneChar(2,0,0xB0);
			LCD_DisplayNum(3,0,min);
			LCD_DisplayNum(6,0,year);
			LCD_DisplayOneChar(8,0,0xB0);
			LCD_DisplayNum(9,0,mon);
			LCD_DisplayOneChar(11,0,0xB0);
			LCD_DisplayNum(12,0,day);											//时间调整部分显示模式
			LCD_DisplayOneChar(15,0,(week0+0x30));
			
			
		    if(scan_key())
	        { 
	         delayms(10);
	         if(scan_key())
		      {  record=num;
		       if(num>=0&&num<=9)
               { dis_time[s0]=num;
                 s0++;
				 if(x0==2|x0==5|x0==8|x0==14) x0++;
				 LCD_DisplayoneNum(x0,num);
	             x0++;
				
                }
			  }
          }
			if(s0>10) 
			{
			  time=0;
			  s0=0;			  //如果调整完成自动回到主显示界面
              x0=0;
			 }
			hour=dis_time[0]*10+dis_time[1];
			min=dis_time[2]*10+dis_time[3];
			year=dis_time[4]*10+dis_time[5];
			mon=dis_time[6]*10+dis_time[7];
			day=dis_time[8]*10+dis_time[9];
			week0=dis_time[10];
			show3=1;
			show2=1;
         }
	 }
    else
	{ dis_time[0]=ahour/10;
	  dis_time[1]=ahour%10;
	  dis_time[2]=amin/10;
	  dis_time[3]=amin%10;
	  if(show3)
	   {  
	    LCD_WriteCommand(0x01);show3=0;
	   }
	  LCD_WriteCommand(0x0c); 
	  LCD_WriteCommand(0x06);
	  LCD_DisplayNum(0,0,ahour);
	  LCD_DisplayOneChar(2,0,0xB0);					   //显示闹钟
	  LCD_DisplayNum(3,0,amin);
	  	
      if(scan_key())
	  { delayms(10);
	      if(scan_key())
		  {  record=num;
		     if(num>=0&&num<=9)
             { dis_time[s0]=num;
                s0++;
		        if(x1==0) 
				 x1++;
				if(x1<5)
		        { LCD_DisplayoneNum(x1,num);
	               x1++;
				}
			 }
		  }
      }
	  if(s0>3) 
			{
			  atime=0;
			  s0=0;			  //如果调整完成自动回到主显示界面
              x1=2;
			 }
			ahour=dis_time[0]*10+dis_time[1];
			amin=dis_time[2]*10+dis_time[3];
		    show1=1;
			show2=1;
	   
	}
  }
}

//时钟产生部分
void timer1() interrupt 1 using 2		//定时工作,作为时钟
{	 unsigned int i,j;
     i=year+2000;
	TH0 =(65536-49975)/256;
	TL0 =(65536-49975)%256;
	sec100++;
	if(sec100>=20)
	{  sec100=0;
		sec++; 	Init++;if(Init++==3){Init=0;show2=1;}
		if(sec>59)
		{ sec=0;if(min==59){alarm_time=1;for(j=20;j>0;j--){}alarm_time=0;} //报时响应
		   min++;
		  if(min>59)
		  { min=0;			 //变换时间
		    hour++;
			if(hour>23)
			{ hour=0;
			  day++;
			  week0++;
			  if(week0>6) week0=0;
			  switch(mon)
			  { case 2:	if(i%4==0&&i%100!=0||i%400==0) if(day>28){day=1;mon++;if(mon>12){mon=1;year++;}} break;
			            if(day>29){day=1;mon++;if(mon>12){mon=1;year++;}} break;
			    case 1:	if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
			    case 3:	if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
			    case 5:	if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;		
			    case 7:	if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
			    case 8:	if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
			    case 10:if(day>31){day=1; mon++;if(mon>12){mon=1;year++;}} break;
                case 12:if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
			   	default:if(day>30){day=1;mon++;if(mon>12){mon=1;year++;}} break;
			  }

			}
		  }
		}
	  }
}
//键盘部分程序
void delayms(unsigned char ms)	
{  unsigned char i;
	while(ms--)
	{
		for(i = 0; i < 120; i++);
	}
}
bit scan_key()
{
  return(num^record);	
}


//闹钟部分中断响应
void searchtime() interrupt 3 using 1
{ 	
    TH1 = 0xFC;
	TL1 = 0x17;
    math=keyscan();
    readkey(math);

    if((ahour==hour)&&(amin==min))
	  alarm=1;
	  else alarm=0;
	  if(scan_key())
	 { if(atime==0&&num==10) time=1;
	    if(time==0&&num==11) atime=1;
	   if(num==12) 
	    { s0=0;
		  x0=0;
		  x1=2;
		  time=0;
	      atime=0;
		}
	   if(num!=15) lcd=1;
     }
  if(lcd) lcd++;
 if(lcd>5000) lcd=0;
 if(lcd!=0)    lcd_led=1;
 else
 lcd_led=0;
}


unsigned char keyscan(void)
{ unsigned char test,tmp;
  P1=0xf0;
  if((P1&0xf0)!=0xf0)
  {if((P1&0xf0)!=0xf0)
	{ test=0xfe;
	  while((test&0x10)!=0)
	  {	P1=test;
	    if((P1&0xf0)!=0xf0)
		{ tmp=(P1&0xf0)|0x0f;
		  return(~(test)+~(tmp));
		}
	else test=(test<<1)|0x01;
	  }
	}
  }
  return(0);
}
 
void readkey(unsigned char date)
 { switch(date)
  {	case 0X11: num=0;break;
    case 0X21: num=1;break;
	case 0X41: num=2;break;
	case 0X81: num=3;break;
	case 0X12: num=4;break;
	case 0X22: num=5;break;
	case 0X42: num=6;break;
	case 0x82: num=7;break;
	case 0x14: num=8;break;
	case 0x24: num=9;break;
	case 0x44: num=10;break;
	case 0x84: num=11;break;
	case 0x18: num=12;break;
	case 0x0: num=15;break;
  }
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -