多功能電子萬年歷設(shè)計論文_第1頁
多功能電子萬年歷設(shè)計論文_第2頁
多功能電子萬年歷設(shè)計論文_第3頁
多功能電子萬年歷設(shè)計論文_第4頁
多功能電子萬年歷設(shè)計論文_第5頁
已閱讀5頁,還剩71頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、江蘇大學(xué)第六屆電子設(shè)計競賽多功能電子萬年歷作品論文參賽隊員:胡建冬(電信科技1302)二零一四年四月【摘要】 該電子萬年歷實現(xiàn)了陽歷年、月、日、星期、時、分、秒、閏平年的顯示,以及對應(yīng)陰歷的日期和閏平年的顯示,同時實現(xiàn)了定時報警、日程提醒和語音報時功能,并可用按鍵選擇菜單以實現(xiàn)對時間和語音報時模式進行調(diào)整。電子萬年歷的硬件部分采用STC89C52RC為主控芯片,時鐘芯片DS1302、液晶LCD1602、語音芯片NY3P065A、5個輕觸開關(guān)等組成外圍電路。軟件部分是基于51單片機的C語言程序, 編譯環(huán)境是Keil。【關(guān)鍵詞】 多功能電子萬年歷 單片機 時鐘芯片 液晶 語音芯片 目 錄1、 設(shè)計

2、任務(wù)與要求41.1 設(shè)計任務(wù)41.2 要求4(1) 基本要求4(2) 選做部分41.3 完成功能4(1) 基本要求4(2) 選做部分41.4 未完成功能42、 方案比較與選擇42.1 主控模塊42.2 時鐘模塊52.3 顯示模塊52.4 語音報時模塊62.5 按鍵模塊62.6 存儲模塊73、 硬件電路的設(shè)計與仿真73.1 硬件電路設(shè)計7(1) 主控模塊7(2) 時鐘模塊8(3) 顯示模塊9(4) 語音報時模塊9(5) 按鍵模塊103.2 硬件電路仿真104、 萬年歷軟件設(shè)計114.1 陽歷轉(zhuǎn)陰歷程序114.2 main函數(shù)244.3 時鐘模塊554.4 顯示模塊604.5 語音報時模塊654.

3、6 存儲模塊704.7 液晶顯示漢字程序734.8 延時子函數(shù)模塊74作者簡介751、 設(shè)計任務(wù)與要求1.1 設(shè)計任務(wù)用實驗室提供的或自主購買的MSP430開發(fā)裝置,設(shè)計一個具有多種功能的電子萬年歷。1.2 要求(1) 基本要求a) 能顯示陽歷年、月、日、星期、小時、分、秒b) 顯示模塊采用LCD液晶顯示,要求能用按鍵調(diào)整時間。c) 能顯示陰歷月、日,在顯示陰歷時間時能標(biāo)明是否為閏年。d) 具有定時報警功能,能夠進行整點和半點語音報時。(2) 選做部分a) 掉電存儲功能,可存儲掉電前用戶定時設(shè)置。b) 具有日程管理,可以設(shè)定指定日期的日程,可以設(shè)置日程的提醒時間,并可用語音進行提示。c) 可以

4、保存30個日程設(shè)定,每個日程的提醒采用音樂提醒,至少有5首歌曲進行選擇播放,提示音樂具有重復(fù)播放功能。1.3 完成功能(1) 基本要求a) 能顯示陽歷年、月、日、星期、小時、分、秒b) 顯示模塊采用LCD液晶顯示,能用按鍵調(diào)整時間。c) 能顯示陰歷月、日,在顯示陰歷時間時能標(biāo)明是否為閏年。d) 具有定時報警功能,能夠進行整點和半點語音報時。(2) 選做部分a) 掉電存儲功能,可存儲掉電前用戶定時設(shè)置。b) 具有日程管理,可以設(shè)定指定日期的日程,可以設(shè)置日程的提醒時間,并用語音進行提示。1.4 未完成功能可以保存30個日程設(shè)定,每個日程的提醒采用音樂提醒,至少有5首歌曲進行選擇播放,提示音樂具有

5、重復(fù)播放功能。2、 方案比較與選擇2.1 主控模塊方案一:采用MSP430為主控芯片。MSP430系列單片機是美國德州儀器(TI)1996年開始推向市場的一種16位超低功耗、具有精簡指令集(RISC)的混合信號處理器。MSP430處理能力強、運算速度快、片內(nèi)資源豐富,它們分別是看門狗(WTD)、模擬比較器A、定時器A0(Timer_A0)、定時器A1(Timer_A1)、定時器B0(Timer_B0)、UART、SPI、I2C、硬件乘法器、液晶驅(qū)動器、10位/12位ADC、16位- ADC、DMA、I/O端口、基本定時器(Basic Timer)、實時時鐘(RTC)和USB控制器等若干外圍模塊

