【資料結構——圖和圖的儲存結構】

qwer1030274531發表於2020-11-12


微控制器實訓之萬年曆(具有時分秒,日期,星期調校功能

什麼是萬年曆????

年曆是中國古代傳說中最古老的一部太陽曆。萬年曆是記錄一定時間範圍內(比如100年或更多)的具體陽曆與陰曆的日期的年曆,方便有需要的人查詢使用。萬年只是一種象徵,表示時間跨度大。所使用的萬年曆,即包括若干年或適用於若干年的歷書 。現代的萬年曆能同時顯示公曆、農曆和干支歷等多套曆法,更能包含黃曆相關吉凶宜忌、節假日、提醒等多種功能資訊,極為方便人們查詢使用。

1. 液晶多功能萬年曆的設計

該專案以AT89C51微控制器為核心,結合數字溫度調節器ds18b20、時鐘晶片ds1302和液晶顯示器lcd1602設計而成的液晶顯示的萬年曆。系統中時鐘模組為整個系統提供較為精準的時間資料;溫度感測器模組可以獲取周圍環境的溫度值且當溫度高於一定的數值時,實現喇叭器報警;液晶顯示模組用於顯示日期(年,月,日)、時間(時,分,秒)、星期、溫度的引數值,也可以透過按鍵來調整各個引數的數值(具有加、減功能)。

2. 設計主要功能

1.顯示年、月、日(含閏年)、時、分、秒、星期(周幾)、溫度的資訊;
2.具有溫度顯示功能;
3.具有溫度報警功能,一旦溫度超過35攝氏度,就開啟喇叭實現報警;
4.定時開啟和關閉(上午8:00-晚上22:00開啟,晚上22:00-第二天上午8:00關閉)功能。
5.具有日期(年,月,日)和時間(時,分,秒)、星期、溫度的調較功能。
6.具有整點報時功能。

1.2. 設計原理

1)微控制器選擇:採用傳統的AT89C51作為此係統的控制核心,AT89C51是一種帶4K位元組閃爍可程式設計可擦除只讀儲存器的低電壓高效能CMOS8位微處理器。
2)時鐘晶片選擇:DS1302是由美國DALLAS公司推出的具有涓細電流充電能力的低功耗實時時鐘晶片。它可以對年、月、日、周、時、分、秒進行計時,且具有閏年補償等多種功能。
時鐘晶片選擇DS1302來實現時鐘功能,DS1302晶片是一種高效能晶片,可自動對秒,分,時,月,日,周,年進行計數,而且精度高。
3)顯示模組的選擇:使用液晶螢幕(LCD1602)顯示時間、日期以及星期的資訊。
4)按鍵模組的選擇:選擇獨立式的按鈕(button),按鍵具體設定為三個按鍵,功能分為設定,加,減,確定修改。

主要電路圖如下:

在這裡插入圖片描述

主要程式碼如下:

shuzishizhong.c

#include<REG51.H>#include<stdio.h>#include<stdlib.h>#include "LCD1602.H"#include "DS1302.H"#include "ds18b20.H"#define uint unsigned int#define uchar unsigned char#define TH 35  //設定溫度上限extern unsigned char week_value[2],TempBuffer[5];   //宣告外部變數extern int temp_value;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;  //秒,分,時到日,月,年位閃的計數sbit Set  = P3^0;       //P3.0口控制模式切換鍵sbit Up   = P3^1;        //加法按鈕sbit Down = P3^2;      //減法按鈕sbit out  = P3^3;       //立刻跳出調整模式按鈕sbit deng = P1^1; sbit bee=P1^3;sbit key_set_alarm=P3^7;char done,count,temp,flag,up_flag,down_flag;char  SD=1;int  a,b,c;int b=1;void show_time();   //液晶顯示函式宣告void close_time();  //液晶屏關閉函式宣告/**************************************************************
延時子程式
**************************************************************/void mdelay(uint delay){ uint i;
  for(;delay>0;delay--)
    {for(i=0;i<62;i++) //1ms延時.
        {;}
    }}/**************************************************************
用於液晶屏顯示關閉
**************************************************************/void close_time(){
    LCD_Write(0,0x01); 
    mdelay(1);}/**************************************************************
用於液晶屏顯示開起		 
**************************************************************///void open_time(){//   LCD_SetDisplay(0x04|0x02); 
   //mdelay(1000);//}/**************************************************************
