基於51微控制器液晶萬年曆設計

_會飛_的魚發表於2018-12-19

電子萬年曆是一種非常廣泛日常計時工具,給人們的帶來了很大的方便,在社會上越來越流行。 它可以對年、月、日、時、分、秒進行計時,採用直觀的數字顯示,可以同時顯示年月日時分秒和溫度等資訊,還有時間校準、鬧鐘等功能。該電子萬年曆主要採用STC89C52微控制器作為主控核心,用DS1302時鐘晶片作為時鐘、液晶12864螢幕顯示。STC89C52微控制器是由巨集晶公司推出的,功耗小,電壓可選用4~6V電壓供電;DS1302時鐘晶片是美國DALLAS公司推出的具有細電流充電功能的低功耗實時時鐘晶片,它可以對年、月、日、星期、時、分、秒進行計時,還具有閏年補償等多種功能,而且DS1302的使用壽命長,誤差小;數字顯示是採用的12864液晶螢幕來顯示,可以同時顯示年、月、日、星期、時、分、秒和溫度等資訊。此外,該電子萬年曆還具有時間校準等功能。

1. 系統總體功能
本設計採用的是巨集晶公司的STC89C52微控制器為核心,通過微控制器與時鐘晶片DS1302通訊來對時間的讀寫,保證時鐘時間的穩定性,並帶有內部電源模組,使系統斷電時時鐘資料不會丟失,以DS18B20溫度感應晶片作為溫度電路的核心,向微控制器發出獲取到的溫度資料,並通過LCD1602將時間、顯示出來,並可以通過按鍵調整時間日期和鬧鐘時間。

2. 總體電路圖
在這裡插入圖片描述
電路組成:

  1. 微控制器最小系統
  2. LCD602液晶螢幕電路
  3. 四路獨立按鍵
  4. DS1302時鐘電路
  5. DS18B20溫度感測器
  6. 系統電源

3. 程式設計
(1) LCD1602驅動程式

sbit rs		= P2^0;
sbit rw		= P2^1;
sbit e  	= P2^2;
#define lcddata P0
sbit busy=P0^7;   //lcd busy bit
void wr_d_lcd(uchar content);
void wr_i_lcd(uchar content);
void clrram_lcd (void);
void init_lcd(void);
void busy_lcd(void);
void rev_row_lcd(uchar row);
void rev_co_lcd(uchar row,uchar col,uchar mode);
void clr_lcd(void);
void wr_co_lcd(uchar row,uchar col,uchar lcddata1,uchar lcddtta2);
void wr_row_lcd(uchar row,char *p);
//**********************************
//液晶初始化
//**********************************
void init_lcd(void)
{
	wr_i_lcd(0x06);  /*游標的移動方向*/
	wr_i_lcd(0x0c);  /*開顯示,關遊標*/
}
//***********************************
//填充液晶DDRAM全為空格
//**********************************
void clrram_lcd (void)
{
	wr_i_lcd(0x30);
	wr_i_lcd(0x01);
}
//***********************************
//對液晶寫資料
//content為要寫入的資料
//***********************************
void wr_d_lcd(uchar content)
{
	busy_lcd();
	rs=1;
    rw=0;
	lcddata=content;
	e=1;
	;
	e=0;
}
//********************************
//對液晶寫指令
//content為要寫入的指令程式碼
//*****************************
void wr_i_lcd(uchar content)
{
	busy_lcd();
	rs=0;
    rw=0;
	lcddata=content;
	e=1;
	;
	e=0;
}
//********************************
//液晶檢測忙狀態
//在寫入之前必須執行
//********************************
void busy_lcd(void)
{
  lcddata=0xff;
  rs=0;
  rw=1;
  e =1;
  while(busy==1);
  e =0;
}
//********************************
//指定要顯示字元的座標
//*******************************
void gotoxy(unsigned char y, unsigned char x)
{
	if(y==1)
		wr_i_lcd(0x80|x);
	if(y==2)
        wr_i_lcd(0x90|x);
	if(y==3)
		wr_i_lcd((0x80|x)+8);
	if(y==4)
        wr_i_lcd((0x90|x)+8);
}
//**********************************
//液晶顯示字串程式
//**********************************
void print(uchar *str)
{
	while(*str!='\0')
	{
		wr_d_lcd(*str);
		str++;
	}
}