6、的不同組合。方案二:采用STC89C52RC為主控芯片。STC89C52RC是STC公司生產(chǎn)的一種低功耗、高性能CMOS8位微控制器,具有 8K 在系統(tǒng)可編程Flash存儲器。 具有以下標(biāo)準(zhǔn)功能: 8k字節(jié)Flash,512字節(jié)RAM, 32 位I/O 口線,看門狗定時器,內(nèi)置4KB EEPROM,MAX810復(fù)位電路,3個16 位定時器/計數(shù)器,4個外部中斷,一個7向量4級中斷結(jié)構(gòu)(兼容傳統(tǒng)51的5向量2級中斷結(jié)構(gòu))。相比較而言,MSP430雖然片內(nèi)資源豐富,但價格較高,且電子萬年歷只需單片機的少部分資源,如果選用MSP430會造成資源浪費;而STC89C52RC價格相對較低,且內(nèi)部資源已能

7、滿足電子萬年歷的需要,所以選擇方案二。2.2 時鐘模塊方案一:采用DS12C887為時鐘芯片。DS12C887可計算到2100年前的秒、分、小時、星期、日期、月、年七種日歷信息并帶閏年補償;自帶晶體振蕩器和鋰電池,在沒有外部電源的情況下可工作10年,對于一天內(nèi)的時間記錄,有12小時制和24小時制兩種模式;在12小時制模式中,用AM和PM區(qū)分上午和下午,可選用夏令時模式,時間表示方法有兩種:一種用二進制數(shù)表示,一種用BCD碼表示。方案二:采用DS1302為時鐘芯片。DS1302可提供年、月、日、星期、時、分、秒,一個月小與31天時可以自動調(diào)整,且具有閏年補償功能,即每月的天數(shù)和閏年的天數(shù)可自動調(diào)

8、整;時鐘操作可通過AM/PM指示決定采用24或12小時格式。工作電壓寬達2.55.5V。采用雙電源供電(主電源和備用電源),可設(shè)置備用電源充電方式,提供了對后背電源進行涓細(xì)電流充電的能力。相比較而言,DS12C887雖然功能齊全,但價格較高,約是DS1302的20倍;而如果給DS1302配上晶振與備用電源也能達到與DS12C887相同的效果,且DS1302的價格較低。所以選擇方案二。2.3 顯示模塊方案一:選用LCD12864作為顯示模塊。LCD12864是一種具有4 位/8 位并行、2 線或3 線串行多種接口方式,內(nèi)部含有國標(biāo)一級、二級簡體 中文字庫的點陣圖形液晶顯示模塊;其顯示分辨率為12

9、8×64,內(nèi)置8192 個16*16 點漢字,和128 個16*8 點ASCII 字符 集。利用該模塊靈活的接口方式和簡單、方便的操作指令,可構(gòu)成全中文人機交互圖形界面??梢燥@示8×4 行16×16 點 陣的漢字。也可完成圖形顯示.低電壓低功耗是其又一顯著特點。方案二:選用LCD1602作為顯示模塊。1602液晶也叫1602字符型液晶,它是一種專門用來顯示字母、數(shù)字、符號等的點陣型液晶模塊。它由若干個5X7或者5X11等點陣字符位組成,每個點陣字符位都可以顯示一個字符,每位之間有一個點距的間隔,每行之間也有間隔。用戶可以自定義CGRAM,顯示8個自定義字符。160

10、2LCD是指顯示的內(nèi)容為16X2,即可以顯示兩行,每行16個字符液晶模塊(顯示字符和數(shù)字)。相比較而言,LCD12864的顯示功能強大,可以顯示漢字,做出良好的人機界面,缺點是價格較高;LCD1602雖不能顯示漢字,但用來顯示萬年歷已夠用,并且價格只有LCD12864的1/3左右。所以選擇方案二。2.4 語音報時模塊語音報時模塊選用NY3P065A芯片。NY3P065A是一次性燒錄的語音OTP芯片,具有體積小巧、質(zhì)量穩(wěn)定、價格低廉等優(yōu)點??梢源锌刂?、并行控制、按鍵控制等。是一種理想的語音OTP。NY3P065A還可以直接驅(qū)動喇叭(PWM)。該電子萬年歷采用的就是直接驅(qū)動喇叭(8歐姆,0.25

11、瓦)。下圖就是該語音芯片所能報的內(nèi)容:圖1 語音芯片內(nèi)容2.5 按鍵模塊按鍵模塊采用5個輕觸開關(guān)。其中4個分別為K1、K2、K3、K4用作萬年歷的調(diào)整。K1用來在時間顯示與菜單選擇之間進行切換:K2是選擇/確定鍵;K3與K4分別用作所調(diào)整的地方減1、加1。剩余的1個作為萬年歷的復(fù)位開關(guān),用來處理系統(tǒng)故障。選擇輕觸開關(guān)作為按鍵模塊,既能實現(xiàn)所需功能,又可以節(jié)省成本。2.6 存儲模塊存儲部分用的是STC89C52RC內(nèi)部的EEPROM。STC89C52RC內(nèi)帶2K字節(jié)EEPROM存儲空間,(其實是采用ISP/IAP 技術(shù)讀寫內(nèi)部FLASH 來實現(xiàn)EEPROM),這樣就節(jié)省了片外資源,使用起來也更加