升序按鍵
**************************************************************/void Upkey(){    Up=1;if(Up==0){
   mdelay(8);
       switch(count)
          {
		  case 1:
             temp=Read1302(DS1302_SECOND);  //讀取秒數
		     temp=temp+1;  //秒數加1
             up_flag=1;    //資料調整後更新標誌
             if((temp&0x7f)>0x59)   //超過59秒,清零
                 temp=0;   
             break;
           case 2:
             temp=Read1302(DS1302_MINUTE);  //讀取分數
             temp=temp+1;  //分數加1
             up_flag=1;
             if(temp>0x59)          //超過59分,清零
                 temp=0;
             break;
           case 3:
             temp=Read1302(DS1302_HOUR);  //讀取小時數
             temp=temp+1;  //小時數加1
             up_flag=1;
             if(temp>0x23)   //超過23小時,清零
                 temp=0;
             break;
           case 4:
             temp=Read1302(DS1302_WEEK);  //讀取星期數
             temp=temp+1;  //星期數加1
             up_flag=1;
             if(temp>0x7)  //大於周1-周7清零
                 temp=1;
             break; 
           case 5:
             temp=Read1302(DS1302_DAY);  //讀取日數
             temp=temp+1;  //日數加1
             up_flag=1;
             if(temp>0x31) //大於31天清零
                temp=1;
             break;
           case 6:
             temp=Read1302(DS1302_MONTH);  //讀取月數
             temp=temp+1;  //月數加1
             up_flag=1;
             if(temp>0x12) //大於12個月清零
                temp=1;
             break;
           case 7:
             temp=Read1302(DS1302_YEAR);  //讀取年數
             temp=temp+1;  //年數加1
             up_flag=1;
             if(temp>0x85) //大於85年清零
               temp=0;
             break;
           default:break;
          }
     while(Up==0);
    }}/**************************************************************
降序按鍵
**************************************************************/void Downkey(){     
    Down=1;
    if(Down==0){
     mdelay(8);
     switch(count){
		  case 1:
             temp=Read1302(DS1302_SECOND);  //讀取秒數
             temp=temp-1;     //秒數減1
             down_flag=1;       //資料調整後更新標誌
             if(temp==0x7f){     //小於0秒,返回59秒
                 temp=0x59;
			 }
             break;
           case 2:
             temp=Read1302(DS1302_MINUTE);  //讀取分數
             temp=temp-1;  //分數減1
             down_flag=1;
             if(temp==-1){
                temp=0x59; 
			 }	      //小於0分,返回59分
             break;
           case 3:
             temp=Read1302(DS1302_HOUR);  //讀取小時數
             temp=temp-1;  //小時數減1
             down_flag=1;
             if(temp==-1)
                temp=0x23;
             break;
           case 4:
             temp=Read1302(DS1302_WEEK);  //讀取星期數
             temp=temp-1;  //星期數減1
             down_flag=1;
             if(temp==0)
                temp=0x07;
             break; 
           case 5:
             temp=Read1302(DS1302_DAY);  //讀取日數
             temp=temp-1;  //日數減1
             down_flag=1;
             if(temp==0)
                temp=0x31;
             break;
           case 6:
             temp=Read1302(DS1302_MONTH);  //讀取月數
             temp=temp-1;  //月數減1
             down_flag=1;
             if(temp==0)
                temp=0x12;
             break;
           case 7:
             temp=Read1302(DS1302_YEAR);  //讀取年數
             temp=temp-1;  //年數減1
             down_flag=1;
             if(temp==-1)
                temp=0x85;
             break;
      default:break;
         }
   while(Down==0);  
  }}/**************************************************************
模式選擇按鍵
**************************************************************/void Setkey(){Set=1;if(Set==0){
           mdelay(8);
           count=count+1; //Setkey按一次,count就加1
           done=1; //進入調整模式
           while(Set==0);
           }}/**************************************************************
跳出調整模式,返回預設顯示
**************************************************************/void outkey()                    { uchar Second;
  out=1;
  if(out==0)         
  {  
       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;           
       while(out==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|0x80); //寫入新的秒數
   Write1302(0x8e,0x80); //禁止寫入
   up_flag=0;
   down_flag=0;
   }
   hide_sec++;          //位閃計數
   if(hide_sec>3)
     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;
   }
   hide_min++;
   if(hide_min>3)
     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;
   }
   hide_hour++;
   if(hide_hour>3)
     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;
   }
   hide_week++;
   if(hide_week>3)
     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;
   }
   hide_day++;
   if(hide_day>3)
     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;
   }
   hide_month++;
   if(hide_month>3)
     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;
   }
   hide_year++;
   if(hide_year>3)
     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;}}/**************************************************************
液晶顯示程式
**************************************************************/void show_time()   {//while(1)//{
  DS1302_GetTime(&CurrentTime);  //獲取時鐘晶片的時間資料
  TimeToStr(&CurrentTime);       //時間資料轉換液晶字元
  DateToStr(&CurrentTime);       //日期資料轉換液晶字元
  ReadTemp();                    //開啟溫度採集程式
  temp_to_str();                 //溫度資料轉換成液晶字元
  GotoXY(12,1);                  //液晶字元顯示位置
  Print(TempBuffer);             //顯示溫度
  GotoXY(0,1);
  Print(CurrentTime.TimeString); //顯示時間
  GotoXY(0,0);
  Print(CurrentTime.DateString); //顯示日期
  GotoXY(15,0);
  Print(week_value);             //顯示星期
  GotoXY(11,0);
  Print("Week"); //在液晶上顯示 字母 week 
  mdelay(50);                 //掃描延時 //}  }/**************************************************************
報警檢測與取消
**************************************************************/void warming(){
  if(temp_value>=TH)
     {if(SD==1&&SD!=0)ET0=1;}
 else {deng=0;ET0=0;SD=1;}
 out=1;if(out==0){ET0=0;SD=0;}}/**************************************************************
主程式
**************************************************************/void main(){
    TMOD=0x02;              //設定模式為定時器T0的模式2 (8位自動重灌計數初值的計數值)        
    TH0=0x03;               //設定計數器初值,靠TH0儲存重灌的計數值
    TL0=0x03;
    TR0=1;                  //啟動T0
    ET0=0;                  //關定時器T0中斷
    EA=1;
    P1=0;
    flag=1;           //時鐘停止標誌
    LCD_Initial();    //液晶初始化
    Initial_DS1302(); //時鐘晶片初始化
    up_flag=0;   //調整標誌位置零
    down_flag=0;  
    done=0;           //進入預設液晶顯示while(1){   
   while(done==1){
       keydone(); //進入調整模式
       warming();
   }   while(done==0)    {  
      show_time();
	  warming();
	  b=1;
	  while(b)							   //b為標誌量
	  {
		   a=(int)Read1302(DS1302_HOUR);   //獲取小時數	0x0x
		   b=(int)Read1302(DS1302_MINUTE); //獲取分鐘數	0x0x
	       c=(int)Read1302(DS1302_SECOND); //獲取秒鐘數	0x0x
		   warming();
		   if(b==0x00 && c==0x00){		   //實現整點報時
	              bee=0;				   
				  warming();
	       }else{
		          bee=1;
				  warming();
		   }    
		   if(a<0x08 || a>0x21){
		      b=1;
			  warming();
			  close_time(); //清屏 
		   }else{ 
		      b=0;
			  warming();	 
		   }
	  }
     flag=0;                  
     Setkey(); //掃描各功能鍵
	 warming();/*   while(1){
	 b=(int)Read1302(DS1302_MINUTE);
	 c=(int)Read1302(DS1302_SECOND);
	 if(b==0x00 && c==0x00){
	      bee=0;
	 }
   }*/
   }   }warming();   }//}/**************************************************************
