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

📄 dateandtime.c

📁 本源程序是基于AT89C51单片机的
💻 C
📖 第 1 页 / 共 2 页
字号:
 /***********************************************************************************
 ************************************************************************************
                        ********************************                      
                         基于MSC-51单片机的万年历程序
                        ********************************
       文件名称:DataAndTime.c
       设 计 者:  黄开坤
 ***********************************************************************************/
#include <reg51.h>
#include <LCD1602.h>
#include <DS18B20.h>
sbit led   =P3^7                   ;    //LCD屏背光灯控制线
sbit Play  =P3^0                   ;    //启到发音
/***全局变量************************************************************************/
unsigned char year             =7  ;    //年变量,初始值为2007年
unsigned char month            =4  ;    //月娈量,初始值为4月
unsigned char day              =20 ;    //日变量,初始值为20日
unsigned char week             =5  ;    //周    ,初始值为周5
unsigned char hour             =12 ;    //时    ,初始值为12
unsigned char minute           =0  ;    //分    ,初始值为0
unsigned char second           =0  ;    //秒    ,初始值为0
unsigned char Timer_hour       =12 ;    //定时器的时变量
unsigned char Timer_minute     =0  ;    //定时器的分变量
unsigned char days             =30 ;    //用于存放每月的天数,初使值为30天
unsigned char Timer_Ring       =1  ;    //定时器提示音编号
unsigned char led_on           =15 ;    //LCD显示屏背光灯亮的时间
unsigned char Number           =0  ;    //用于指定报第几个音
  
bit Temperature_sin            =1  ;    //温度转换标志,为1,则启动温度转换并刷新
bit LeapYear_sin               =0  ;    //润年标志,1为润年,0为非润年 
bit Timer_sin =0                   ;    //定时器响应标志,为1表示定时已到,正在响应
bit Timer_ON_OFF                   ;    //定时器开/关标志。1开;0为关
bit Timer_Show_sin                 ;    //定时器显示标志。为1表示正处于定时器显示状态
bit Speak_sin                      ;    //报时标志,为1表示正在报时
                                       
unsigned char DATA[3]              ;    //存放两位十进制数的ASCII码
unsigned char Week_Str[4]          ;    //用于存放3个字符,表示星期,如Mon表示星期一
unsigned char Voice[4]             ;    //存放两位十进数的语音地址
unsigned char Speak[11]            ;    //存放将要报出的语音
/***0-10语音地址表******************************************************************/
unsigned char code VoiceTab[]={0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c,0x20,0x24};

/***2000--2099年中的润年表**********************************************************/
unsigned char code Leap_YearTAB[]={4 ,8 ,12,16,20,24,28,32,36,40,44,48,
                                   52,56,60,64,68,72,76,80,84,88,92,96};