12、方便。3、 硬件電路的設(shè)計與仿真該電子萬年歷采用單片機STC89C52RC作為主控模塊,由時鐘芯片DS1302、液晶LCD1602、語音芯片NY3P065A,5個輕觸開關(guān)等組成外圍電路。3.1 硬件電路設(shè)計原理圖如下:(1) 主控模塊單片機最小系統(tǒng)電路圖如下:圖2 單片機最小系統(tǒng)該電路時單片機最小系統(tǒng)。其中電容C1、C2、晶振Y1 構(gòu)成振蕩電路為單片機時鐘信號,電容C8與電阻R3構(gòu)成上電復(fù)位電路;按鍵K0與VCC相連構(gòu)成手動復(fù)位電路。復(fù)位后單片機各部件恢復(fù)為初始狀態(tài)。STC8952RC的I/O口分配如下:3個I/O口用于控制時鐘芯片,16個I/O口用于液晶顯示,3個I/O口用于語音芯片,5個I

13、/O口用于按鍵模塊。電源部分采用3節(jié)1.5V干電池串聯(lián)的方式,形成4.5V的電壓給萬年歷各個部件供電 。(2) 時鐘模塊圖3 時鐘電路上圖是時鐘模塊的電路圖。X1、X2腳外接32768Hz的晶振Y2,為芯片提供計時脈沖。BATTERY為后備電池,VCC2為主電源;VCC1為備份電源。當(dāng)VCC1>VCC2+0.2V時,由VCC1向DS1302供電,當(dāng)VCC1< VCC2時,由VCC2向DS1302供電。DS1302的SCLK、I/O、RST三個管腳分別連接單片機的3個I/O口,單片機通過控制這3I/O口來讀取DS1302里的時間,然后通過LCD1602來顯示時間。(3) 顯示模塊圖4

14、 液晶電路上圖是顯示模塊的LCD1602的連接電路。P0P7為數(shù)據(jù)口,連接到單片機的P0口;電容C7用來濾波(接其它電源);VO連接電位器,用來調(diào)節(jié)液晶的對比度;RS、RW、E分別連接到單片機的3個I/O口,控制液晶的顯示;15 、16腳是液晶的背光電源端與接地端。(4) 語音報時模塊圖5 語音芯片電路上圖是語音報時模塊的電路圖。與VL連接的電路作用是去耦;電容C5的作用是濾波;PWM-1、PWM-2直接驅(qū)動喇叭(8歐姆,0.25瓦);IO2、OKY1、IO1接到單片機的3個I/O口,用來控制語音芯片。(5) 按鍵模塊 圖6 按鍵模塊電路該電路是萬年歷的按鍵模塊。K1K4連接單片機的4個I/O

15、口用來調(diào)整萬年歷,復(fù)位電路見主控模塊。3.2 硬件電路仿真圖7 Proteus仿真圖注:由于Proteus提供的液晶中的點陣是5*7,而LCD1602中的點陣是5*8,所以仿真圖中的漢字少了最下面一行。下圖是實際的顯示:圖8 實際顯示圖第一行:左半部分是陽歷日期的顯示;右邊的英文字母是星期的縮寫;最右邊的漢字表示2014年是陽歷閏年。第二行:左半部分是時間的顯示:右邊的“03-08”表示陰歷三月初八;最右邊的漢字表示2014年是陰歷閏年。4、 萬年歷軟件設(shè)計源程序:#include <reg52.h>#include "lcd1602.h"#include &q