定時器中斷
**************************************************************/void t0 (void) interrupt 1 using 1 {deng=!deng;}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482

LCD1602.h

#ifndef LCD_CHAR_1602#define LCD_CHAR_1602#include <intrins.h>sbit LcdRs = P2^0; //定義埠sbit LcdRw = P2^1;sbit LcdEn  = P2^2;sfr  DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.資料埠/********************************************************
內部等待函式
********************************************************/unsigned char LCD_Wait(void){LcdRs=0;LcdRw=1; _nop_();LcdEn=1; _nop_();
 LcdEn=0;return DBPort;}/*******************************************************
向LCD寫入命令或資料
*******************************************************/#define LCD_COMMAND 0      // Command#define LCD_DATA 1      // Data#define LCD_CLEAR_SCREEN 0x01      // 清屏#define LCD_HOMING  0x02      // 游標返回原點void LCD_Write(bit style, unsigned char input){LcdEn=0;LcdRs=style;LcdRw=0; _nop_();DBPort=input; _nop_();//注意順序LcdEn=1; _nop_();//注意順序LcdEn=0; _nop_();LCD_Wait();}/*****************************************************
設定顯示模式
*****************************************************/#define LCD_SHOW 0x04    //顯示開#define LCD_HIDE 0x00    //顯示關   #define LCD_CURSOR 0x02 //顯示游標#define LCD_NO_CURSOR 0x00    //無游標      #define LCD_FLASH 0x01    //游標閃動#define LCD_NO_FLASH 0x00    //游標不閃動void LCD_SetDisplay(unsigned char DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}/***************************************************
設定輸入模式
***************************************************/#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00      // default#define LCD_MOVE 0x01      // 畫面可平移#define LCD_NO_MOVE 0x00      //defaultvoid LCD_SetInput(unsigned char InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}/***************************************************
初始化LCD
***************************************************/void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38);           //8位資料埠,2行顯示,5*7點陣LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);    //開啟顯示, 無游標LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);       //AC遞增, 畫面不動}/***********************************************
液晶字元輸入的位置
************************************************/void GotoXY(unsigned char x, unsigned char y){if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}/************************************************
將字元輸出到液晶顯示
************************************************/void Print(unsigned char *str){while(*str!='\0'){LCD_Write(LCD_DATA,*str);str++;}}#endif123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105