/***计算润年************************************************************************/
void Leap_Year(unsigned char Years)
{	 
     unsigned char i;
	 for(i=0;i<24;i++)
	    { 
		 if(Years==Leap_YearTAB[i])    //用查表的方法确定是否为润年
		      {LeapYear_sin=1;break;}
         else
		      LeapYear_sin=0;
		}
}
/***计算每月的天数******************************************************************/
unsigned char Momth_Days(unsigned char Months)
{
     switch(Months)
	   { case 2  :{if(LeapYear_sin==1)  //二月份天数,润年为29天,非润年为28天
	                  days=29;
				   else
				      days=28;
				   };break;
		 case 4  :	                    //四、六、九、十一月份为30天
		 case 6  :
		 case 9  :
		 case 11 :days=30  ;break;
		 default :days=31  ;            //其余月份为31天
		}
	days=days+1	   ;
	return(days);                       //返回值=某月的实际天数+1。
}		                            
/***星期转换************************************************************************/
void WeekToStr( char n)
{
     switch(n)
       { case 1 :{Week_Str[0]='M' ;     //星期一,Mon
	              Week_Str[1]='o' ;
				  Week_Str[2]='n' ;
				  Week_Str[3]='\0';
				  };break         ;
	     case 2 :{Week_Str[0]='T' ;     //星期二,Tue
	              Week_Str[1]='u' ;
				  Week_Str[2]='e' ;
				  Week_Str[3]='\0';
				  };break         ;
	     case 3 :{Week_Str[0]='W' ;     //星期三,Wen
	              Week_Str[1]='e' ;
				  Week_Str[2]='n' ;
				  Week_Str[3]='\0';
				  };break         ;
	     case 4 :{Week_Str[0]='T' ;     //星期四,Thu
	              Week_Str[1]='h' ;
				  Week_Str[2]='u' ;
				  Week_Str[3]='\0';
				  };break         ;
	     case 5 :{Week_Str[0]='F' ;     //星期五,Fri
	              Week_Str[1]='r' ;
				  Week_Str[2]='i' ;
				  Week_Str[3]='\0';
				  };break         ;
	     case 6 :{Week_Str[0]='S' ;     //星期六,Sat
	              Week_Str[1]='a' ;
				  Week_Str[2]='t' ;
				  Week_Str[3]='\0';
		  		  };break         ;
		 case 7 :{Week_Str[0]='S' ;     //星期日,Sun
	              Week_Str[1]='u' ;
				  Week_Str[2]='n' ;
				  Week_Str[3]='\0';
				  };break         ;
	   }
} 
/***类型转换(将字符型数据转换成相应的ASCII码****************************************/  
void CharToStr(unsigned char t) 
{
	DATA[0]=(t/10)%10+'0'          ;  //取十位,并转换成相应的ASCII码       	
	DATA[1]=t%10+'0'               ;  //取个位,并转换成相应的ASCII码                                    	
	DATA[2]='\0'                   ;  //字符串结束符                                 	
} 
/***延时程序************************************************************************/
void Delay1ms(unsigned char n)        //延时时间≈(4*n+996*n)us=n ms
{  
     unsigned char k=166;
	 while(--n)
	    {  while(--k)
		   ;
		}
}
/***键盘扫描程序********************************************************************/  
unsigned char Key_Scan(void)
{  
	 if((P2&0x0f)!=0x0f)                             //判断P.4--P2.7是否有键按下
	    { Delay1ms(10)        ;                      //延时10ms,消抖动
		  if((P2&0x0f)!=0x0f)
		     { led_on=15      ;                      //LCD屏的背光灯亮的时间重新赋值
			   led=1          ;						 //只要有键按下,LCD屏的背光灯就亮
			   Timer_sin=0    ;                      //只要有键按下,闹铃停止
			   switch(P2&0x0f)
			    {case 0x0e :{while((P2&0x0f)!=0x0f)  //等待按键释放 
				              ;
				              return 1;				 //P2.4上的键按下,1号键
							  };break;	            
				 case 0x0d :{while((P2&0x0f)!=0x0f)  //等待按键释放 
				              ;
				              return 2;				 //P2.5上的键按下,2号键
							  };break;	            
				 case 0x0b :{while((P2&0x0f)!=0x0f)  //等待按键释放 
				              ;
				              return 3;				 //P2.6上的键按下,3号键
							  };break;	            
				 case 0x07 :{while((P2&0x0f)!=0x0f)  //等待按键释放 
				              ;
				              return 4;				 //P2.7上的键按下,4号键
							  };break;	            
				 default   :return 0;
				}
			}
		}
	else
	    return 0;
}
/***数字——语音变换****************************************************************/
void NumberToVoice(unsigned char number)//将数字转换成相应的读音。(0≤number<60)
{
     unsigned char a,b;
	 a=(number/10)%10        ;          //取十位值
	 b=number%10     ;                  //取个位值
	 if(a==0)                           //0≤number<10时的读音,(一个音)
	   { Voice[0]=VoiceTab[b];          //
	     Voice[1]=0xff       ;          //
		}
	 if(a!=0&&b==0)                     //number的个位为0,十位不为0时的读音
	  {if(a==1)                         //10的读音
	    {Voice[0]=0x28       ;          //
		 Voice[1]=0xff       ;          //
		}
	    Voice[0]=VoiceTab[a] ;          //个位为0,十位不为0和1时的读音
		Voice[1]=0x28        ;          //
		Voice[2]=0xff        ;          //
	  }
	 if(a==1&&b!=0)                     //10<number<20时的读音,(两个音)
	   {Voice[0]=0x28        ;          //
	    Voice[1]=VoiceTab[b] ;          //
		Voice[2]=0xff        ;          //
	    }
	 if((a!=0&&a!=1)&&b!=0)             //number的个位不为0,十位不为0和1时的读音
	    {Voice[0]=VoiceTab[a];          //
		 Voice[1]=0x28       ;          //
		 Voice[2]=VoiceTab[b];          //
		 Voice[3]=0xff       ;          //
		 } 
}
/***语音报时************************************************************************/
void SpeakTime(void)                    //语音报时函数
{
     unsigned char j,i=0     ;
	 Speak[i]=0x3c           ;          //报时前凑音
	 i++                     ; 
	 Speak[i]=0x2c           ;          //“现在时刻”
	 NumberToVoice(hour)     ;          //“小时”
	 for(j=0;j<5;j++)
	    { i++				 ;
		  if(Voice[j]==0xff) 
		    { Speak[i]=0x34  ;          //“点”
			  break;
			} 
		    Speak[i]=Voice[j];
		}					 
	 NumberToVoice(minute)   ;         //“分钟”
	 for(j=0;j<5;j++)               
	    { i++                ;
		  if(Voice[j]==0xff) 
		  	{ Speak[i]=0x38  ;		    //“分”
			  break          ;
			 }         	  
		  Speak[i]=Voice[j]  ;
		 }
	 i++                     ;
	 Speak[i]=0xff           ;          //报时结束标志     
	 EX0=1                   ;          //INT0开中
	 IE0=1                   ;          //启动报时
	 Speak_sin=1             ;          //报时标志置1
}
/***闹铃****************************************************************************/
void Ring(void)            
{	 
	 if(Timer_Ring==1)					//铃声1
	    P1=0x44              ;
	 if(Timer_Ring==2)		            //铃声2
	    P1=0x58              ;
	 if(Timer_Ring==3)		            //铃声3
	    P1=0x70              ;
	 Timer_sin=1             ;          //表示进入闹铃状态
	 EX0=1                   ;			//INT0开中
	 IE0=1                   ;			//启动闹铃
}
/***日历和时间调整******************************************************************/
void Set_TimeAndDate(void)
{ 
 		   unsigned char key; 
	       EX1=0;					    //关闭INT1中断,停止计时
           LCD_ShowMode(LCD_SHOW|LCD_CORSOR|LCD_FLASH);	//开光标,光标闪烁
 Year_set: LCD_GoToXY(2,1)            ; //年校正  
		   key=Key_Scan()             ; //键盘扫描   
 	       if(key==1) goto Month_set  ;	//如果按下的是功能键(1号键),转月校正
		   if(key==2) year++          ;	//如果按下的是加1 键(2号键),年加1
		   if(year==100)                //年上限循环
		      year=0                  ;         
		   if(key==3) year--          ; //如果按下的是减1 键(3号键),年减1
		   if(year==-1)				    //年下限循环
		      year=99                 ;
		   Leap_Year(year)			  ; //判断润年
		   LCD_GoToXY(2,1)            ;
		   CharToStr(year)            ; //将校正后的年数据转换成相对应的ASCII码
		   Delay1ms(50)               ; //延时100ms
		   LCD_Print(DATA)            ; //年显示刷新
		   goto Year_set              ;	//年校正循环

Month_set: LCD_GoToXY(5,1)            ;	//月校正
	       key=Key_Scan()             ; //键盘扫描  
 	       if(key==1) goto Day_set    ; //如果按下的是功能键(1号键),转日校正
		   if(key==2) month++         ;	//如果按下的是加1 键(2号键),月加1
		   if(month==13)                //月上限循环
		      month=1                 ;         
		   if(key==3) month--         ; //如果按下的是减1 键(3号键),月减1
		   if(month==0)					//月下限循环
		      month=12                ;
		   CharToStr(month)           ;	//将校正后的月数据转换成相对应的ASCII码
		   Delay1ms(50)              ;	//延时100ms
		   LCD_Print(DATA)            ; //月显示刷新
		   Momth_Days(month)          ;	//确定校正后,月的天数
		   goto Month_set             ; //月校正循环

  Day_set: LCD_GoToXY(8,1)			  ; //日校正
   		   key=Key_Scan()             ; //键盘扫描  
 	       if(key==1) goto Week_set   ;	//如果按下的是功能键(1号键),转时校正
		   if(key==2) day++           ; //如果按下的是加1 键(2号键),日加1         
		   if(day==days)                //日上限循环
		      day=1                   ;

⌨️ 快捷键说明

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