//***************************************
//液晶顯示主程式模組
//***************************************
void show_time()   
{
  DS1302_GetTime(&CurrentTime);  //獲取時鐘晶片的時間資料
  TimeToStr(&CurrentTime);       //時間資料轉換液晶字元
  DateToStr(&CurrentTime);       //日期資料轉換液晶字元
  ReadTemp();                    //開啟溫度採集程式
  temp_to_str();                 //溫度資料轉換成液晶字元
  gotoxy(4,0);
  print("溫度");
  gotoxy(4,2);                  //液晶字元顯示位置
  print(TempBuffer);             //顯示溫度
  gotoxy(4,6);
  print("℃");
  gotoxy(3,0);
  print("時間:");
  gotoxy(3,3);
  print(CurrentTime.TimeString); //顯示時間
  gotoxy(2,3);
  print(CurrentTime.DateString); //顯示日期
  gotoxy(2,0);
  print("星期");
  gotoxy(2,2);
  print(week_value);             //顯示星期
  gotoxy(1,1);
  print("【萬年曆】");
  mdelay(500);                 //掃描延時
}

(2) DS1302驅動程式

//***********************************
//DS1302時鐘部分子程式模組
//***********************************
typedef struct __SYSTEMTIME__
{
	uchar Second;
	uchar Minute;
	uchar Hour;
	uchar Week;
	uchar Day;
	uchar Month;
	uchar  Year;
	uchar DateString[11];
	uchar TimeString[9];
}SYSTEMTIME;	//定義的時間型別
SYSTEMTIME CurrentTime;


#define AM(X)	X
#define PM(X)	(X+12)            	  // 轉成24小時制
#define DS1302_SECOND	0x80          //時鐘晶片的暫存器位置,存放時間
#define DS1302_MINUTE	0x82
#define DS1302_HOUR		0x84 
#define DS1302_WEEK		0x8A
#define DS1302_DAY		0x86
#define DS1302_MONTH	0x88
#define DS1302_YEAR		0x8C 
//**********************************
//實時時鐘寫入一位元組(內部函式)
//**********************************
void DS1302InputByte(uchar d) 	
{ 
    uchar i;
    ACC = d;
    for(i=8; i>0; i--)
    {
        DS1302_IO = ACC0;           	//相當於彙編中的 RRC
        DS1302_CLK = 1;
        DS1302_CLK = 0;
        ACC = ACC >> 1; 
    } 
}
//*************************************
//實時時鐘讀取一位元組(內部函式)
//*************************************
uchar DS1302OutputByte(void) 	
{ 
    uchar i;
    for(i=8; i>0; i--)
    {
        ACC = ACC >>1;         			//相當於彙編中的 RRC 
        ACC7 = DS1302_IO;
        DS1302_CLK = 1;
        DS1302_CLK = 0;
    } 
    return(ACC); 
}
//**************************************
//ucAddr: DS1302地址, ucData: 要寫的資料
//**************************************
void Write1302(uchar ucAddr, uchar ucDa)	
{
    DS1302_RST = 0;
    DS1302_CLK = 0;
    DS1302_RST = 1;
    DS1302InputByte(ucAddr);       	// 地址,命令 
    DS1302InputByte(ucDa);       	// 寫1Byte資料
    DS1302_CLK = 1;
    DS1302_RST = 0;
} 
//**************************************
//讀取DS1302某地址的資料
//**************************************
uchar Read1302(uchar ucAddr)	
{
    uchar ucData;
    DS1302_RST = 0;
    DS1302_CLK = 0;
    DS1302_RST = 1;
    DS1302InputByte(ucAddr|0x01);        // 地址,命令 
    ucData = DS1302OutputByte();         // 讀1Byte資料
    DS1302_CLK = 1;
    DS1302_RST = 0;
    return(ucData);
}