DS1302.h

#ifndef _REAL_TIMER_DS1302_2009_6_28_#define _REAL_TIMER_DS1302_2009_6_28_sbit  DS1302_CLK = P1^6;              //實時時鐘時鐘線引腳 sbit  DS1302_IO  = P1^7;              //實時時鐘資料線引腳 sbit  DS1302_RST = P1^5;              //實時時鐘復位線引腳sbit  ACC0 = ACC^0;sbit  ACC7 = ACC^7;unsigned char week_value[2];char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;  //秒,分,時到日,月,年位閃的計數typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char  Year;unsigned char DateString[11];unsigned char 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(unsigned char d) //實時時鐘寫入一位元組(內部函式){ 
    unsigned char i;
    ACC = d;
    for(i=8; i>0; i--)
    {
        DS1302_IO = ACC0;            //相當於彙編中的 RRC
        DS1302_CLK = 1;
        DS1302_CLK = 0;
        ACC = ACC >> 1; 
    } }unsigned char DS1302OutputByte(void) //實時時鐘讀取一位元組(內部函式){ 
    unsigned char i;
    for(i=8; i>0; i--)
    {
        ACC = ACC >>1;          //相當於彙編中的 RRC 
        ACC7 = DS1302_IO;
        DS1302_CLK = 1;
        DS1302_CLK = 0;
    } 
    return(ACC); }void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要寫的資料{
    DS1302_RST = 0;
    DS1302_CLK = 0;
    DS1302_RST = 1;
    DS1302InputByte(ucAddr);        // 地址,命令 
    DS1302InputByte(ucDa);        // 寫1Byte資料
    DS1302_CLK = 1;
    DS1302_RST = 0;} unsigned char Read1302(unsigned char ucAddr) //讀取DS1302某地址的資料{
    unsigned char 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)  //獲取時鐘晶片的時鐘資料到自定義的結構型陣列{unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);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&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);}void DateToStr(SYSTEMTIME *Time)    //將時間年,月,日,星期資料轉換成液晶顯示字串,放到陣列裡DateString[]{   if(hide_year<2)                 //這裡的if,else語句都是判斷位閃爍,<2顯示資料,>2就不顯示,輸出字串為 2013-01-02
    {                               
  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] = Time->Week%10+'0';  //星期的資料另外放到 week_value[]陣列裡,跟年,月,日的分開存放,因為等一下要在最後顯示
}
  else
  {
    week_value[0] = ' ';
  }
  week_value[1] = '\0';
