基于51單片機(jī)的萬年歷的設(shè)計(jì).doc
《基于51單片機(jī)的萬年歷的設(shè)計(jì).doc》由會(huì)員分享,可在線閱讀,更多相關(guān)《基于51單片機(jī)的萬年歷的設(shè)計(jì).doc(27頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
單片機(jī)課程實(shí)訓(xùn) SCM PRACTICAL TRAINING 實(shí)訓(xùn)設(shè)計(jì)題目 Title Of Training 萬年歷的設(shè)計(jì) 分院(系別) Department ?! I(yè) Speciality 班 級(jí) Class 設(shè)計(jì)作者 Author 完成日期 Date 組 別 Team 指導(dǎo)教師 Advisor 目 錄 第一部分 課程設(shè)計(jì)任務(wù)書 1 一、課程設(shè)計(jì)題目 1 二、課程設(shè)計(jì)時(shí)間 1 三、實(shí)訓(xùn)提交方式 1 四、設(shè)計(jì)要求 1 第二部分 課程設(shè)計(jì)報(bào)告 2 一、單片機(jī)發(fā)展概況 2 二、MCS-51單片機(jī)系統(tǒng)簡(jiǎn)介 2 三、設(shè)計(jì)思想 3 四、硬件電路設(shè)計(jì) 3 1. 總體設(shè)計(jì) 3 2. 晶振電路 4 3. 復(fù)位電路 4 4. DS1302時(shí)鐘電路 5 5. 溫度采集系統(tǒng)電路 5 6. 按鍵調(diào)整電路 6 7. 鬧鐘提示電路 6 五、軟件設(shè)計(jì)框圖 7 六、程序源代碼 8 1. 主程序 8 2. 溫度控制程序 11 3. 日歷設(shè)置程序 13 4. 時(shí)鐘控制程序 18 5. 顯示設(shè)置程序 20 七、結(jié)束語 23 八、課程設(shè)計(jì)小組分工 24 九、參考文獻(xiàn) 24 第一部分 課程設(shè)計(jì)任務(wù)書 一、課程設(shè)計(jì)題目 用中小規(guī)模集成芯片設(shè)計(jì)制作萬年歷。 二、課程設(shè)計(jì)時(shí)間 五天 三、實(shí)訓(xùn)提交方式 提交實(shí)訓(xùn)設(shè)計(jì)報(bào)告電子版與紙質(zhì)版 四、設(shè)計(jì)要求 (1)顯示年、月、日、時(shí)、分、秒和星期,并有相應(yīng)的農(nóng)歷顯示。 (2)可通過鍵盤自動(dòng)調(diào)整時(shí)間。 (3)具有鬧鐘功能。 (4)能夠顯示環(huán)境溫度,誤差小于1℃ (5)計(jì)時(shí)精度:月誤差小于20秒。 第二部分 課程設(shè)計(jì)報(bào)告 一、單片機(jī)發(fā)展概況 單片機(jī)誕生于20世紀(jì)70年代末,它的發(fā)展史大致可分為三個(gè)階段: 第一階段(1976-1978):初級(jí)單片機(jī)微處理階段。該時(shí)期的單片機(jī)具有 8 位CPU,并行 I/O 端口、8 位時(shí)序同步計(jì)數(shù)器,尋址范圍 4KB,但是沒有串行口。 第二階段(1978-1982):高性能單片機(jī)微機(jī)處理階段,該時(shí)期的單片機(jī)具有I/O 串行端口,有多級(jí)中斷處理系統(tǒng),15 位時(shí)序同步技術(shù)器,RAM、ROM 容量加大,尋址范圍可達(dá) 64KB。 第三階段(1982-至今)位單片機(jī)微處理改良型及 16 位單片機(jī)微處理階段民用電子產(chǎn)品、計(jì)算機(jī)系統(tǒng)中的部件控制器、智能儀器儀表、工業(yè)測(cè)控、網(wǎng)絡(luò)與通信的職能接口、軍工領(lǐng)域、辦公自動(dòng)化、集散控制系統(tǒng)、并行多機(jī)處理系統(tǒng)和局域網(wǎng)絡(luò)系統(tǒng)。 二、MCS-51單片機(jī)系統(tǒng)簡(jiǎn)介 MCS-51系列單片機(jī)產(chǎn)品都是以Intel公司最早的典型產(chǎn)品8051為核心構(gòu)成的。MCS-51單片機(jī)由CPU 、RAM 、ROM 、I/O接口、定時(shí)器/計(jì)數(shù)器、中斷系統(tǒng)、內(nèi)部總線等部件組成。8051單片機(jī)的基本性能有: u 8位CPU; u 布爾代數(shù)處理器,具有位尋址能力; u 128B內(nèi)部RAM,21個(gè)專用寄存器; u 4KB內(nèi)部掩膜ROM; u 2個(gè)16位可編程二進(jìn)制加1定時(shí)器/計(jì)數(shù)器; u 32個(gè)(48位)雙向可獨(dú)立尋址的I/O口; u 1個(gè)全雙工UART(異步串行通信口); u 5個(gè)中斷源,兩級(jí)中斷結(jié)構(gòu) ; u 片內(nèi)振蕩器及時(shí)鐘電路 ,晶振頻率為1.2MHz~12MHz; u 外部程序/數(shù)據(jù)存儲(chǔ)器尋址空間均為64KB; u 111條指令,大部分為單字節(jié)指令; u 單一+5V電源供電,雙列直插40引腳DIP封裝。 三、設(shè)計(jì)思想 整體設(shè)計(jì)以單片機(jī)技術(shù)為核心,采用C語言進(jìn)行軟件設(shè)計(jì),增加了程序的可讀性和可移植性,為了便于擴(kuò)展和更改,軟件的設(shè)計(jì)采用模塊化結(jié)構(gòu)。程序先向LCD更新時(shí)鐘芯片的時(shí)間與溫度傳感器的時(shí)間,然后進(jìn)行初始化工作。程序由一個(gè)主函數(shù),兩個(gè)定時(shí)器中斷程序,一個(gè)時(shí)鐘設(shè)置子程序,一個(gè)農(nóng)歷設(shè)置子程序,一個(gè)溫度設(shè)置子程序,一個(gè)延時(shí)子程序,一個(gè)調(diào)時(shí)子程序,一個(gè)顯示子程序構(gòu)成。程序通過按鍵掃描程序來確定是否調(diào)用中斷程序來對(duì)時(shí)間進(jìn)行調(diào)整。用一子程序完成時(shí)分的調(diào)整,通過循環(huán)掃描四個(gè)按鍵的電平變化來判斷對(duì)應(yīng)按鍵是否按下,并帶有去抖動(dòng)功能,四個(gè)按鍵分別有增加,減小,退出與功能選擇的作用。通過功能選擇時(shí)鐘設(shè)置與鬧鐘設(shè)置,使用加或減按鍵進(jìn)行預(yù)置,完成后可點(diǎn)退出鍵完成操作。 可分為以下幾個(gè)功能模塊: 1)主程序:定時(shí)器中斷初始化、時(shí)鐘與溫度更新程序與鍵盤監(jiān)控。 2)計(jì)時(shí):為定時(shí)器中斷服務(wù)子程序,完成刷新計(jì)時(shí)緩沖區(qū)的功能。 3)農(nóng)歷:由陰歷換算對(duì)照表得出陽(yáng)歷并顯示。 4)鬧鐘:采用定時(shí)器中斷方式實(shí)現(xiàn)鬧鐘與整點(diǎn)報(bào)時(shí)。 5) 溫度:由溫度傳感器將溫度傳送到LCD顯示。 6)設(shè)置:由按鍵設(shè)置鬧鐘時(shí)間或時(shí)鐘時(shí)間。 7)鍵盤掃描:判斷是否有鍵按下,并確定鍵號(hào)。 8)LCD顯示:完成8位動(dòng)態(tài)顯示。 四、硬件電路設(shè)計(jì) 1. 總體設(shè)計(jì) 系統(tǒng)包括單片機(jī)主控模塊,溫度傳感器采集模塊,日歷時(shí)鐘模塊,按鍵調(diào)整模塊,蜂鳴器模塊,鬧鐘模塊。如圖1所示為系統(tǒng)設(shè)計(jì)圖。 日歷時(shí)鐘芯片 DS1302 按鍵調(diào)整 電路 AT89C51 單片機(jī) 溫度傳感器 DS18B20 LCD12864 蜂鳴器鬧鐘 圖1 系統(tǒng)設(shè)計(jì)圖 如圖2所示為系統(tǒng)仿真圖。 圖2 系統(tǒng)仿真圖 2. 晶振電路 如圖3所示,51單片機(jī)的內(nèi)部有一個(gè)用于構(gòu)成振蕩器的高增益反相放大器,它的輸入端為XTAL1引腳,輸出端為XTAL2引腳,兩個(gè)跨接石英晶體及兩個(gè)電容就可以構(gòu)成穩(wěn)定的自激振蕩器。電容器通常取30pF左右。 圖3 晶振電路 圖4 復(fù)位電路 3. 復(fù)位電路 往單片機(jī)的復(fù)位引腳上輸入24個(gè)時(shí)鐘周期以上的高電平,即執(zhí)行復(fù)位操作。按鍵復(fù)位是指系統(tǒng)在運(yùn)行時(shí),按下一個(gè)開關(guān),就能在RST引腳產(chǎn)生一段時(shí)間的高電平,使系統(tǒng)復(fù)位,常見的按鍵復(fù)位電路如圖4所示。對(duì)12MHz晶振頻率而言,電路中C取10pF,R取1KΩ。 4. DS1302時(shí)鐘電路 DS1302是一種高性能、低功耗、帶RAM的實(shí)時(shí)時(shí)鐘電路,它可以對(duì)年、月、日、周日、 時(shí)、分、秒進(jìn)行計(jì)時(shí),具有閏年補(bǔ)償功能,工作電壓為2.5V~5.5V。采用三線接口與CPU進(jìn)行同步通信,并可采用突發(fā)方式一次傳送多個(gè)字節(jié)的時(shí)鐘信號(hào)或RAM數(shù)據(jù)。DS1302內(nèi)部有一個(gè)318的用于臨時(shí)性存放數(shù)據(jù)的RAM寄存器。DS1302是DS1202的升級(jí)產(chǎn)品,與DS1202兼容,但增加了主電源/后背電源雙電源引腳,同時(shí)提供了對(duì)后背電源進(jìn)行涓細(xì)電流充電的能力。 圖5示出DS1302的引腳排列,其中Vcc1為后備電源,Vcc2為主電源。在主電源關(guān)閉的情況下,也能保持時(shí)鐘的連續(xù)運(yùn)行。DS1302由Vcc1或Vcc2兩者中的較大者供電。當(dāng)Vcc2大于Vcc1+0.2V時(shí),Vcc2給DS1302供電。當(dāng)Vcc2小于Vcc1時(shí),DS1302由Vcc1供電。X1和X2是振蕩源,外接32.768KHz晶振。RST是復(fù)位/片選線,通過把RST輸入驅(qū)動(dòng)置高電平來啟動(dòng)所有的數(shù)據(jù)傳送。RST輸入有兩種功能:首先,RST接通控制邏輯,允許地址/命令序列送入移位寄存器;其次,RST提供終止單字節(jié)或多字節(jié)數(shù)據(jù)的傳送手段。當(dāng)RST為高電平時(shí),所有的數(shù)據(jù)傳送被初始化,允許對(duì)DS1302進(jìn)行操作。如果在傳送過程中RSTS置為低電平,則會(huì)終止此次數(shù)據(jù)傳送,I/O引腳變?yōu)楦咦钁B(tài)。上電動(dòng)行時(shí),在Vcc大于等于2.5V之前,RST必須保持低電平。中有在SCLK為低電平時(shí),才能將RST置為高電平,I/O為串行數(shù)據(jù)輸入端(雙向)。SCLK始終是輸入端。 圖5 DS1302時(shí)鐘芯片 圖6 溫度采集系統(tǒng)電路 5. 溫度采集系統(tǒng)電路 在本萬年歷當(dāng)中溫度的采集采用數(shù)字溫度傳感器DS18B20。它屬于單總線器件,具有線路簡(jiǎn)單,體積小的特點(diǎn)。因此用它來組成一個(gè)測(cè)溫系統(tǒng),具有線路簡(jiǎn)單,在一根通信線,可以掛很多這樣的數(shù)字溫度計(jì),十分方便。 具有如下的經(jīng)濟(jì)特點(diǎn):(1)只要求一個(gè)端口即可實(shí)現(xiàn)通信。(2)在DS18B20中的每個(gè)器件上都有獨(dú)一無二的序列號(hào)。(3)實(shí)際應(yīng)用中不需要外部任何元器件即可實(shí)現(xiàn)測(cè)溫。(4)測(cè)量溫度范圍在-55。C到+125。C之間。(5)數(shù)字溫度計(jì)的分辨率用戶可以從9位到12位選擇。(6)內(nèi)部有溫度上、下限告警設(shè)置。如圖6所示。 6. 按鍵調(diào)整電路 按鍵采用4個(gè)獨(dú)立的按鍵,一個(gè)功能鍵、一個(gè)退出鍵、一個(gè)加按鍵、一個(gè)減按鍵通過這四個(gè)按鍵可以來合理的設(shè)置時(shí)鐘的調(diào)整和鬧鈴的設(shè)置等。如圖7所示與51單片機(jī)的P0.0~P0.3的連接示意圖。 圖7 按鍵調(diào)整電路 7. 鬧鐘提示電路 當(dāng)?shù)竭_(dá)整點(diǎn)時(shí)或者當(dāng)前的時(shí)間等于51單片機(jī)中設(shè)置鬧鐘時(shí)間時(shí)蜂鳴器便會(huì)發(fā)出聲音進(jìn)行提示。與單片機(jī)P0.5引腳的連接電路如圖8所示。 圖8 鬧鐘提示電路 圖9 LCD顯示電路 8. LCD顯示電路 在本萬年歷當(dāng)中12864液晶顯示當(dāng)前的實(shí)時(shí)時(shí)間重要的陰陽(yáng)歷節(jié)日等功能。12864液晶具有如下的特性: 1)提供8位,4位并行接口及串行接口可選 2)并行接口適配M6800時(shí)序 3)自動(dòng)電源啟動(dòng)復(fù)位功能 4)內(nèi)部自建振蕩源 6416位字符顯示RAM(DDRAM最多16字符4行,LCD顯示范圍162行)(改為半角輸入) 2M位中文字型ROM(CGROM),總共提供8192個(gè)中文字型(1616點(diǎn)陣)16K位半寬字型ROM(HCGROM),總共提供126個(gè)西文字型(168點(diǎn)陣)6416位字符產(chǎn)生RAM(CGRAM) 1516位總共240點(diǎn)的ICONRAM(ICONRAM)其與單片機(jī)的連接電路如圖9所示。 五、軟件設(shè)計(jì)框圖 1. 主程序流程圖: 2. 陰陽(yáng)歷轉(zhuǎn)換流程圖: 六、程序源代碼 1. 主程序 #include < reg52.h > #include < nongli.h > #include < lcd.h > #include < shezhi.h > #include < time.h> #include < wendu.h > #include < key.h > #define uchar unsigned char #define uint unsigned int /******************************************************************** sbit bell = P2 ^ 0; //定義蜂鳴器端口 /******************************************************************** 定時(shí)器設(shè)置整點(diǎn)報(bào)時(shí) ********************************************************************/ void Timer0_Service() interrupt 1 { static uchar count = 0; static uchar flag = 0; //記錄鳴叫的次數(shù) count = 0; TR0 = 0; //關(guān)閉Timer0 TH0 = 0x3c; TL0 = 0XB0; //延時(shí) 50 ms TR0 = 1 ; //啟動(dòng)Timer0 count ++; if( count == 20 ) //鳴叫 1 秒 { bell = ~ bell; count = 0; flag ++; } if( flag == 6 ) { flag = 0; TR0 = 0; //關(guān)閉Timer0 } } /******************************************************************** 中斷服務(wù)程序 整點(diǎn)報(bào)時(shí) 一分鐘 ********************************************************************/ uchar HexNum_Convert(uchar HexNum)//將16進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù) { uchar Numtemp; Numtemp=(HexNum>>4)*10+(HexNum&0X0F); return Numtemp; } /******************************************************************** * 函數(shù)名稱:main() * 功 能: * 入口參數(shù): * 出口參數(shù): ********************************************************************/ void main( void ) { uchar clock_time[6] = {0X00,0X59,0X23,0X09,0X04,0X11}; //定義時(shí)間變量 秒 分 時(shí) 日 月 年 uchar alarm_time[2] = { 10, 06}; //鬧鐘設(shè)置 alarm_time[0]: 分鐘 alarm_time[1] :小時(shí) uchar temperature[2]; //定義溫度變量 temperature[0] 低8位 temperature[1] 高8位 Lcd_Initial(); //LCD初始化 Clock_Fresh( clock_time ); //時(shí)間刷新 Clock_Initial( clock_time ); //時(shí)鐘初試化 /***********************中斷初始化***************************/ EA = 1; //開總中斷 ET0 = 1; //Timer0 開中斷 ET2 = 1; //Timer2 開中斷 TMOD = 0x01 ; //Timer0 工作方式 1 RCAP2H = 0x3c; RCAP2L = 0xb0; //Timer2 延時(shí) 50 ms while( 1 ) { switch( Key_Scan() ) //按鍵掃描 { case up_array: { Key_Idle(); //檢測(cè)按鍵松開 } break; case down_array: { Key_Idle(); //檢測(cè)按鍵松開 } break; case clear_array: { Key_Idle(); //檢測(cè)按鍵松開 } break; case function_array:{ Key_Function( clock_time, alarm_time ); } case null: { Clock_Fresh( clock_time ); //時(shí)間刷新 Lcd_Clock( clock_time ); //時(shí)間顯示 Sensor_Fresh( temperature ); //溫度更新 Lcd_Temperture( temperature ); //溫度顯示 Calendar_Convert( 0 , clock_time ); Week_Convert( 0, clock_time ); //整點(diǎn)報(bào)時(shí) if( ( * clock_time == 0x59 ) && ( * ( clock_time + 1 ) == 0x59 ) ) { bell = 0; TR2 = 1; //啟動(dòng)Timer2 }//鬧鐘報(bào)警 if( * alarm_time == HexNum_Convert(* ( clock_time + 1 ) ))//分鐘相吻if( * ( alarm_time + 1 ) == HexNum_Convert(*( clock_time + 2 )) ) //小時(shí)相吻合 { bell = 0; TR2 = 1; //啟動(dòng)Timer2 } } break; } } } 2. 溫度控制程序 #ifndef _SENSOR #define _SENSOR #define uchar unsigned char #define uint unsigned int /***************DS18B20管腳配置*******/ sbit dq = P2 ^ 1; /********************************************************************DS18B20軟件延時(shí)專用 ********************************************************************/ void Sensor_Delay(uchar count)//延時(shí)函數(shù) { while(count--); } /********************************************************************從DS18B20讀一個(gè)字節(jié) ********************************************************************/ uchar Sensor_Read_Byte(void) { uchar i = 0; uchar temp = 0; for(i=8;i>0;i--) { dq = 0; // 給脈沖信號(hào) temp >>= 1; dq = 1; // 給脈沖信號(hào) if(dq) temp |= 0x80; Sensor_Delay(20); } return (temp); } /********************************************************************向DS18B20寫一個(gè)字節(jié) ********************************************************************/ void Sensor_Write_Byte(uchar temp) { uchar i = 0; for(i=8;i>0;i--) { dq = 0; dq = temp&0x01; Sensor_Delay(20); dq = 1; temp>>=1; } } /******************************************************************** DS18B20初始化 ********************************************************************/ uchar Sensor_Initial(void) { uchar i = 0; dq = 1; // DQ復(fù)位 Sensor_Delay(1); // 稍做延時(shí) dq = 0; // 單片機(jī)將DQ拉低 Sensor_Delay(100); // 精確延時(shí),大于480us dq = 1; // 拉高總線 Sensor_Delay(6); // 稍做延時(shí)后 i = dq; // 若x=0則初始化成功,若x=1則初始化失敗 Sensor_Delay(130); return (~i); } /******************************************************************** 讀取并顯示溫度 ********************************************************************/ void Sensor_Fresh(uchar * temperature ) { Sensor_Initial(); Sensor_Write_Byte( 0xCC ); // 跳過讀序號(hào)列號(hào)的操作 Sensor_Write_Byte( 0x44 ); // 啟動(dòng)溫度轉(zhuǎn)換 Sensor_Initial(); Sensor_Write_Byte( 0xCC ); // 跳過讀序號(hào)列號(hào)的操作 Sensor_Write_Byte( 0xBE ); // 讀取溫度寄存器 temperature [0] = Sensor_Read_Byte(); //低位 temperature [1] = Sensor_Read_Byte(); //高位 }#endif 3. 日歷設(shè)置程序 #ifndef _SUN_MOON #define _SUN_MOON /*************************************************************************/ #define uchar unsigned char #define uint unsigned int #include < shezhi.h > #include < lcd.h > /******************************************************************** * 功能: 讀取數(shù)據(jù)表中農(nóng)歷的大月或小月 ,如果大月返回1, 小月返回0 ********************************************************************/ bit get_moon_day( uchar month_p,uint calendar_address ) { uchar temp,temp1; temp1=(month_p+3)/8; temp=0x80>>((month_p+3)%8); temp=year_code[calendar_address+temp1]&temp; if(temp==0){return(0);}else{return(1);} } /******************************************************************** * 功能: 輸入BCD的陽(yáng)歷數(shù)據(jù), 輸出BCD陰歷數(shù)據(jù)( 1901 - 2099 ) c_flag:陽(yáng)歷的世紀(jì)標(biāo)志 clock_time: 時(shí)鐘地址 * 說明: c_flag = 0 :21世紀(jì) c_flag = 1 :19世紀(jì) ********************************************************************/ void Calendar_Convert( uchar c_flag, uchar * clock_time ) { bit flag_month, flag_year; uchar year, month, day, month_point; //定義 年 月 天 uchar temp1, temp2, temp3; uint calendar_address; //定義農(nóng)歷地址 uint day_number; uchar clock_moon[3]; //定義陰歷 clock_time += 3; //指向日 day = ( * clock_time >> 4 ) * 10 + ( *clock_time & 0x0f ); //BCD轉(zhuǎn)換十進(jìn)制 clock_time ++; //指向月 month = ( * clock_time >> 4 ) * 10 + ( * clock_time & 0x0f ); //BCD轉(zhuǎn)換十進(jìn)制 clock_time ++; //指向年 year = ( * clock_time >> 4 ) * 10 + ( * clock_time & 0x0f ); //BCD轉(zhuǎn)換十進(jìn)制 //定位日歷地址 if( c_flag == 0 ) calendar_address = ( year + 99 ) * 3; else calendar_address = ( year - 1 ) * 3; //春節(jié)(正月初一)所在的陽(yáng)歷月份 temp1 = year_code[ calendar_address + 2 ] & 0x60; //Bit6~~Bit5:春節(jié)所在的陽(yáng)歷月份 temp1 >>= 5 ; //春節(jié)(正月初一)所在的陽(yáng)歷日期 temp2 = year_code[ calendar_address + 2 ] & 0x1f; //Bit4~~Bit0:春節(jié)所在的陽(yáng)歷日期 //計(jì)算春節(jié)(正月初一)離當(dāng)年元旦{ 1月1日(陽(yáng)歷) }的天數(shù);春節(jié)只會(huì)在陽(yáng)歷的1月 或 2月 /*if( temp1 == 1 ) temp3 = temp2 - 1; else temp3 = temp2 + 31 - 1; */ temp3=temp2-1; if(temp1!=1) temp3+=0x1f; //計(jì)算陽(yáng)歷月離當(dāng)年元旦{ 1月1日(陽(yáng)歷) }的天數(shù) if( month < 10 ) {day_number = day_code1[ month - 1 ] + day ;} else {day_number = day_code2[ month - 10 ] + day ;} //如果陽(yáng)歷的月大于2 且該年的2月為閏月,天數(shù)加1 //閏年指的就是陽(yáng)歷有閏日或陰歷有閏月的一年; //陽(yáng)歷四年一閏,在二月加一天,這一天叫做閏日: //農(nóng)歷三年一閏,五年兩閏,十九年七閏,每逢閏年所加的一個(gè)月叫做閏月。 if( ( month <= 2 ) || ( year % 0x04!= 0) ) day_number-=1; // day_number ++; // if ((month<2)||(year%0x04!=0)) // day_number-=1; //判斷陽(yáng)歷日 在春節(jié)(正月初一) 之前 還是 之后 if( day_number >= temp3 ) //陽(yáng)歷在春節(jié)之后 或者 春節(jié)當(dāng)日 { day_number -= temp3; month = 1; month_point = 1; // month_point 為月份指向,陽(yáng)歷日在春季前就是春季 flag_month = get_moon_day( month_point, calendar_address ); //檢查該陰歷月的大小 大月返回1 小月返回0 flag_year = 0; /* if( flag_month ) temp1 = 30; //大月30天 else temp1 = 29; //小月29天 */ if (flag_month==0) {temp1=29;} else{temp1=30;} //閏月所在的月分 temp2 = year_code[ calendar_address ] & 0xf0; temp2 >>= 4; //提取高四位 假如是0 表示沒有閏月 while( day_number >= temp1 ) { day_number -= temp1; month_point ++; if( month == temp2 ) { flag_year = ~ flag_year; if( flag_year == 0 ) month +=1; } else month ++ ; flag_month = get_moon_day( month_point, calendar_address ); if( flag_month ) temp1 = 30; else temp1 = 29; } day = day_number + 1; } else //陽(yáng)歷在春節(jié)之前使用以下代碼進(jìn)行運(yùn)算 { temp3 -= day_number; if( year == 0 ) { year = 0xe3; c_flag = 1; } else year -= 1; calendar_address -= 3; month = 0xc; temp2 = year_code[ calendar_address ] & 0xf0; temp2 >>= 4; //提取高4位 flag_year=0; if( temp2 == 0 ) month_point = 12; else month_point = 13; //flag_year = 0; flag_month = get_moon_day( month_point, calendar_address ); if( flag_month ) temp1 = 30; else temp1 = 29; while( temp3 > temp1 ) { temp3 -= temp1; month_point --; if( flag_year == 0 ) month -=1; if( month == temp2 ) flag_year = ~ flag_year; flag_month = get_moon_day( month_point, calendar_address ); if( flag_month ) temp1 = 0x1e; else temp1 = 0x1d; } day = temp1 - temp3 + 1; } //HEX->BCD ,運(yùn)算結(jié)束后,把數(shù)據(jù)轉(zhuǎn)換為BCD數(shù)據(jù) temp1 = year / 10; temp1 <<= 4; clock_moon[2] = temp1 | ( year % 10 ); temp1 = month / 10; temp1 <<= 4; clock_moon[1] = temp1 | ( month % 10 ); temp1 = day / 10; temp1 <<= 4; clock_moon[0] = temp1 | ( day % 10 ); Lcd_Lunar_Calendar( clock_moon ); } /******************************************************************** 算法: ( 日期 + 年份 + 所過閏年 + 月校正 ) / 7 的余數(shù)就是星期 如果是閏年又不到 3 月份上述之和 要減一天 再 ********************************************************************/ void Week_Convert( bit c, uchar * clock_time ) { uchar year, month, day; //定義 年 月 天 uchar temp; clock_time += 3; //指向日 day = ( * clock_time >> 4 ) * 10 + ( *clock_time & 0x0f ); //BCD轉(zhuǎn)換十進(jìn)制 clock_time ++; //指向月 month = ( * clock_time >> 4 ) * 10 + ( * clock_time & 0x0f ); clock_time ++; //指向年 year = ( * clock_time >> 4 ) * 10 + ( * clock_time & 0x0f ); if( c == 0 ) //如果為21世紀(jì),年份數(shù)加100 year += 100; temp = year / 4; //所過閏年數(shù)只算1900年之后的 temp = year + temp; temp = temp % 0x07; //為節(jié)省資源,先進(jìn)行一次取余,避免數(shù)大于0xff,避免使用整型數(shù)據(jù) temp = temp + day + table_week[ month - 1 ]; if( ( year % 4 == 0 ) && ( month <3 ) ) temp -=1; Lcd_Week( temp % 7 ); } /*******************************************************************/ #endif 4. 時(shí)鐘控制程序 #ifndef _REAL_TIMER_DS1302 #define _REAL_TIMER_DS1302 /*****************************預(yù)定義**************************************/ #define uchar unsigned char #define uint unsigned int/***************************DS1302管腳配置****************************/ sbit clock_rst = P2^4; sbit clock_io = P2^3; sbit clock_sclk= P2^2; /*********************為了編程方便定義的位變量**********************/ sbit ACC0 = ACC ^ 0; sbit ACC7 = ACC ^ 7; #define second_address 0x80 #define minute_address 0x82 #define hour_address 0x84 #define day_address 0x86 #define month_address 0x88 #define year_address 0x8C /******************************************************************** * 功 能:向時(shí)鐘DS1302寫入一個(gè)字節(jié) ********************************************************************/ void Clock_Write_Byte(uchar temp) { uchar i; ACC=temp; for(i=8; i>0; i--) { clock_io = ACC0; //相當(dāng)于匯編中的 RRC clock_sclk = 1; clock_sclk = 0; ACC = ACC >> 1; } } /******************************************************************** * 功 能:從時(shí)鐘DS1302讀取一個(gè)字節(jié) ********************************************************************/ uchar Clock_Read_Byte(void) { uchar i; for(i=8; i>0; i--) { ACC = ACC >>1; //相當(dāng)于匯編中的 RRC ACC7= clock_io; clock_sclk = 1; clock_sclk = 0; } return(ACC); } /******************************************************************** * 功 能:向時(shí)鐘DS1302寫入一個(gè)時(shí)間 ********************************************************************/ void Clock_Write_Time(uchar address, uchar temp) { clock_sclk=0; clock_rst=0; clock_rst=1; Clock_Write_Byte(address); Clock_Write_Byte(temp); clock_rst=0; clock_sclk=1; } /******************************************************************** * 功 能:從時(shí)鐘DS1302讀出一個(gè)時(shí)間 ********************************************************************/ uchar Clock_Read_Time(uchar address) { uchar temp=0; clock_sclk=0; clock_rst=0; clock_rst=1; Clock_Write_Byte( address|0x01 ); temp=Clock_Read_Byte(); clock_rst=0; clock_sclk=1; return(temp); } /******************************************************************** * 功 能:時(shí)鐘初始化 ********************************************************************/ void Clock_Initial(uchar *clock_time ) { Clock_Write_Time(0x8e,0x00); //WP=0 寫操作 *clock_time &= 0x7f; //最高位為 0 時(shí)鐘芯片工作 Clock_Write_Time( second_address, * clock_time ); //秒 clock_time ++; Clock_Write_Time( minute_address, * clock_time ); //分 clock_time ++; Clock_Write_Time( hour_address, * clock_time ); //時(shí) clock_time ++; Clock_Write_Time( day_address, * clock_time ); //日 clock_time ++; Clock_Write_Time( month_address, * clock_time); //月 clock_time ++; Clock_Write_Time( year_address, * clock_time ); //年 Clock_Write_Time( 0x8e,0x80); //WP=1 寫保護(hù) } /********************************************************************* 功 能:從時(shí)鐘DS1302讀出時(shí)間 ********************************************************************/ void Clock_Fresh(uchar * clock_time ) { * clock_time = Clock_Read_Time( second_address ); //讀秒 clock_time ++; * clock_time = Clock_Read_Time( minute_address ); //讀分 clock_time ++; * clock_time = Clock_Read_Time( hour_address ); //讀時(shí) clock_time ++; * clock_time = Clock_Read_Time( day_address ); //讀日 clock_time ++; * clock_time = Clock_Read_Time( month_address ); //讀月 clock_time ++; *clock_time = Clock_Read_Time( year_address ); //讀年 } #endif 5. 顯示設(shè)置程序 #ifndef _LCD_12864 #define _LCD_12864 /***********************預(yù)定義**************************************/ #define uchar unsigned char #define uint unsigned int/***************************12864管腳配置****************************/ #define- 1.請(qǐng)仔細(xì)閱讀文檔,確保文檔完整性,對(duì)于不預(yù)覽、不比對(duì)內(nèi)容而直接下載帶來的問題本站不予受理。
- 2.下載的文檔,不會(huì)出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請(qǐng)點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
9.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁(yè)顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國(guó)旗、國(guó)徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對(duì)作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 基于 51 單片機(jī) 萬年歷 設(shè)計(jì)
鏈接地址:http://www.820124.com/p-6682727.html