//******************************************
//獲取時鐘晶片的時鐘資料到自定義的結構型陣列
//******************************************
void DS1302_GetTime(SYSTEMTIME *Time)  
{
	uchar ReadValue;
	ReadValue = Read1302(DS1302_SECOND);
	Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//轉換為相應的10進位制數
	ReadValue = Read1302(DS1302_MINUTE);
	Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
	ReadValue = Read1302(DS1302_HOUR);
	Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
	ReadValue = Read1302(DS1302_DAY);
	Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);	
	ReadValue = Read1302(DS1302_WEEK);
	Time->Week = ((ReadValue&0x10)>>4)*10 + (ReadValue&0x0F);
	ReadValue = Read1302(DS1302_MONTH);
	Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
	ReadValue = Read1302(DS1302_YEAR);
	Time->Year = ((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F);	
}
//******************************************
//將時間年,月,日,星期資料轉換成液
//晶顯示字串,放到陣列裡DateString[]
//******************************************
void DateToStr(SYSTEMTIME *Time)    
{   
   uchar tab[ ]={0XD2,0XBB,0XB6,0XFE,0XC8,0XFD,0XCB,0XC4,0XCE,0XE5,0XC1,0XF9,0XC8,0XD5};
   if(hide_year<2)          //這裡的if,else語句都是判斷位閃爍,<2顯示資料,>2就不顯示,輸出字串為 2007/07/22
    {                               
	  Time->DateString[0] = '2';
	  Time->DateString[1] = '0';	 
	  Time->DateString[2] = Time->Year/10 + '0';
	  Time->DateString[3] = Time->Year%10 + '0';
	}
	  else
	    { 
	      Time->DateString[0] = ' ';
	      Time->DateString[1] = ' ';		 
	      Time->DateString[2] = ' ';
	      Time->DateString[3] = ' ';
		}
    Time->DateString[4]='-';
	if(hide_month<2)
	{
	  Time->DateString[5] = Time->Month/10 + '0';
	  Time->DateString[6] = Time->Month%10 + '0';
	}
	  else
	  {
	    Time->DateString[5] = ' ';
	    Time->DateString[6] = ' ';
	  }
    Time->DateString[7]='-';
	if(hide_day<2)
	{
	  Time->DateString[8] = Time->Day/10 + '0';
	  Time->DateString[9] = Time->Day%10 + '0';
	}
	  else
	  {
	    Time->DateString[8] = ' ';
	    Time->DateString[9] = ' ';	    
	  }
	if(hide_week<2)
	{
	  week_value[0] =tab[2*(Time->Week%10)-2];  //星期的資料另外放到 week_value[]陣列裡,跟年,月,日的分開存放,因為等一下要在最後顯示
	  week_value[1] =tab[2*(Time->Week%10)-1];
	}
	  else
	  {
	    week_value[0] = ' ';
		week_value[1]=' ';
	  }
	  week_value[2] = '\0';

	Time->DateString[10] = '\0'; //字串末尾加 '\0' ,判斷結束字元
}
//******************************************
//將時,分,秒資料轉換成液晶
//顯示字元放到陣列 TimeString[]
//*****************************************
void TimeToStr(SYSTEMTIME *Time) 
{   if(hide_hour<2)
    {
	  Time->TimeString[0] = Time->Hour/10 + '0';
	  Time->TimeString[1] = Time->Hour%10 + '0';
	}
	  else
	    {
	      Time->TimeString[0] = ' ';
	      Time->TimeString[1] = ' ';
		}
	Time->TimeString[2] = ':';
    if(hide_min<2)
	{
	  Time->TimeString[3] = Time->Minute/10 + '0';
	  Time->TimeString[4] = Time->Minute%10 + '0';
	}
	  else
	    {
	      Time->TimeString[3] = ' ';
	      Time->TimeString[4] = ' ';
   	    }
	Time->TimeString[5] = ':';
    if(hide_sec<2)
    {
	  Time->TimeString[6] = Time->Second/10 + '0';
	  Time->TimeString[7] = Time->Second%10 + '0';
    }
      else
       {
         Time->TimeString[6] = ' ';
	     Time->TimeString[7] = ' ';
       }
	Time->TimeString[8] = '\0';
}