Time->DateString[10] = '\0'; //字串末尾加 '\0' ,判斷結束字元 */}void TimeToStr(SYSTEMTIME *Time)  //將時,分,秒資料轉換成液晶顯示字元放到陣列 TimeString[];{   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->DateString[8] = '\0';}void Initial_DS1302(void)   //時鐘晶片初始化{   unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80)       //判斷時鐘晶片是否關閉   
    {Write1302(0x8e,0x00); //寫入允許Write1302(0x8c,0x13); //以下寫入初始化時間 日期:13-01-02.星期: 3. 時間: 14:03:00Write1302(0x88,0x01);Write1302(0x86,0x02);Write1302(0x8a,0x07);Write1302(0x84,0x14);Write1302(0x82,0x03);Write1302(0x80,0x00);Write1302(0x8e,0x80); //禁止寫入}}#endif123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213

DS18B20.h

#ifndef DS18B20_H_2009_6_28#define DS18B20_H_2009_6_28#define uint unsigned int#define uchar unsigned charsbit DQ = P1^0;        //溫度傳送資料IO口int temp_value;      //溫度值unsigned char TempBuffer[5];  // 存放溫度的各個位的值/***********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(80); //精確延時 大於 480usDQ = 1;          //拉高匯流排delay_18B20(14);x=DQ;            //稍做延時後 如果x=0則初始化成功 x=1則初始化失敗delay_18B20(20);}/***********ds18b20讀一個位元組**************/  unsigned char 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){
  unsigned char i=0;
  for (i=8; i>0; i--)
  {
  DQ = 0;
  DQ = dat&0x01;
    delay_18B20(5);
  DQ = 1;
    dat>>=1;
 }}/**************讀取ds18b20當前溫度************/void ReadTemp(void){unsigned char a=0;unsigned char b=0;unsigned char t=0;Init_DS18B20();WriteOneChar(0xCC);    // 跳過讀序號列號的操作WriteOneChar(0x44); // 啟動溫度轉換delay_18B20(100);       // this message is wery importantInit_DS18B20();WriteOneChar(0xCC); //跳過讀序號列號的操作WriteOneChar(0xBE); //讀取溫度暫存器等(共可讀9個暫存器) 前兩個就是溫度delay_18B20(100);a=ReadOneChar();    //讀取溫度值低位b=ReadOneChar();    //讀取溫度值高位temp_value=b<<4;temp_value+=(a&0xf0)>>4;               }void temp_to_str()   //溫度資料轉換成液晶字元顯示{
  TempBuffer[0]=temp_value/10+'0';  //十位
  TempBuffer[1]=temp_value%10+'0';  //個位
  TempBuffer[2]=0xdf;   //溫度符號
  TempBuffer[3]='C';
  TempBuffer[4]='\0';}#endif123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100

1.6.2 上電後螢幕
通電後的LCD可以顯示出現在的日期,包括年月日星期還有時分秒,另外還有溫度的顯示。
在這裡插入圖片描述

1-11 通電後LCD螢幕
1.6.3 按鍵設定時間
按下設定按鍵時可對螢幕的時間進行調整。(加操作)
在這裡插入圖片描述

按下左邊第一個鍵,開啟調較按鈕,按下次數與對應關係如下:
1->秒調校
2->分調較
3->時調校
4->星期調校
5->日調校
6->月調校
7->年調校
8->確定的修改時間
 秒調校:
在這裡插入圖片描述

調教後的結果:
在這裡插入圖片描述

 分調節:
在這裡插入圖片描述

調校後的結果:
在這裡插入圖片描述

 時調校:
在這裡插入圖片描述

調較後: 在這裡插入圖片描述
在這裡插入圖片描述

1-12 按鍵設定
 星期修改:
在這裡插入圖片描述

修改星期後:

在這裡插入圖片描述
在這裡插入圖片描述

 日修改: 在這裡插入圖片描述

修改日後: /oldage/

在這裡插入圖片描述
在這裡插入圖片描述

 月修改:
在這裡插入圖片描述

修改月份後:

在這裡插入圖片描述
在這裡插入圖片描述

 年修改: 在這裡插入圖片描述

修改年份好:
在這裡插入圖片描述

在這裡插入圖片描述

1.6.4 小燈到指定時間閃爍,表示鬧鐘在指定時間(整點)響起。(從20:59——21:00實現報時)
在這裡插入圖片描述
在這裡插入圖片描述

1-14 小燈閃爍(鬧鈴響起)
1.6.5 順利完成定時顯示(早上8:00-晚上22:00開啟,晚上22:00-第二天早上8:00關閉)
 早上7:59-8:00實現跳轉 /jilin/

在這裡插入圖片描述

在這裡插入圖片描述

 晚上21:59-22:00實現跳轉 在這裡插入圖片描述
在這裡插入圖片描述

1.6.6 DS1302獲取溫度傳入螢幕,並設定溫度當溫度超過35攝氏度時實現報警
在這裡插入圖片描述

溫度>35攝氏度時,喇叭響。

在這裡插入圖片描述

1.4. 除錯中遇到的問題和解決方法  
(1)在調節時間和日期之後,微控制器上電更新的是PC的時間,後來查資料,是設定DS1302的問題,且存在一定的誤差且誤差在2-3s內,隨著執行的時間不斷增加,誤差會不斷地加大。
(2)按鍵操作時有時會出現功能不穩定,這是由於按鍵存在抖動,後來加個延時函式就可以去抖動,實現按鍵按下後馬上得到相應。
(3)調整日期時,使得日期與星期無法聯動。後期仍需要改進和修改。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30239065/viewspace-2733719/,如需轉載,請註明出處,否則將追究法律責任。

相關文章