16、uot;delay.h"#include "ds1302.h"#include "character.h"#include "eeprom.h"#include "NY3P065A.h"4.1 陽歷轉(zhuǎn)陰歷程序 #define uchar unsigned char #define uint unsigned int #include <intrins.h> /* 公歷年對應(yīng)的農(nóng)歷數(shù)據(jù),每年三字節(jié), 格式第一字節(jié)BIT7-4 位表示閏月月份,值為0 為無閏月,BIT3-0 對應(yīng)農(nóng)歷第1-4 月的

17、大小 第二字節(jié)BIT7-0 對應(yīng)農(nóng)歷第5-12 月大小,第三字節(jié)BIT7 表示農(nóng)歷第13 個月大小 月份對應(yīng)的位為1 表示本農(nóng)歷月大(30 天),為0 表示小(29 天) 第三字節(jié)BIT6-5 表示春節(jié)的公歷月份,BIT4-0 表示春節(jié)的公歷日期 */ code uchar year_code597 = 0x04,0xAe,0x53,0x0A,0x57,0x48,0x55,0x26,0xBd,0x0d,0x26,0x50,0x0d,0x95,0x44,0x46,0xAA,0xB9,0x05,0x6A,0x4d,0x09,0xAd,0x42,0x24,0xAe,0xB6,0x04,0xAe,0x

18、4A,0x6A,0x4d,0xBe,0x0A,0x4d,0x52,0x0d,0x25,0x46,0x5d,0x52,0xBA,0x0B,0x54,0x4e,0x0d,0x6A,0x43,0x29,0x6d,0x37,0x09,0x5B,0x4B,0x74,0x9B,0xC1,0x04,0x97,0x54,0x0A,0x4B,0x48,0x5B,0x25,0xBC,0x06,0xA5,0x50,0x06,0xd4,0x45,0x4A,0xdA,0xB8,0x02,0xB6,0x4d,0x09,0x57,0x42,0x24,0x97,0xB7,0x04,0x97,0x4A,0x66,0x4B,0x

19、3e,0x0d,0x4A,0x51,0x0e,0xA5,0x46,0x56,0xd4,0xBA,0x05,0xAd,0x4e,0x02,0xB6,0x44,0x39,0x37,0x38,0x09,0x2e,0x4B,0x7C,0x96,0xBf,0x0C,0x95,0x53,0x0d,0x4A,0x48,0x6d,0xA5,0x3B,0x0B,0x55,0x4f,0x05,0x6A,0x45,0x4A,0xAd,0xB9,0x02,0x5d,0x4d,0x09,0x2d,0x42,0x2C,0x95,0xB6,0x0A,0x95,0x4A,0x7B,0x4A,0xBd,0x06,0xCA,0x

20、51,0x0B,0x55,0x46,0x55,0x5A,0xBB,0x04,0xdA,0x4e,0x0A,0x5B,0x43,0x35,0x2B,0xB8,0x05,0x2B,0x4C,0x8A,0x95,0x3f,0x0e,0x95,0x52,0x06,0xAA,0x48,0x7A,0xd5,0x3C,0x0A,0xB5,0x4f,0x04,0xB6,0x45,0x4A,0x57,0x39, 0x0A,0x57,0x4d,0x05,0x26,0x42,0x3e,0x93,0x35,0x0d,0x95,0x49,0x75,0xAA,0xBe,0x05,0x6A,0x51,0x09,0x6d,0

21、x46,0x54,0xAe,0xBB,0x04,0xAd,0x4f,0x0A,0x4d,0x43,0x4d,0x26,0xB7,0x0d,0x25,0x4B,0x8d,0x52,0xBf,0x0B,0x54,0x52,0x0B,0x6A,0x47,0x69,0x6d,0x3C,0x09,0x5B,0x50,0x04,0x9B,0x45,0x4A,0x4B,0xB9,0x0A,0x4B,0x4d,0xAB,0x25,0xC2,0x06,0xA5,0x54,0x06,0xd4,0x49,0x6A,0xdA,0x3d,0x0A,0xB6,0x51,0x09,0x37,0x46,0x54,0x97,0

22、xBB,0x04,0x97,0x4f,0x06,0x4B,0x44,0x36,0xA5,0x37,0x0e,0xA5,0x4A,0x86,0xB2,0xBf,0x05,0xAC,0x53,0x0A,0xB6,0x47,0x59,0x36,0xBC,0x09,0x2e,0x50,0x0C,0x96,0x45,0x4d,0x4A,0xB8,0x0d,0x4A,0x4C,0x0d,0xA5,0x41,0x25,0xAA,0xB6,0x05,0x6A,0x49,0x7A,0xAd,0xBd,0x02,0x5d,0x52,0x09,0x2d,0x47,0x5C,0x95,0xBA,0x0A,0x95,0