//******************************
//時鐘晶片初始化
//******************************
void Initial_DS1302(void)   
{   
	uchar Second=Read1302(DS1302_SECOND);
	if(Second&0x80)	      //判斷時鐘晶片是否關閉	  
    {
	Write1302(0x8e,0x00); //寫入允許
	Write1302(0x8c,0x07); //以下寫入初始化時間 日期:07/07/25.星期: 3. 時間: 23:59:55
	Write1302(0x88,0x07);
	Write1302(0x86,0x25);
	Write1302(0x8a,0x07);
	Write1302(0x84,0x23);
	Write1302(0x82,0x59);
	Write1302(0x80,0x55);
	Write1302(0x8e,0x80); //禁止寫入
	}

}

(3)DS18B20驅動程式

/***********ds18b20子程式*************************/

/***********ds18b20延遲子函式(晶振12MHz )*******/ 

void delay_18B20(unsigned int i)
{
	while(i--);
}

/**********ds18b20初始化函式**********************/

void Init_DS18B20(void) 
{
	 unsigned char x=0;
	 DQ = 1;          //DQ復位
	 delay_18B20(8);  //稍做延時
	 DQ = 0;          //微控制器將DQ拉低
	 delay_18B20(40); //精確延時 大於 480us
	 DQ = 1;          //拉高匯流排
	 delay_18B20(7);
	 x=DQ;            //稍做延時後 如果x=0則初始化成功 x=1則初始化失敗
	 delay_18B20(10);
}

/***********ds18b20讀一個位元組**************/  

uchar ReadOneChar(void)
{
	uchar i=0;
	uchar dat = 0;
	for (i=8;i>0;i--)
	 {
		  DQ = 0; // 給脈衝訊號
		  dat>>=1;
		  DQ = 1; // 給脈衝訊號
		  if(DQ)
		  dat|=0x80;
		  delay_18B20(4);
	 }
 	return(dat);
}

/*************ds18b20寫一個位元組****************/  

void WriteOneChar(uchar dat)
{
 	uchar i=0;
 	for (i=8; i>0; i--)
 	{
  		DQ = 0;
 		DQ = dat&0x01;
    	delay_18B20(5);
 		DQ = 1;
    	dat>>=1;
 }
}

/**************讀取ds18b20當前溫度************/

void ReadTemp(void)
{
	uchar a=0;
	uchar b=0;
	uchar t;

	Init_DS18B20();
	WriteOneChar(0xCC);    	// 跳過讀序號列號的操作
	WriteOneChar(0x44); 	// 啟動溫度轉換

	delay_18B20(100);       // this message is wery important

	Init_DS18B20();
	WriteOneChar(0xCC); 	//跳過讀序號列號的操作
	WriteOneChar(0xBE); 	//讀取溫度暫存器等(共可讀9個暫存器) 前兩個就是溫度

	delay_18B20(50);

	a=ReadOneChar();    	//讀取溫度值低位
	b=ReadOneChar();   		//讀取溫度值高位
	t=b&0xf8;
	if(t)
	{
	  TempBuffer[0]=':';
	  TempBuffer[1]='-';
  	  temp_value=b<<4;
	  temp_value+=(a&0xf0)>>4;  
	  temp_value=~temp_value+1;
	  temp1_value=~a&0x0f;
	}
	else
	{  
        temp_value=b<<4;
        temp_value+=(a&0xf0)>>4; 
		 temp1_value=a&0x0f;
	    TempBuffer[0]=':';
	    TempBuffer[1]=temp_value/100+'0';  //百位
       if(TempBuffer[1]=='1')
       {
            TempBuffer[1]='1';
       }
       else
       {
           TempBuffer[1]=' ';
       } 
    }
}
void temp_to_str()   //溫度資料轉換成液晶字元顯示
{		

  TempBuffer[2]=temp_value%100/10+'0';  //十位
  TempBuffer[3]=temp_value%10+'0';  //個位
  TempBuffer[4]='.';
  TempBuffer[5]=temp1_value*625/1000%10+'0';
  TempBuffer[6]=temp1_value*625/100%10+'0';
  TempBuffer[7]=temp1_value*625/10%10+'0';
  //TempBuffer[8]=temp1_value*625%10+'0';
  TempBuffer[8]='\0';
}
//**********************************************
//延時子程式模組
//**********************************************
void mdelay(uint delay)
{	uint i;
 	for(;delay>0;delay--)
   		{for(i=0;i<80;i++) //1ms延時.
       		{;}
   		}
}

