|
這是一個萬年歷的小制作,包含有完整的論文,大家可以多多提供意見呀!!
里面有仿真圖以及源代碼提供下載
還有實物圖喲!
洛陽理工學院單片機課程設計
課程名稱:基于單片機的萬年歷 系別:計算機與信息工程學院 班級:B140509 學號:B14050918 姓名:伍華 同組人:李威 楊宇 指導老師:李
【目錄】 1 諸論 1.1 摘要 1.2 單片機發展概況 1.3 單片機原理及應用簡介 2 系統方案 2.1 系統功能 2.2 系統總體方案 2.2 芯片簡介 2.2.1 80C52芯片 2.2.2 實時時鐘芯片DS1302 2.2.3 DS18B20單總線數字溫度計 2.2.4 Lcd1602液晶顯示器 3 系統軟件設計 4 PROTUES軟件仿真 4.1 仿真過程 4.2 仿真結果 5 開發板調試結果 6 心得體會 7 待解決問題 8 附錄
1 諸論1.1摘要本設計是一個基于MCS-51單片機實現的萬年歷。 單片機中央處理系統的方案設計,選用80C52單片機作為中央處理器,如圖所示。該單片機除了擁有MCS-51系列單片機的所有優點外,內部還具有8K的在系統可編程FLASH存儲器,低功耗的空閑和掉電模式,極大的降低了電路的功耗,還包含了定時器、程序存儲器、數據存儲器等硬件,其硬件能符合整個控制系統的要求,不需要外接其他存儲器芯片和定時器件,方便地構成一個最小系統。整個系統結構緊湊,抗干擾能力強,性價比高。 1.2單片機發展概況單片機的發展歷史可大致分為4個階段。
第一階段(1974年-1976年):單片機初級階段。因工藝限制,單片機采用雙片的形式而且功能比較簡單。1974年12月,仙童公司推出了8位的F8單片機,實際上只包括了8位CPU、64B RAM和2個并行口。
第二階段(1976年-1978年):低性能單片機階段。1976年,Intel公司推出的MCS-48單片機(8位單片機)極大地促進了單片機的變革和發展;1977年,GI公司推出了PIC1650,但這個階段的單片機仍然處于低性能階段。
第三階段(1978年-1983年):高性能單片機階段。1978年,Zilog公司推出了28單片機;1980年,Intel公司在MCS-48單片機的基礎上推出了MCS-51系列,Mortorola公司推出了6801單片機;這些產品使單片機的性能及應用躍上了一個新的臺階。此后,各公司的8位單片機迅速發展起來。這個階段推出的單片機普遍帶有串行I/O口、多級中斷系統、16位定時器/計數器,片內ROM、RAM容量加大,且尋址范圍可達64 KB,有的片內還帶有A/D轉換器。由于這類單片機的性能價格比高,所以被廣泛應用,是目前應用數量最多的單片機。
第四階段(1983年-現在):8位單片機鞏固、發展及16位單片機、32位單片機推出階段。16位單片機的典型產品為Intel公司生產的MCS-96系列單片機。而32位單片機除了具有更高的集成度外,其數據處理速度比16位單片機提高許多,性能比8位、16位單片機更加優越。20世紀90年代是單片機制造業大發展的時期,這個時期的Mortorola、Intel、ATMEL、德州儀器(TI)、三菱、日立、Philips、LG等公司也開發了一大批性能優越的單片機,極大地推動了單片機的應用。近年來,又有不少新型的高集成度單片機產品涌現出來,出現了單片機產品豐富多彩的局面。目前,除了8位單片機得到廣泛應用之外,16位單片機、32位單片機也得到廣大用戶的青睞。
1.3單片機原理及應用簡介 單片機是單片微型計算機的簡稱,指在一塊大規模或超大規模集成電路芯片上制成的微型計算機。單片機具有體積小、功耗低、性價比高、應用靈活等優點,可以作為一個部件嵌入到各種裝置和產品中。現代生活中,從通信設備、家用電器、辦公應用到工業控制、儀器儀表、汽車電子、航空航天,幾乎每件電子和機械產品中都有單片機在工作,單片機的用量早已遠遠超過包括個人計算機在內的其他計算機的總和。以其嵌入到實際產品中發揮的控制作用或所處的地位,單片機又被稱為微控制器或嵌入式微控制器。
單片機的種類繁多、功能各異。Intel公司的MCS-51系列8位單片機,以其完善的結構、豐富的功能、開放的體系,盛行30多年而不衰。眾多半導體廠商(如Atmel、Dallas Semi、Infineon、Philips/Signetics等)獲得Intel公司的授權后,在保持代碼兼容性的前提下,融合各自先進技術,針對不同市場需求,在時鐘、存儲器、定時器/計數器、I/O接口、串行總線控制等方面進行了改進、裁剪,使得在任何實際產品的設計中都有最恰當的芯片可供選擇,也給這一單片機家族提供了旺盛的生命力。本書選擇MCS-51系列單片機作為主講機型,系統全面地介紹MCS-51單片機內部的功能結構、軟硬件資源的原理與應用,以及使用外部電路進行功能擴展的方法。 單片機是單片微型計算機的簡稱,指在一塊大規模或超大規模集成電路芯片上制成的微型計算機。單片機具有體積小、功耗低、性價比高、應用靈活等優點,可以作為一個部件嵌入到各種裝置和產品中。現代生活中,從通信設備、家用電器、辦公應用到工業控制、儀器儀表、汽車電子、航空航天,幾乎每件電子和機械產品中都有單片機在工作,單片機的用量早已遠遠超過包括個人計算機在內的其他計算機的總和。以其嵌入到實際產品中發揮的控制作用或所處的地位,單片機又被稱為微控制器或嵌入式微控制器。
單片機的種類繁多、功能各異。Intel公司的MCS-51系列8位單片機,以其完善的結構、豐富的功能、開放的體系,盛行30多年而不衰。眾多半導體廠商(如Atmel、Dallas Semi、Infineon、Philips/Signetics等)獲得Intel公司的授權后,在保持代碼兼容性的前提下,融合各自先進技術,針對不同市場需求,在時鐘、存儲器、定時器/計數器、I/O接口、串行總線控制等方面進行了改進、裁剪,使得在任何實際產品的設計中都有最恰當的芯片可供選擇,也給這一單片機家族提供了旺盛的生命力。本書選擇MCS-51系列單片機作為主講機型,系統全面地介紹MCS-51單片機內部的功能結構、軟硬件資源的原理與應用,以及使用外部電路進行功能擴展的方法。
2 系統方案2.1系統功能1:LCD顯示年、月、日、時、分、秒、星期、溫度信息; 2:用按鍵可以調整日期和時間、星期; 3:可以設置鬧鈴時間,到鬧鈴響起; 2.2系統總體方案本設計分為編程,仿真,調試開發板等步驟。以單片機為主體,利用單片機的諸多功能來控制外部設備的正常運行。 顯示器為LM016L,通過PO口將數據傳輸到顯示器上。時鐘信號的發生靠的是DS1302,將時鐘信號傳到單片機用于顯示時間以及定時的功能。利用DS18B20檢測外部環境溫度,實時檢測,將溫度數據及時的傳輸到單片機。 2芯片簡介2.2.180C52芯片80C52芯片結合了HMOS的高速和高密度技術及CHMOS的低功耗特征,它基于標準的MCS-51單片機體系結構和指令系統,屬于80C51增強型單片機版本,集成了時鐘輸出和向上或向下計數器等更多的功能,適合于類似馬達控制等應用場合。 80C52內置8位中央處理單元、256字節內部數據存儲器RAM、8k片內程序存儲器(ROM)32個雙向輸入/輸出(I/O)口、3個16位定時/計數器和5個兩級中斷結構,一個全雙工串行通信口,片內時鐘振蕩電路。 此外,80C52還可工作于低功耗模式,可通過兩種軟件選擇空閑和掉電模式。在空閑模式下凍結CPU而RAM定時器、串行口和中斷系統維持其功能。掉電模式下,保存RAM數據,時鐘振蕩停止,同時停止芯片內其它功能。80C52有PDIP(40pin)和PLCC(44pin)兩種封裝形式。 8051片內有 ROM,無須外接外存儲器和373,更能體現“單片”的簡練。但是你編的程序你無法燒寫到其ROM中,只有將程序交芯片廠代你燒寫,并是一次性的,今后你和芯片廠都不能改寫其內容。
1.001.jpg (20.8 KB, 下載次數: 50)
下載附件
2017-5-22 17:50 上傳
2.2.2實時時鐘芯片DS1302美國DALLAS公司推出的具有涓細電流充電能力的低功耗實時時鐘電路DS1302的結構、工作原理及其在實時顯示時間中的應用。它可以對年、月、日、周日、時、分、秒進行計時,且具有閏年補償等多種功能。 DS1302的引腳排列,其中Vcc1為后備電源,VCC2為主電源。在主電源關閉的情況下,也能保持時鐘的連續運行。DS1302由Vcc1或Vcc2兩者中的較大者供電。當Vcc2大于Vcc1+0.2V時,Vcc2給DS1302供電。當Vcc2小于Vcc1時,DS1302由Vcc1供電。 X1和X2是振蕩源,外接32.768kHz晶振。RST是復位/片選線,通過把RST輸入驅動置高電平來啟動所有的數據傳送。RST輸入有兩種功能:首先,RST接通控制邏輯,允許地址/命令序列送入移位寄存器;其次,RST提供終止單字節或多字節數據的傳送手段。當RST為高電平時,所有的數據傳送被初始化,允許對DS1302進行操作。如果在傳送過程中RST置為低電平,則會終止此次數據傳送,I/O引腳變為高阻態。上電運行時,在Vcc≥2.5V之前,RST必須保持低電平。只有在SCLK為低電平時,才能將RST置為高電平。 I/O為串行數據輸入輸出端(雙向),后面有詳細說明。 SCLK為時鐘輸入端。
1.002.jpg (11.48 KB, 下載次數: 43)
下載附件
2017-5-22 17:50 上傳
2.2.3DS18B20單總線數字溫度計DS18B20是常用的溫度傳感器,具有體積小,硬件開銷低,抗干擾能力強,精度高的特點。[ DS18B20的讀寫時序和測溫原理與DS1820相同,只是得到的溫度值的位數因分辨率不同而不同,且溫度轉換時的延時時間由2s減為750ms。 DS18B20測溫原理如圖3所示。圖中低溫度系數晶振的振蕩頻率受溫度影響很小,用于產生固定頻率的脈沖信號送給計數器1。高溫度系數晶振隨溫度變化其振蕩率明顯改變,所產生的信號作為計數器2的脈沖輸入。計數器1和溫度寄存器被預置在-55℃所對應的一個基數值。計數器1對低溫度系數晶振產生的脈沖信號進行減法計數,當計數器1的預置值減到0時,溫度寄存器的值將加1,計數器1的預置將重新被裝入,計數器1重新開始對低溫度系數晶振產生的脈沖信號進行計數,如此循環直到計數器2計數到0時,停止溫度寄存器值的累加,此時溫度寄存器中的數值即為所測溫度。斜率累加器用于補償和修正測溫過程中的非線性,其輸出用于修正計數器1的預置值。[
1.003.jpg (18.46 KB, 下載次數: 61)
下載附件
2017-5-22 17:50 上傳
2.2.4Lcd1602液晶顯示器1602液晶也叫1602字符型液晶,它是一種專門用來顯示字母、數字、符號等的點陣型液晶模塊。它由若干個5X7或者5X11等點陣字符位組成,每個點陣字符位都可以顯示一個字符,每位之間有一個點距的間隔,每行之間也有間隔,起到了字符間距和行間距的作用,正因為如此所以它不能很好地顯示圖形(用自定義CGRAM,顯示效果也不好)。 1602LCD是指顯示的內容為16X2,即可以顯示兩行,每行16個字符液晶模塊(顯示字符和數字)。 1602采用標準的16腳接口,其中: 第1腳:GND為電源地 第2腳:VCC接5V電源正極 第3腳:V0為液晶顯示器對比度調整端,接正電源時對比度最弱,接地電源時對比度最高(對比度過高時會 產生“鬼影”,使用時可以通過一個10K的電位器調整對比度)。 第4腳:RS為寄存器選擇,高電平1時選擇數據寄存器、低電平0時選擇指令寄存器。 第5腳:RW為讀寫信號線,高電平(1)時進行讀操作,
低電平(0)時進行寫操作。 第6腳:E(或EN)端為使能(enable)端,高電平(1)時讀取信息,負跳 變時執行指令。 第7~14腳:D0~D7為8位雙向數據端。第15~16腳:空腳或背燈電 源。15腳背光正極,16腳背光負極。+
1.004.jpg (17.57 KB, 下載次數: 53)
下載附件
2017-5-22 17:50 上傳
3 系統軟件設計
1.005.jpg (16.89 KB, 下載次數: 60)
下載附件
2017-5-22 17:50 上傳
在多功能模塊化程序設計中,主程序的作用時設置系統運行的一些初始狀態及系統運行的環境,并將各種功能子程序按要求連接起來組成一個功能強大的系統。本系統主程序的流程圖如圖。在本程序中,LCD1602初始化:8位數據接口,兩行顯示,5*7點陣字符,顯示開,關光標,光標移動為增量式。 LCD1602的初始化已被寫成一個函數LCD——INITIAL(),直接調用就可完成LCD1602的初始化。
4 PROTUES軟件仿真4.1 仿真過程- 仿真:打開keil uVision2,建立工程,輸入所編寫的源程序并對程序進行編譯,在軟件的幫助下檢查其中的錯誤并進行反復修改,知道編譯正確侯運行,生成相應的HEX文件,并進行保存,保存時給其命名,以便將來載入程序時容易找到。
- 打開PROTUES軟件,并出畫單片機電子萬年歷具體運行電路圖。
- 檢查所畫電路運行圖,確保沒有錯誤以后,在PROTUES下對原理圖進行加載keil uVision下的源程序。
1.006.jpg (22.63 KB, 下載次數: 49)
下載附件
2017-5-22 17:50 上傳
4.2 仿真結果
1.007.jpg (16.38 KB, 下載次數: 53)
下載附件
2017-5-22 17:50 上傳
1.008.jpg (20.44 KB, 下載次數: 55)
下載附件
2017-5-22 17:50 上傳
5 開發板調試結果…
1.009.jpg (10.5 KB, 下載次數: 37)
下載附件
2017-5-22 17:50 上傳
1.010.jpg (13.08 KB, 下載次數: 74)
下載附件
2017-5-22 17:50 上傳
6 程序流程圖
1.011.jpg (19.56 KB, 下載次數: 62)
下載附件
2017-5-22 17:50 上傳
7 心得體會課程設計是培養學生綜合運用所學知識,發現、提出、分析和解決實際問題,鍛煉實踐能力的重要環節,回顧此次單片機課程設計,我感覺受益良多,其中編程,仿真,調試開發板等步驟。這次課程設計是我懂得理論與實際相結合是很重要的,只有理論知識是遠遠不夠的,只有把所學知識和實踐相結合起來,從理論中得出結論,才能真正讓所學的知識服務于我們的生活,服務于我們的社會,從而提高我們的實際動手能力和獨立思考的能力,同時加強了與同學的合作和與老師的溝通,收獲很多大!這次課程設計也讓我發現了自己的不足之處,對以前學過的理論知識理解得不夠深刻,掌握得不夠牢固,對單片機匯編語言掌握得不好,一定要把以前的知識溫故而知新。
8 待解決問題1:仿真部件所屬的庫 2:程序中一則警告無法消除 9 附錄
單片機源程序如下:
- #include //52單片機的頭文件,規定了52單片機的寄存器和IO口
- #include //_nop_空指令及左右循環移位子函數庫
- #define uchar unsigned char //宏定義
- #define uint unsigned int
- sbit lcden=P2^6; //定義下面通過lcden來操作P2^6口,1602液晶使能控制端
- sbit lcdwr=P2^5; //定義下面通過lcdwr來操作P2^5口,1602讀寫選擇端
- sbit lcdrs=P2^4; //定義下面選數據寄存器還是選指令寄存器控制端
- sbit sda=P3^6; //定義DS1302數據總線,DS1302設置時間
- sbit rst=P3^4; //定義DS1302復位
- sbit sck=P3^5; //定義時鐘總線
- sbit s1=P3^0; //定義設置按鈕
- sbit s2=P3^1; //定義調試按鈕
- sbit s3=P3^2; //定義確定按鈕
- sbit s4=P3^3;
- sbit DQ=P3^7; //定義DS18B20通信端口
- sbit ACC0=ACC^0;
- sbit ACC7=ACC^7;
- sbit BELL=P1^5;
- char fen,shi,miao,ri,yue,nian,zhou,s1num,s2num,s4num,flag1,flag2,lshi,lfen;
- uchar code table[]={" 2016- - "}; //要寫入1602液晶的數據
- uchar code alarm[]={" CLOCK SETTINGS"}; //要寫入1602液晶的數據
- uchar code alarm1[]={" : "}; //要寫入1602液晶的數據
- uchar code table1[]={" : : . "}; //字庫中的字可直接以外加""號的形式直接寫入
- uchar code table2[]={" Wan Nian Li !"}; //歡迎界面
- uchar code table3[]={"Wo Men Jie Zuo!!"}; //歡迎界面
-
-
- //*****************星期編碼表**********************************
- uchar code Weeks[][3]={{"SUN"},{"MON"},{"TUE"},{"WED"},{"THU"},{"FRI"},{"SAT"},{"SUN"}};
- uchar i,j;
- //*********************短暫延時********************************
- void delay0(uint z)
- {
- while(z--);
- }
- //*********************毫秒延時********************************
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- //DS18B20初始化函數
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ=1; //DQ復位,DQ一般是表示單總線的數據接口端 //
- delay0(8); //稍做延時
- DQ=0; //單片機將DQ拉低
- delay0(80); //精確延時
- DQ=1; //拉高總線
- delay0(14);
- x=DQ; //稍做延時后?如果x=0則初始化成功?x=1則初始化失敗
- delay0(20);
- }
-
- //DS18B20讀一個字節
- uchar ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat=0;
- for(i=8;i>0;i--)
- {
- DQ=0; //給脈沖信號
- dat>>=1; //讓從總線上讀到的位數據,依次從高位移動到低位 //
- DQ=1; //給脈沖信號
- if(DQ)
- dat|=0x80;
- delay0(4);
- }
- return(dat);
- }
-
- //DS18B20寫一個字節?
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for(i=8;i>0;i--)
- {
- DQ=0;
- DQ=dat&0x01;
- delay0(5);
- DQ=1;
- dat>>=1;
- }
- }
-
- //DS18B20讀取溫度
- uint ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned char b=0;
- unsigned int t=0;
- float tt=0;
- Init_DS18B20();
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0x44); //啟動溫度轉換
- Init_DS18B20();
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度
- a=ReadOneChar();
- b=ReadOneChar();
- t=b;
- t<<=8;
- t=t|a;
- tt=t*0.0625; //將溫度的高位與低位合并
- t=tt*10+0.5; //對結果進行4舍5入
- return(t);
- }
- /*********************蜂鳴器函數************************************************/
- void didi()
- {
- uchar i;
- for(i=0;i<60;i++)
- {
- BELL=0;
- delay(1);
- BELL=1;
- delay(1);
- }
- }
-
- /*******************向1602液晶中寫一個指令**************************************/
- void write_com(uchar com)
- {
- lcdwr=0; //lcdwr為讀寫控制端,
- //lcdwr=0,
- lcdrs=0; //液晶rs接口為0時,寫指令,rs為1時寫數據
- P0=com; //將要寫的指令賦給P0口,
- delay(5); //由1602讀寫操作時序圖,先將指令賦給P0口,延時后將使能
- lcden=1; //端lcden置高,再延時一段時間,然后將lcden置低,這樣指令
- delay(5); //就寫入到LCD了
- lcden=0;
- }
- /****************************
- 向
- 液
- 晶
- 寫
- 數
- 據
- ***************************************/
- void write_data(uchar date)
- {
- lcdrs=1; //與寫指令類似,這里lcdrs設為1
- P0=date;
- delay(5);
- lcden=1;
- delay(5);
- lcden=0;
- }
-
- /*****************************初使化1602液晶************************************/
- void init_1602()
- {
- lcdwr=0;
- lcden=0;
- write_com(0x38); //設置LCD為16*2顯示、5*7點陣、8位數據接口模式
- write_com(0x0c); //開顯示、不顯示光標
- write_com(0x06); //寫一個字符后,地址指針加1
- write_com(0x01); //顯示清0
- P0=0xff;
- }
-
-
- /*******************************************************************************/
- void gudingtime_1602()
- {
- uchar num;
- write_com(0x80); //將指針指向初始位置
- for(num=0;num<16;num++) //循環函數,用于將"2012- - "寫入液晶
- write_data(table[num]);
- write_com(0x80+0x40); //將指針指向1602液晶的第二行?
- for(num=0;num<16;num++) //功能與上同,用于將" : : "寫入
- write_data(table1[num]);
- }
- void gudingtime_1602_1()
- {
- uchar num1;
- write_com(0x80); //將指針指向初始位置
- for(num1=0;num1<16;num1++) //循環函數,用于將"?2012- - "寫入液晶
- write_data(alarm[num1]);
- write_com(0x80+0x40); //將指針指向1602液晶的第二行
- for(num1=0;num1<16;num1++)//功能與上同,用于將" : : . "寫入
- write_data(alarm1[num1]);
- }
-
-
- /**************************顯示初始化界面函數*************************************/
- void displaystar(void)
- {
- uchar i;
- write_com(0x80);
- for(i=0;i<16;i++)
- write_data(table2[i]);
- write_com(0x80+0x40);
- for(i=0;i<16;i++)
- write_data(table3[i]);
- }
-
- /***************************顯示時間、日期子函數*********************************/
- void write_sfm(uchar add,uchar time) //用于在1602上顯示年、月、日、時、分、秒。Add為顯示位置,time為要顯示的內容
- {
- uchar shiwei,gewei;
- shiwei=time/16; //將從DS1302中讀取的BCD碼數據轉化成十六
- gewei=time%16; //十六進制個位
- write_com(add+0x80); //定義顯示在液晶的什么位置
- write_data(0x30+shiwei); //由1602液晶字庫可知,0~9的數據碼分別對應0x30~0x39
- write_data(0x30+gewei); //初使化中設定了寫一個字符后,地址指針加1
- } //?不用重新光標寫位?
- void write_temp(uchar add,uint temp) //用于在1602上顯示年、月、日、時、分、秒。Add為顯示位置,time為要顯示的內容
- {
- uchar shi,ge,xshu;
- shi=temp/100; //將從DS1302中讀取的BCD碼數據轉化成10進制個位和10??
- ge=temp%100/10; //進制十位?
- xshu=temp%10;
- write_com(add+0x80); //定義顯示在液晶的什么位置??
- write_data(0x30+shi); //由1602液晶字庫可知,0~9的數據碼分別對應0x30~0x39
- write_data(0x30+ge); //初使化中設定了寫一個字符后,地址指針加1,因此這里
- write_com(0x80+0x40+14);
- write_data(0x30+xshu); //?不用重新光標寫位?
- }
-
- /**************************顯示周子函數*****************************************/
- void write_zhou(uchar time1) //用于在1602上顯示周信息,與顯示
- { //時間日期子函數類似?
- uchar gewei;
- gewei=time1%16; //一周七天,因此只需個位?
- write_com(0x80+14);
- write_data(0x30+gewei);
- }
- /***************************寫數據字節子函數************************************/
- void Input_1byte(uchar TD) //寫一字節數據
- {
- uchar i;
- ACC=TD;
- for(i=8;i>0;i--)
- {
- sda=ACC0;
- sck=1;
- sck=0;
- ACC=ACC>>1;
- }
- }
-
- /*************************
- 讀數據字節子函數**************************************/
- uchar Output_1byte(void) //讀一字節數據
- {
- uchar i;
- for(i=8;i>0;i--)
- {
- ACC=ACC>>1;
- ACC7=sda;
- sck=1;
- sck=0;
- }
- return(ACC);
- }
- /***************************寫DS1302數據函數***********************************/
- void write_1302(uchar DS_ADD,uchar DS_DAT) //寫操作
- {
- rst=0;
- sck=0;
- rst=1;
- Input_1byte(DS_ADD);
- Input_1byte(DS_DAT);
- sck=1;
- rst=0;
- }
- /***************************讀DS1302數據函數***********************************/
- uchar read_1302(uchar DS_ADD) //讀操作
- {
- uchar DS_INF;
- rst=0;
- sck=0;
- rst=1;
- Input_1byte(DS_ADD);
- DS_INF=Output_1byte();
- sck=1;
- rst=0;
- return(DS_INF);
- }
-
- /*************************初始化DS1302子函數***********************************/
- void inital_1302()
- {
- write_1302(0x8e,0x00); //禁止寫保護
- write_1302(0x90,0xaa); //定義充電
- write_1302(0x80,0x53); //秒
- write_1302(0x84,0x09); //時
- write_1302(0x82,0x56); //分
- write_1302(0x8c,0x13); //年
- write_1302(0x88,0x04); //月
- write_1302(0x86,0x14); //日
- write_1302(0x8a,0x07); //星期?
- write_1302(0xc0,0x08); //鬧鐘小時初始化
- write_1302(0xfc,0x00); //鬧鐘分鐘初始化
- write_1302(0x8e,0x80); //開保護?
- }
-
- /********************************************************************************掃描函數********************************************************************************/
- void keyscan()
- {
- if(s1==0&&s4num==0) //按鍵1按下且s4在此之前未曾按過?
- {
- delay(5);
- if(s1==0&&s4num==0)
- {
- flag1=1;
- s1num++;
- while(!s1);
- didi();
- if(s1num==1)
- {
- write_com(0x80+0x40+8); //光標移動到**位置
- write_com(0x0f); //顯示光標?
- }
- if(s1num==2)
- {
- write_1302(0x8e,0x00); //禁止寫保護
- write_1302(0x80,miao); //寫入秒信息
- write_1302(0x8e,0x80); //開寫保護
- write_com(0x80+0x40+5);
- }
- if(s1num==3)
- {
- write_1302(0x8e,0x00);
- write_1302(0x82,fen);
- write_1302(0x8e,0x80);
- write_com(0x80+0x40+2);
- }
- if(s1num==4)
- {
- write_1302(0x8e,0x00);
- write_1302(0x88,yue);
- write_1302(0x8e,0x80);
- write_com(0x80+14);
- }
- if(s1num==5)
- {
- write_1302(0x8e,0x00);
- write_1302(0x84,shi);
- write_1302(0x8e,0x80);
- write_com(0x80+10);
- }
- if(s1num==6)
- {
- write_1302(0x8e,0x00);
- write_1302(0x86,ri);
- write_1302(0x8e,0x80);
- write_com(0x80+7);
- }
- if(s1num==7)
- {
- write_1302(0x8e,0x00);
- write_1302(0x8c,nian);
- write_1302(0x8e,0x80);
- write_com(0x80+4);
- }
- if(s1num==8)
- {
- flag1=0;
- s1num=0;
- write_1302(0x8e,0x00);
- write_1302(0x8a,zhou);
- write_1302(0x8e,0x80);
- write_com(0x0c); //不顯示光標?
- }
- }
-
- }
-
-
-
- /*******************************************************************************/
-
- if(s1num!=0&&s4num==0) //按鍵1按下*次且s4再此之前未曾按過
- {
- if(s2==0)
- {
- delay(5);
- if(s2==0)
- {
- while(!s2);
- didi();
- if(s1num==1)
- {
- int x1,x2;
- x1=miao%16;
- x2=miao/16;
- x1++;
- if(x1==10)
- {
- x1=0;
- x2++;
- if(x2>=6)
- x2=0;
- }
- miao=x1+x2*16;
- write_sfm(7+0x40,miao);//將修改的數送到1602顯示
- write_com(0x80+0x40+8);//挪回光標
- }
- if(s1num==2)
- {
- int x3,x4;
- x3=fen%16;
- x4=fen/16;
- x3++;
- if(x3==10)
- {
- x3=0;
- x4++;
- if(x4>=6)
- x4=0;
- }
- fen=x3+x4*16;
- write_sfm(4+0x40,fen);
- write_com(0x80+0x40+5);
- }
- if(s1num==3)
- {
- int x5,x6;
- x5=shi%16;
- x6=shi/16;
- x5++;
- if(x6>=2&&x5>=4)
- {
- x5=0;
- x6=0;
- }
- if(x5==10)
- {
- x5=0;
- x6++;
- }
- shi=x5+x6*16;
- write_sfm(1+0x40,shi);
- write_com(0x80+0x40+2);
- }
- if(s1num==4)
- {
- zhou++;
- if(zhou==8)
- zhou=1;
- write_zhou(zhou);
- write_com(0x80+14);
- }
- if(s1num==5)
- {
- int x5,x6;
- x5=ri%16;
- x6=ri/16;
- x5++;
- if(x6>=3&&x5>=1)
- {
- x5=1;
- x6=0;
- }
- if(x5==10)
- {
- x5=0;
- x6++;
- }
- ri=x5+x6*16;
- write_sfm(9,ri);
- write_com(0x80+10);
- }
- if(s1num==6)
- {
- int x5,x6;
- x5=yue%16;
- x6=yue/16;
- x5++;
- if(x6>=1&&x5>=3)
- {
- x5=1;
- x6=0;
- }
- if(x5==10)
- {
- x5=0;
- x6++;
- }
- yue=x5+x6*16;
- write_sfm(6,yue);
- write_com(0x80+7);
- }
- if(s1num==7)
- {
- int x5,x6;
- x5=nian%16;
- x6=nian/16;
- x5++;
- if(x6>=2&&x5>=1)
- {
- x5=1;
- x6=0;
- }
- if(x5==10)
- {
- x5=0;
- x6++;
- }
- nian=x5+x6*16;
- write_sfm(3,nian);
- write_com(0x80+4);
- }
- }
- }
- }
-
-
-
-
-
-
-
- if(s1num!=0||s4num!=0) // 在調整模式下
- {
- if(s3==0) //如果確定鍵按下
- {
- delay(5);
- if(s3==0) //延時并重新檢測S3是否按下,用于差小誤差
- {
- if(s1num!=0)
- {
- while(!s3);
- didi();//在松手時將調整后的時間、日期及周信息寫 入DS1302,退出調整模式并隱藏光標,按鍵次數清0
- write_1302(0x8e,0x00);
- write_1302(0x80,miao);
- write_1302(0x84,shi);
- write_1302(0x82,fen);
- write_1302(0x8a,zhou);
- write_1302(0x8c,nian);
- write_1302(0x88,yue);
- write_1302(0x86,ri);
- write_1302(0x8e,0x80);
- flag1=0;
- write_com(0x0c);
- s1num=0;
- gudingtime_1602();
- }
- if(s4num!=0)
- {
- while(!s3);didi();//再松手是將調整后的時間、日期及周信息寫入DS1302,退出調整模式并隱藏光標,按鍵次數清0
- write_1302(0x8e,0x00);
- write_1302(0xc0,lshi);
- write_1302(0xfc,lfen);
- write_1302(0x8e,0x80);
- flag2=0;
- write_com(0x0c);
- s4num=0;
- gudingtime_1602();
- }
- }
- }
- }
- if(s4==0&&s1num==0) //按鍵4按下*次且s1再次之前未曾按 過
- {
- delay(5);
- if(s4==0&&s1num==0)
- {
- s4num++;
- flag2=1;
- while(!s4);didi();
- if(s4num==1)
- {
- gudingtime_1602_1();
- lshi=read_1302(0xc1);//從ds1302里面的RAM讀取鬧鐘時, 此處不放在while(1)大循環里面是因為ds1302里面的RAM里的數據是不變的只需讀取一次
- lfen=read_1302(0xfd);//從ds1302里面的RAM讀取鬧鐘分
- write_sfm(0x40+10,lshi);//將鬧鐘時送到1602顯示
- write_com(0x80+0x40+12);//將鬧鐘:送到1602顯示
- write_data(table1[3]);
- write_sfm(0x40+13,lfen);//將鬧鐘分送到1602?
- write_com(0x80+0x40+14);
- write_com(0x0f);
- }
- if(s4num==2)
- {
- write_1302(0x8e,0x00); //禁止寫保護
- write_1302(0xfc,lfen); //鬧鐘初始化
- write_1302(0x8e,0x80); //開寫保護
- lshi=read_1302(0xc1); //從ds1302里面的RAM讀取鬧鐘 時,此處不放在while(1)大循環里面是因為ds1302里面的RAM里的數據是不變的只需讀取一次
- lfen=read_1302(0xfd); //從ds1302里面的RAM讀取鬧鐘分
- write_sfm(0x40+10,lshi);//將鬧鐘時送到1602顯示
- write_sfm(0x40+13,lfen);//將鬧鐘分送到1602顯示
- write_com(0x80+0x40+11);
- write_com(0x0f);
- }
- if(s4num==3)
- {
- s4num=0;
- flag2=0;
- write_1302(0x8e,0x00);//禁止寫保護
- write_1302(0xc0,lshi);//鬧鐘初始化
- write_1302(0x8e,0x80);//開寫保護
- write_com(0x0c); //不顯示光標
- write_com(0x01); //顯示清0
- gudingtime_1602();
- }
- }
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
單片機課程設計伍錫華 - r9wm4.doc
(1.43 MB, 下載次數: 45)
2017-5-22 08:02 上傳
點擊文件名下載附件
萬年歷 下載積分: 黑幣 -5
|
評分
-
查看全部評分
|