23、x4e,0x0B,0x4A,0x43,0x4B,0x55,0x37,0x0A,0xd5,0x4A,0x95,0x5A,0xBf,0x04,0xBA,0x53,0x0A,0x5B,0x48,0x65,0x2B,0xBC,0x05,0x2B,0x50,0x0A,0x93,0x45,0x47,0x4A,0xB9,0x06,0xAA,0x4C,0x0A,0xd5,0x41,0x24,0xdA,0xB6,0x04,0xB6,0x4A,0x69,0x57,0x3d,0x0A,0x4e,0x51,0x0d,0x26,0x46,0x5e,0x93,0x3A,0x0d,0x53,0x4d,0x05,0xAA,0

24、x43,0x36,0xB5,0x37,0x09,0x6d,0x4B, 0xB4,0xAe,0xBf,0x04,0xAd,0x53,0x0A,0x4d,0x48,0x6d,0x25,0xBC,0x0d,0x25,0x4f,0x0d,0x52,0x44,0x5d,0xAA,0x38,0x0B,0x5A,0x4C,0x05,0x6d,0x41,0x24,0xAd,0xB6,0x04,0x9B,0x4A,0x7A,0x4B,0xBe,0x0A,0x4B,0x51,0x0A,0xA5,0x46,0x5B,0x52,0xBA,0x06,0xd2,0x4e,0x0A,0xdA,0x42,0x35,0x5B,

25、0x37,0x09,0x37,0x4B,0x84,0x97,0xC1,0x04,0x97,0x53,0x06,0x4B,0x48,0x66,0xA5,0x3C,0x0e,0xA5,0x4f,0x06,0xB2,0x44,0x4A,0xB6,0x38,0x0A,0xAe,0x4C,0x09,0x2e,0x42,0x3C,0x97,0x35,0x0C,0x96,0x49,0x7d,0x4A,0xBd,0x0d,0x4A,0x51,0x0d,0xA5,0x45,0x55,0xAA,0xBA,0x05,0x6A,0x4e,0x0A,0x6d,0x43, 0x45,0x2e,0xB7,0x05,0x2d

26、,0x4B,0x8A,0x95,0xBf,0x0A,0x95,0x53,0x0B,0x4A,0x47,0x6B,0x55,0x3B,0x0A,0xd5,0x4f,0x05,0x5A,0x45,0x4A,0x5d,0x38,0x0A,0x5B,0x4C,0x05,0x2B,0x42,0x3A,0x93,0xB6, 0x06,0x93,0x49,0x77,0x29,0xBd,0x06,0xAA,0x51,0x0A,0xd5,0x46,0x54,0xdA,0xBA,0x04,0xB6,0x4e,0x0A,0x57,0x43,0x45,0x27,0x38,0x0d,0x26,0x4A,0x8e,0x9

27、3,0x3e,0x0d,0x52,0x52,0x0d,0xAA,0x47,0x66,0xB5,0x3B,0x05,0x6d,0x4f,0x04,0xAe,0x45,0x4A,0x4e,0xB9,0x0A,0x4d,0x4C,0x0d,0x15,0x41,0x2d,0x92,0xB5, ; /月份數(shù)據(jù)表 code uchar day_code19=0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3; code uint day_code23=0x111,0x130,0x14e; /* 函數(shù)功能:輸入BCD陽歷數(shù)據(jù),輸出BCD陰歷數(shù)據(jù)(只允許1901-2099年

28、) 調(diào)用函數(shù)示例:Conversion(c_sun,year_sun,month_sun,day_sun) 如:計算2004年10月16日Conversion(0,0x4,0x10,0x16); c_sun,year_sun,month_sun,day_sun均為BCD數(shù)據(jù),c_sun為世紀(jì)標(biāo)志位,c_sun=0為21世 紀(jì),c_sun=1為19世紀(jì) 調(diào)用函數(shù)后,原有數(shù)據(jù)不變,讀c_moon,year_moon,month_moon,day_moon得出陰歷BCD數(shù)據(jù) */ bit c_moon; data uchar year_moon,month_moon,day_moon,week; /

29、*子函數(shù),用于讀取數(shù)據(jù)表中農(nóng)歷月的大月或小月,如果該月為大返回1,為小返回0*/ bit get_moon_day(uchar month_p,uint table_addr) uchar temp; switch (month_p) case 1:temp=year_codetable_addr&0x08; if (temp=0)return(0);else return(1); case 2:temp=year_codetable_addr&0x04; if (temp=0)return(0);else return(1); case 3:temp=year_codetab