(4) 按鍵驅動程式

//************************************
//跳出調整模式,返回預設顯示
//************************************
void outkey()                    
{ uchar Second;
  if(out==0)         
  { mdelay(5); 
	count=0;
	hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;
	Second=Read1302(DS1302_SECOND);
    Write1302(0x8e,0x00); //寫入允許
	Write1302(0x80,Second&0x7f);
	Write1302(0x8E,0x80);          //禁止寫入
	done=0;           
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//*************************
//升序按鍵
//*************************
void Upkey()
{	   
		Up=1;
	            if(Up==0)
		          {
				   mdelay(5);
				       switch(count)
				          {case 1:
                                  temp=Read1302(DS1302_SECOND);  //讀取秒數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //秒數加1
                                  up_flag=1;    //資料調整後更新標誌
								  if((temp)>59)   //超過59秒,清零
                                  temp=0;	
							  	  temp=temp/10*16+temp%10;
								  break;
				           case 2:
                                  temp=Read1302(DS1302_MINUTE);  //讀取分數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //分數加1
                                  up_flag=1;
								  if(temp>59)          //超過59分,清零
								  temp=0;
								  temp=temp/10*16+temp%10;
								  break;
				           case 3:
                                  temp=Read1302(DS1302_HOUR);  //讀取小時數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //小時數加1
                                  up_flag=1;
								  if(temp>23)   //超過23小時,清零
								  temp=0;
								  temp=temp/10*16+temp%10;
								  break;
				           case 4:
                                  temp=Read1302(DS1302_WEEK);  //讀取星期數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //星期數加1
                                  up_flag=1;
								  if(temp>7)  
								  temp=1;
								  temp=temp/10*16+temp%10;
								  break;
				           case 5:
                                  temp=Read1302(DS1302_DAY);  //讀取日數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //日數加1
                                  up_flag=1;
								  if(temp>31)
								  temp=1;
								  temp=temp/10*16+temp%10;
								  break;
				           case 6:
                                  temp=Read1302(DS1302_MONTH);  //讀取月數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //月數加1
                                  up_flag=1;
								  if(temp>12)
								  temp=1;
								  temp=temp/10*16+temp%10;
								  break;
				           case 7:
                                  temp=Read1302(DS1302_YEAR);  //讀取年數
								  temp=((temp&0xf0)>>4)*10 + (temp&0x0F);
								  temp=temp+1;  //年數加1
                                  up_flag=1;
								  if(temp>99)
								  temp=0;
								  temp=temp/10*16+temp%10;
								  break;
					       default:break;
				          }
					  
				 //  while(Up==0);
				  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
//************************
//降序按鍵
//************************
void Downkey()
{	    
		Down=1;
	    if(Down==0)
		          {
				   mdelay(5);
				     switch(count)
				          {case 1:
                                  temp=Read1302(DS1302_SECOND);  //讀取秒數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;						    //秒數減1
                                  down_flag=1;       //資料調整後更新標誌
								  if(temp==-1)     //小於0秒,返回59秒
								  temp=59;
								  temp=temp/10*16+temp%10;
								  break;
				           case 2:
                                  temp=Read1302(DS1302_MINUTE);  //讀取分數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //分數減1
                                  down_flag=1;
								  if(temp==-1)
								  temp=59;      //小於0秒,返回59秒
								  temp=temp/10*16+temp%10;
								  break;
				           case 3:
                                  temp=Read1302(DS1302_HOUR);  //讀取小時數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //小時數減1
                                  down_flag=1;
								  if(temp==-1)
								  temp=23;
								  temp=temp/10*16+temp%10;
								  break;
				           case 4:
                                  temp=Read1302(DS1302_WEEK);  //讀取星期數;
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //星期數減1
                                  down_flag=1;
								  if(temp==0)
								  temp=7;
								  temp=temp/10*16+temp%10;
								  break;
				           case 5:
                                  temp=Read1302(DS1302_DAY);  //讀取日數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //日數減1
                                  down_flag=1;
								  if(temp==0)
								  temp=31;
								  temp=temp/10*16+temp%10;
								  break;
				           case 6:
                                  temp=Read1302(DS1302_MONTH);  //讀取月數
								  temp=((temp&0x70)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //月數減1
                                  down_flag=1;
								  if(temp==0)
								  temp=12;
								  temp=temp/10*16+temp%10;
								  break;
				           case 7:
                                  temp=Read1302(DS1302_YEAR);  //讀取年數
								  temp=((temp&0xf0)>>4)*10 + (temp&0x0F);
								  temp=temp-1;  //年數減1
                                  down_flag=1;
								  if(temp==-1)
								  temp=99;
								  temp=temp/10*16+temp%10;
								  break;
					      default:break;
				         }
					 
				 //  while(Down==0);
				  }
}

//**************************
//模式選擇按鍵
//**************************
void Setkey()
{
		Set=1;
		if(Set==0)
	    {
           mdelay(5);
           count=count+1;	 //Setkey按一次,count就加1
		   done=1;			 //進入調整模式
           while(Set==0);
		 }

}

//*************************
//按鍵功能執行
//*************************
void keydone()
{        
		uchar Second;
		/* if(flag==0)    //關閉時鐘,停止計時
         { Write1302(0x8e,0x00); //寫入允許
           temp=Read1302(0x80);
           Write1302(0x80,temp|0x80);
	       Write1302(0x8e,0x80); //禁止寫入
           flag=1;
         }*/
         Setkey();				            //掃描模式切換按鍵
		 switch(count)
		 {
		 	case 1:do					        //count=1,調整秒
		       {
                   outkey();			   //掃描跳出按鈕
				   Upkey();                //掃描加按鈕
				   Downkey();              //掃描減按鈕
				   if(up_flag==1||down_flag==1)  //資料更新,重新寫入新的資料
				   {
				     Write1302(0x8e,0x00); //寫入允許
				     Write1302(0x80,temp); //寫入新的秒數
				     Write1302(0x8e,0x80); //禁止寫入
				     up_flag=0;
			    	 down_flag=0;
				  }
                     if(Down!=0&&Up!=0)
                     {
						hide_sec++;
				        if(hide_sec>3)
				        hide_sec=0;
                     }
					 else hide_sec=0;
					 show_time();         //液晶顯示資料
				  }while(count==2);break;  
		  case 2:do					        //count=2,調整分
		          {
				   hide_sec=0;
				   outkey();
				   Upkey();
				   Downkey();
				   if(temp>0x60)
				     temp=0;
				   if(up_flag==1||down_flag==1)
				   {
				     Write1302(0x8e,0x00); //寫入允許
				     Write1302(0x82,temp); //寫入新的分數
				     Write1302(0x8e,0x80); //禁止寫入
				     up_flag=0;
				     down_flag=0;
				  }
                     if(Down!=0&&Up!=0)
                     {
						hide_min++;
				        if(hide_min>3)
				        hide_min=0;
                     }
					 else hide_min=0;
					 show_time();
				  }while(count==3);break;
		  case 3:do					        //count=3,調整小時
		          {
                   hide_min=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				      Write1302(0x8e,0x00); //寫入允許
				      Write1302(0x84,temp); //寫入新的小時數
				      Write1302(0x8e,0x80); //禁止寫入
				      up_flag=0;
				      down_flag=0;
				   }
                      if(Down!=0&&Up!=0)
                     {
						hide_hour++;
				        if(hide_hour>3)
				        hide_hour=0;
                     }
					 else  hide_hour=0;
					  show_time();
				  }while(count==4);break;
		  case 4:do					        //count=4,調整星期
		          {
                   hide_hour=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				     Write1302(0x8e,0x00); //寫入允許
				     Write1302(0x8a,temp); //寫入新的星期數
				     Write1302(0x8e,0x80); //禁止寫入
				     up_flag=0;
				     down_flag=0;
				   }
                     if(Down!=0&&Up!=0)
                     {
					   hide_week++;
				       if(hide_week>3)
				       hide_week=0;
                     }
					 else hide_week=0;
					 show_time();
				  }while(count==5);break;
		  case 5:do					        //count=5,調整日
		          {
				   hide_week=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				     Write1302(0x8e,0x00); //寫入允許
				     Write1302(0x86,temp); //寫入新的日數
				     Write1302(0x8e,0x80); //禁止寫入
				     up_flag=0;
				     down_flag=0;
				   }
                     if(Down!=0&&Up!=0)
				     {
						hide_day++;
				        if(hide_day>3)
				        hide_day=0;
					 }
				    else hide_day=0;
                     show_time();
				  }while(count==6);break;
		  case 6:do					        //count=6,調整月
		          {
                   hide_day=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				      Write1302(0x8e,0x00); //寫入允許
				      Write1302(0x88,temp); //寫入新的月數
				      Write1302(0x8e,0x80); //禁止寫入
				      up_flag=0;
				      down_flag=0;
				   }
                     if(Down!=0&&Up!=0)
				     {
						 hide_month++;
				         if(hide_month>3)
				         hide_month=0;
					 }
					else hide_month=0;
                     show_time();
				  }while(count==7);break;
		  case 7:do					        //count=7,調整年
		          {
                   hide_month=0; 
				   outkey();
				   Upkey();
				   Downkey();
				   if(up_flag==1||down_flag==1)
				   {
				      Write1302(0x8e,0x00); //寫入允許
				      Write1302(0x8c,temp); //寫入新的年數
				      Write1302(0x8e,0x80); //禁止寫入
				      up_flag=0;
				      down_flag=0;
				  }
                      if(Down!=0&&Up!=0)
				      {
					 	 hide_year++;
				         if(hide_year>3)
				         hide_year=0;
                      }
					  else hide_year=0;
                      show_time();
				  }while(count==8);break;
		  case 8: count=0;hide_year=0;  //count8, 跳出調整模式,返回預設顯示狀態
	              Second=Read1302(DS1302_SECOND);
                  Write1302(0x8e,0x00); //寫入允許
	              Write1302(0x80,Second&0x7f);
	              Write1302(0x8E,0x80);          //禁止寫入
				  done=0;
		  break; //count=7,開啟中斷,標誌位置0並退出
		  default:break;

		 }

}

(5) 主程式

main()
{
  //  flag=1;           //時鐘停止標誌
	init_lcd();
	clrram_lcd();
	Init_DS18B20( ) ;      //DS18B20初始化
	Initial_DS1302(); //時鐘晶片初始化
	up_flag=0;
	down_flag=0;
	done=0;           //進入預設液晶顯示
	while(1)
	{   
        while(done==1)
          keydone();    //進入調整模式
		while(done==0)
 	    {  
            show_time();                //液晶顯示資料
           // flag=0;                  
  		    Setkey();				 //掃描各功能鍵
 		}		
	}
}

原始碼+AD電路圖 下載:關注公眾號,首頁回覆“萬年曆”獲取資料
在這裡插入圖片描述

相關文章