30、le_addr&0x02; if (temp=0)return(0);else return(1); case 4:temp=year_codetable_addr&0x01; if (temp=0)return(0);else return(1); case 5:temp=year_codetable_addr+1&0x80; if (temp=0) return(0);else return(1); case 6:temp=year_codetable_addr+1&0x40; if (temp=0)return(0);else return(1); cas

31、e 7:temp=year_codetable_addr+1&0x20; if (temp=0)return(0);else return(1); case 8:temp=year_codetable_addr+1&0x10; if (temp=0)return(0);else return(1); case 9:temp=year_codetable_addr+1&0x08; if (temp=0)return(0);else return(1); case 10:temp=year_codetable_addr+1&0x04; if (temp=0)retu

32、rn(0);else return(1); case 11:temp=year_codetable_addr+1&0x02; if (temp=0)return(0);else return(1); case 12:temp=year_codetable_addr+1&0x01; if (temp=0)return(0);else return(1); case 13:temp=year_codetable_addr+2&0x80; if (temp=0)return(0);else return(1); /* 函數(shù)功能:輸入BCD陽歷數(shù)據(jù),輸出BCD陰歷數(shù)據(jù)(只允許1

33、901-2099年) 調(diào)用函數(shù)示例:Conversion(c_sun,year_sun,month_sun,day_sun) 如:計算2004年10月16日Conversion(0,0x4,0x10,0x16); c_sun,year_sun,month_sun,day_sun均為BCD數(shù)據(jù),c_sun為世紀(jì)標(biāo)志位,c_sun=0為21世 紀(jì),c_sun=1為19世紀(jì) 調(diào)用函數(shù)后,原有數(shù)據(jù)不變,讀c_moon,year_moon,month_moon,day_moon得出陰歷BCD數(shù)據(jù) */ void Conversion(bit c,uchar year,uchar month,uchar

34、day) /c=0 為21世紀(jì),c=1 為19世紀(jì) 輸入輸出數(shù)據(jù)均為BCD數(shù)據(jù) uchar temp1,temp2,temp3,month_p; uint temp4,table_addr; bit flag2,flag_y; temp1=year/16; /BCD->hex 先把數(shù)據(jù)轉(zhuǎn)換為十六進制 temp2=year%16; year=temp1*10+temp2; temp1=month/16; temp2=month%16; month=temp1*10+temp2; temp1=day/16; temp2=day%16; day=temp1*10+temp2; /定位數(shù)據(jù)表地址

35、 if(c=0) table_addr=(year+0x64-1)*0x3; else table_addr=(year-1)*0x3; /定位數(shù)據(jù)表地址完成 /取當(dāng)年春節(jié)所在的公歷月份 temp1=year_codetable_addr+2&0x60; temp1=_cror_(temp1,5); /取當(dāng)年春節(jié)所在的公歷月份完成 /取當(dāng)年春節(jié)所在的公歷日 temp2=year_codetable_addr+2&0x1f; /取當(dāng)年春節(jié)所在的公歷日完成 / 計算當(dāng)年春年離當(dāng)年元旦的天數(shù),春節(jié)只會在公歷1月或2月 if(temp1=0x1) temp3=temp2-1; else

36、 temp3=temp2+0x1f-1; / 計算當(dāng)年春年離當(dāng)年元旦的天數(shù)完成 /計算公歷日離當(dāng)年元旦的天數(shù),為了減少運算,用了兩個表 /day_code19,day_code23 /如果公歷月在九月或前,天數(shù)會少于0xff,用表day_code19, /在九月后,天數(shù)大于0xff,用表day_code23 /如輸入公歷日為8月10日,則公歷日離元旦天數(shù)為day_code18-1+10-1 /如輸入公歷日為11月10日,則公歷日離元旦天數(shù)為day_code211-10+10-1 if (month<10) temp4=day_code1month-1+day-1; else temp4=

37、day_code2month-10+day-1; if (month>0x2)&&(year%0x4=0) temp4+=1; /如果公歷月大于2月并且該年的2月為閏月,天數(shù)加1/計算公歷日離當(dāng)年元旦的天數(shù)完成 /判斷公歷日在春節(jié)前還是春節(jié)后 if (temp4>=temp3) /公歷日在春節(jié)后或就是春節(jié)當(dāng)日使用下面代碼進行運算 temp4-=temp3; month=0x1; month_p=0x1; /month_p為月份指向,公歷日在春節(jié)前或就是春節(jié)當(dāng)日month_p指向首月 flag2=get_moon_day(month_p,table_addr); /檢

38、查該農(nóng)歷月為大小還是小月,大月返回1,小月返回0 flag_y=0; if(flag2=0)temp1=0x1d; /小月29天 else temp1=0x1e; /大小30天 temp2=year_codetable_addr&0xf0; temp2=_cror_(temp2,4); /從數(shù)據(jù)表中取該年的閏月月份,如為0則該年無閏月 while(temp4>=temp1) temp4-=temp1; month_p+=1; if(month=temp2) flag_y=flag_y; if(flag_y=0) month+=1; else month+=1; flag2=get

39、_moon_day(month_p,table_addr); if(flag2=0)temp1=0x1d; else temp1=0x1e; day=temp4+1; else /公歷日在春節(jié)前使用下面代碼進行運算 temp3-=temp4; if (year=0x0) year=0x63;c=1; else year-=1; table_addr-=0x3; month=0xc; temp2=year_codetable_addr&0xf0; temp2=_cror_(temp2,4); if (temp2=0) month_p=0xc; else month_p=0xd; /*mo

40、nth_p為月份指向,如果當(dāng)年有閏月,一年有十三個月,月指向13,無閏月指向12*/ flag_y=0; flag2=get_moon_day(month_p,table_addr); if(flag2=0)temp1=0x1d; elsetemp1=0x1e; while(temp3>temp1) temp3-=temp1; month_p-=1; if(flag_y=0)month-=1; if(month=temp2)flag_y=flag_y; flag2=get_moon_day(month_p,table_addr); if(flag2=0)temp1=0x1d; elset

41、emp1=0x1e; day=temp1-temp3+1; c_moon=c; /HEX->BCD ,運算結(jié)束后,把數(shù)據(jù)轉(zhuǎn)換為BCD數(shù)據(jù) temp1=year/10; temp1=_crol_(temp1,4); temp2=year%10; year_moon=temp1|temp2; temp1=month/10; temp1=_crol_(temp1,4); temp2=month%10; month_moon=temp1|temp2; temp1=day/10; temp1=_crol_(temp1,4); temp2=day%10; day_moon=temp1|temp2;

42、/*函數(shù)功能:輸入BCD陽歷數(shù)據(jù),輸出BCD星期數(shù)據(jù)(只允許1901-2099年) 調(diào)用函數(shù)示例:Conver_week(c_sun,year_sun,month_sun,day_sun) 如:計算2004年10月16日Conversion(0,0x4,0x10,0x16); c_sun,year_sun,month_sun,day_sun均為BCD數(shù)據(jù),c_sun為世紀(jì)標(biāo)志位,c_sun=0為21世 紀(jì),c_sun=1為19世紀(jì) 調(diào)用函數(shù)后,原有數(shù)據(jù)不變,讀week得出陰歷BCD數(shù)據(jù) */ code uchar table_week12=0,3,3,6,1,4,6,2,5,0,3,5; /月

43、修正數(shù)據(jù)表 /* 算法:日期+年份+所過閏年數(shù)+月較正數(shù)之和除7 的余數(shù)就是星期但如果是在 閏年又不到3 月份上述之和要減一天再除7 星期數(shù)為0 */ void Conver_week(bit c,uchar year,uchar month,uchar day) /c=0 為21世紀(jì),c=1 為19世紀(jì) 輸入輸出數(shù)據(jù)均為BCD數(shù)據(jù) uchar temp1,temp2; temp1=year/16; /BCD->hex 先把數(shù)據(jù)轉(zhuǎn)換為十六進制 temp2=year%16; year=temp1*10+temp2; temp1=month/16; temp2=month%16; month

44、=temp1*10+temp2; temp1=day/16; temp2=day%16; day=temp1*10+temp2; if (c=0)year+=0x64; /如果為21世紀(jì),年份數(shù)加100 temp1=year/0x4; /所過閏年數(shù)只算1900年之后的 temp2=year+temp1; temp2=temp2%0x7; /為節(jié)省資源,先進行一次取余,避免數(shù)大于0xff,避免使用整型數(shù)據(jù) temp2=temp2+day+table_weekmonth-1; if (year%0x4=0&&month<3)temp2-=1; week=temp2%0x7;

45、sbit K1 = P32;/定義按鍵K1:時鐘顯示與菜單切換sbit K2 = P33;/定義按鍵K2:選擇/確認(rèn)sbit K3 = P34;/定義按鍵K3:數(shù)字減1sbit K4 = P35;/定義按鍵K4:數(shù)字加1bit m0 = 0;unsigned char m1, m2, m3, m4, SoundMode, t;/分別對應(yīng):m0時鐘顯示與菜單切換、m1菜單1選項、m2菜單2選項、m3菜單3選項、m4菜單4選項、語音報時模式選擇、t菜單選項unsigned char i = 0, j = 0;/用于按鍵的延時消抖以及循環(huán)unsigned char t0 = 0;/菜單返回計數(shù)uns

46、igned char MonthsDays13 = 0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31; /1-12月每月的天數(shù)unsigned char code runnian37 = 0x01, 0x04, 0x06, 0x09, 0x12, 0x14, 0x17,0x20, 0x23, /2000-2099年陰歷閏年數(shù)據(jù)0x25, 0x28, 0x31, 0x33, 0x36, 0x39, 0x42, 0x44, 0x47, 0x50, 0x52, 0x55, 0x58, 0x61, 0x63, 0x66, 0x69, 0x71,0x74,

47、 0x77, 0x80, 0x82, 0x85, 0x88, 0x90, 0x93, 0x96, 0x99;4.2 main函數(shù)/*下面為調(diào)用的子函數(shù)聲明*/*下面為調(diào)用的子函數(shù)聲明*/*一上電就讀取單片機內(nèi)部EEPROM中的鬧鐘、日程數(shù)據(jù)*/void ReadData ();/*函數(shù)功能:顯示時鐘界面*/void TimeDisplay ();/*函數(shù)功能:判斷是否為陽歷閏年*/unsigned char LeapYear (unsigned char year);/*函數(shù)功能:鬧鐘程序*/void AlarmClock ();/*函數(shù)功能:日程程序*/void ScheduleAlarm

48、();/*函數(shù)功能:語音報時*/void TimeSound();/*函數(shù)功能:按鍵, 按K3數(shù)字減1, 按K4數(shù)字加1*/void K3K4Down (unsigned char j, unsigned char min, unsigned char max);/*函數(shù)功能:在調(diào)時界面,按下K2將時鐘數(shù)據(jù)寫入DS1302*/void K2WriteTime ();/*函數(shù)功能:在調(diào)時界面,按下K2將鬧鐘數(shù)據(jù)寫入單片機內(nèi)部EEPROM保存*/void K2WriteAlarmTime ();/*函數(shù)功能:在調(diào)時界面,按下K2將日程數(shù)據(jù)寫入單片機內(nèi)部EEPROM保存*/void K2WriteS

49、cheduleTime ();/*函數(shù)功能:在語音報時模式顯示界面下,將語音報時模式數(shù)據(jù)寫入STC內(nèi)部EEPROM保存*/void K2WriteSoundMode();/*函數(shù)功能:外部中斷1初始化*/void Int1Init();/*函數(shù)功能:中斷日程響應(yīng)*/void AlarmScheduleInterrupt();/一上電會給語音芯片一個脈沖,使語音芯片發(fā)出語音:“0”void main ()Lcd1602Init (); /LCD1602初始化Int1Init();/外部中斷1初始化WriteCharacter (); /將漢字“年”、“月”、“日”、“閏”、“平”、“開”、“關(guān)”

50、寫進LCD1602Lcd1602WriteString (0x80, " Welcome!");/歡迎界面Lcd1602WriteString (0xc0, " Welcome!");Ds1302ReadTime(); /一上電就讀取DS1302中的時鐘數(shù)據(jù)ReadData (); /讀取存放在STC內(nèi)部EEPROM中的數(shù)據(jù)Delay10ms (250);/歡迎界面保持3秒左右Write1602Cmd (0x01); /清屏while (1)if (K1 = 0)/按一下,在時鐘顯示與菜單顯示之間轉(zhuǎn)換Delay10ms (1);/延時消抖if (K1 =

51、 0)t = 1;/初始化狀態(tài)m1 = 0; /在回到時鐘顯示時若之前的操作未保存則回到初始狀態(tài)m2 = 0;m3 = 0;m4 = 0;Time7 = AlarmTime0; /將鬧鐘數(shù)據(jù)送到LCD顯示Time8 = AlarmTime1;Time9 = AlarmTime2;Time13 = ScheduleTime0; /將日程數(shù)據(jù)送到LCD顯示Time14 = ScheduleTime1;Time15 = ScheduleTime2;Time16 = ScheduleTime3;Time17 = ScheduleTime4;Time18 = ScheduleTime5;Time19 = SoundMode;Write1602Cmd (0x01);/清屏m0 = m0;/m0只能是0、1while (i < 20) && (K1 = 0) /松手檢測,防止因硬件問題導(dǎo)致死循環(huán)Delay1ms (2);i+;i = 0;if (m0 = 0)TimeSound ();/只報一次AlarmClock ();/不斷檢測是否為鬧鐘時間,按下K2后鬧鐘停止,并且鬧鐘為OFF狀態(tài)ScheduleAlarm (); /不斷檢測是否為日

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論