這個設計很全ppt 還有源程序和仿真都有
下載地址:
基于單片機的智能交通燈系統(tǒng)的設計.zip
(1.74 MB, 下載次數(shù): 135)
2016-12-5 02:06 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
下面是文檔的部分內(nèi)容預覽:
ppt內(nèi)容預覽:
0.png (267.5 KB, 下載次數(shù): 79)
下載附件
2016-12-5 02:07 上傳
2 設計要求和設計方案2.1 設計要求 2.1.1項目概述 道路交通信號燈是道路交通安全的產(chǎn)品,它可以加強道路交通管理,減少交通事故的發(fā)生,提高道路使用效率,改善交通狀況的一種重要工具。它適用于各種十字、丁字等交叉路口,由道路交通信號燈控制,指導車輛和行人安全而有序地通行。 2.1.2 設計任務 設計一種交通信號燈的控制系統(tǒng)。要求直觀,簡單。能夠滿足十字路口交通等的使用需求。 2.1.3 設計要求 1. 交通路口為十字路口。 2.馬路為雙向六車道,即要有左轉(zhuǎn)燈,直行燈,右轉(zhuǎn)燈。 3.要考慮人行橫道的信號燈。 4.有顯示設備可以顯示通信時間。 5.要求通行時間可調(diào)。
2.2 設計方案 2.2.1 供電方案 系統(tǒng)要在正常而穩(wěn)定的狀態(tài)下工作,必須要有可靠的電源。而本次基于單片機的設計需要顯示的芯片較多,電源供應量大,因此本次設計了如下三種方案。 方案一:利用獨立的穩(wěn)壓電源供電。優(yōu)點是可提供穩(wěn)定而可靠電源,而且可以利用220V電壓轉(zhuǎn)化,不受各種因素的限制;缺點是各模塊都采用獨立電源,會增加本次設計的難度,而且對其他電路還會造成一定的干擾。 方案二:采用USB轉(zhuǎn)接口5V電壓供電,這樣簡單明了,但是單單一個5V電源供電可能會顯得電源不足,而無法滿足實際的需要。 方案三:采用USB轉(zhuǎn)接口5V雙電源電壓供電,這樣把本次設計分為兩大模塊,一是交通信號燈控制系統(tǒng),二是萬年歷系統(tǒng),采用雙電源供電,一個為交通信號燈控制系統(tǒng)提供電源,另一個為萬年歷系統(tǒng)提供電源。這樣即簡單而又可提供穩(wěn)定的電源。 考慮到實際情況和電路的簡潔,本設計采用了第三套方案,此方案在電路的設計上可以把系統(tǒng)分為兩大模塊,使系統(tǒng)設計簡單化,從而又可以提供穩(wěn)定而可靠電源。而且在單電源斷電的情況下不影響另一模塊的工作。
2.2.2 輸入方案 該系統(tǒng)要求能手動及智能控制改變交通信號燈的通行時間和萬年歷時間的調(diào)整。 方案一:采用8155擴展I/O 口及鍵盤、顯示等。該方案的優(yōu)點是:使用靈活可編程,并且有RAM,及計數(shù)器。若用該方案,可提供較多I/O 口,但操作起來稍顯復雜。 方案二: 直接在I/O口線上接上按鍵開關(guān)。該方案優(yōu)點是:編程更加簡潔,使用更加簡單,且成本更低。缺點就是功能有限。 綜合考慮本設計的實際需要,在使用輸入的時候不需要過于復雜的功能,因此直接在I/O口線上接上按鍵開關(guān)足以滿足本次系統(tǒng)設計的需要,故采用方案二。
2.2.3 顯示界面方案 本設計涉及到倒計時、狀態(tài)燈、時間、溫度等顯示功能。基于功能需求,本設計考慮如下四種方案: 方案一:完全采用數(shù)碼管顯示。這種方案只顯示有限的符號和數(shù)碼字符,無法勝任功能需求。 方案二:完全采用點陣式LED 顯示。這種方案實現(xiàn)復雜,且須完成大量的軟件工作;但功能強大,可方便的顯示各種英文字符,漢字,圖形等。 方案三:采用LCD1602液晶顯示,這種顯示比較樂觀,但是工作量大,而且設計復雜,再加上需要到的LCD1602較多,從經(jīng)濟上也不劃算。 方案四:采用數(shù)碼管、LED與LCD1602相結(jié)合的方法因為設計既要求倒計時數(shù)字輸出,又要求有狀態(tài)燈輸出,同時還要顯示出年、月、日、時、分、秒、星期和溫度。為了方便觀看并考慮到實際情況,用數(shù)碼管顯示交通信號燈的倒計時,用LED顯示交通燈的狀態(tài)燈、用LCD1602顯示年、月、日、時、分、秒、星期和溫度。這種設計方案既滿足系統(tǒng)功能要求,又減少了系統(tǒng)實現(xiàn)的復雜度。
2.2.4交通燈方案 2.2.4.1交通燈規(guī)則方案 本設計的交通燈以十字路口為模型,在實現(xiàn)基本的功能前提下增加了時間及溫度的液晶顯示。從而還增加了路口高峰期的智能化人工管理機制。 實際生活中交通信號燈的規(guī)則千變?nèi)f化,在不同的路口上看到的交通信號燈的規(guī)則不一樣,但是總體還是相差不大,也有一些根據(jù)實際的需要而設置不同的交通規(guī)則,本次系統(tǒng)交通規(guī)則的設置是根據(jù)現(xiàn)實生活中的交通規(guī)則和多加考慮各種現(xiàn)實因素結(jié)合起來而制定了以下交通規(guī)則。 下圖所示為一種紅綠燈規(guī)則的狀態(tài)圖:
1.001.jpg (7.83 KB, 下載次數(shù): 77)
下載附件
2016-12-5 02:02 上傳
1.002.jpg (8.26 KB, 下載次數(shù): 76)
下載附件
2016-12-5 02:02 上傳
1.003.jpg (3.31 KB, 下載次數(shù): 80)
下載附件
2016-12-5 02:02 上傳
1.004.jpg (3.02 KB, 下載次數(shù): 84)
下載附件
2016-12-5 02:02 上傳
1.005.jpg (7.22 KB, 下載次數(shù): 77)
下載附件
2016-12-5 02:02 上傳
1.006.jpg (7.6 KB, 下載次數(shù): 64)
下載附件
2016-12-5 02:02 上傳
1.007.jpg (3.2 KB, 下載次數(shù): 93)
下載附件
2016-12-5 02:02 上傳
1.008.jpg (3.25 KB, 下載次數(shù): 70)
下載附件
2016-12-5 02:02 上傳
共四種狀態(tài),分別設定為S1、S2、S3、S4,交通燈以這四種狀態(tài)為一個周期,循環(huán)執(zhí)行如下圖所示:
1.009.jpg (8.18 KB, 下載次數(shù): 65)
下載附件
2016-12-5 02:02 上傳
1.010.jpg (2.5 KB, 下載次數(shù): 91)
下載附件
2016-12-5 02:02 上傳
依據(jù)上述車輛行駛的狀態(tài)圖,可以列出正常模式下各個路口交通信號燈的邏輯表如下表所示(其中邏輯值“1”表示直行通行,邏輯值“0”表示禁止通行,邏輯值“L”表示左轉(zhuǎn)通行):
表2.1 正常模式下工作表
程序就是在上述四種狀態(tài)下循環(huán)轉(zhuǎn)化的,而每種狀態(tài)下又包括綠燈通行和黃燈閃爍警告狀態(tài)。系統(tǒng)在正常模式下循環(huán)一個周期所需要的時間為120S,數(shù)碼管顯示的工作模式為半周期60.
2.2.4.2各種模式下通行時間 本系統(tǒng)結(jié)合實際的需要,而在上述四種狀態(tài)的每種狀態(tài)下再細分為綠燈通行、黃燈閃爍兩種狀態(tài),總共八種工作狀態(tài)。系統(tǒng)在正常工作模式下又可分為三種工作模式,分別為:正常模式、繁忙模式和特殊模式。各種模式下的時間分配如下表2.2: 表2.2 各模式下時間分配表
2.2.5 萬年歷設計方案 電路設計框圖 本系統(tǒng)的電路系統(tǒng)框圖如圖2.6所示。AT89C51單片機對DS1302和DS18B20寫入控制字并讀取相應的數(shù)據(jù),繼而控制LCD1602作出對應的顯示,同時也向交通信號燈外部發(fā)出定時中斷,從而改變交通信號燈的工作模式。
3 芯片的介紹及應用3.1 AT89C51單片機介紹及應用 單片微型計算機簡稱單片機,同時又稱為微控制器、嵌入式微控制器等,它屬于第四代電子計算機。它把各種芯片電路集成在一塊芯片上,因此它具有體積小、抗干擾能力強、功耗低、可靠性高以及低廉的價格。它廣泛應用于工業(yè)過程控制、測控系統(tǒng)及各種智能儀器儀表等。因此國際上逐漸采用微控制器(MCU)代替單片微型計算機(SCM)這一名稱。微控制器可以更準確的反應出單片機的本質(zhì),但單片機這一名稱以為大多數(shù)人所接受,所以單片微型計算機即是單片機,同時又稱為微控制器。
3.1.1單片機的引腳及功能 AT89C51單片機的 引腳圖如圖3.1 所示
1.023.jpg (20.32 KB, 下載次數(shù): 68)
下載附件
2016-12-5 02:02 上傳
圖3.1 AT89C51單片機引腳圖
VCC:電源電壓 GND:地 P0口:P0口是一個漏極開路型8位雙向I/0口,即數(shù)據(jù)/地址總線的復用口。當它作為輸出端口使用時,每位能驅(qū)動8個TTL邏輯門電路。 P1口:Pl 口是一個帶內(nèi)部上拉電阻的8位雙向I/O口,Pl口的輸出緩沖級能驅(qū)動4個TTL邏輯門電路。當我們對端口寫入“1”時,通過內(nèi)部上拉電阻來把端口拉到高電平,此時P1口可做為輸入端口。當P1口做為輸入口時,由于內(nèi)部存在上拉電阻,當被外部引腳拉低時會輸出數(shù)據(jù)。P1口除了以上功能外,最重要的是它的第二功能如表3.1所示。
表3.1 P1口引腳的第二功能
P2口:P2口也是一個帶有內(nèi)部上拉電阻的8 位雙向I/O 口。P2 的輸出緩沖級也能驅(qū)動4 個TTL邏輯門電路。當我們對端口寫入“1”時,通過內(nèi)部上拉電阻來把端口拉到高電平,此時P2口可做為輸入端口。當P2口做為輸入口時,由于內(nèi)部存在上拉電阻,當被外部引腳拉低時會輸出數(shù)據(jù)。當訪問外部程序存儲器或16位地址外部數(shù)據(jù)的存儲器時,P2口輸出高8位數(shù)據(jù)地址。當訪問8 位外部數(shù)據(jù)存儲器地址時,P2口的內(nèi)容在整個訪問過程將不會改變。 P3 口:P3 口也是一個帶有內(nèi)部上拉電阻的8 位雙向I/0 口。P3 口輸出緩沖級也能驅(qū)動4 個TTL邏輯門電路。當我們對端口寫入“1”時,通過內(nèi)部上拉電阻來把端口拉到高電平,此時P3口可做為輸入端口。當P3口做為輸入口時,由于內(nèi)部存在上拉電阻,當被外部引腳拉低時會輸出數(shù)據(jù)。P3口除了以上用途外,最重要的是它的第二功能如表3.2所示。 表3.2 P3口引腳的第二功能 | | | | | | | | | | | | | | | / WR(外部數(shù)據(jù)存儲器寫選通) | | / RD(外部數(shù)據(jù)存儲器讀選通) |
P3口還可用于接收一些Flash閃速存儲器的編程及程序的校驗控制等。 RST:復位輸入引腳。振蕩器在工作時,RST引腳將會出現(xiàn)兩個或兩個以上的機器周期高電平來使單片機進行復位。WDT 溢出將使該引腳輸出高電平,設置SFR AUXR的DISRT0 位(地址8EH)可打開或關(guān)閉該功能。DISRT0位缺省為RESET輸出高電平打開狀態(tài)。 ALE/:在訪問外部數(shù)據(jù)存儲器或程序存儲器時,ALE(地址鎖存)主要是利用輸出脈沖來鎖存地址低8位字節(jié)。ALE還可以用于對外輸出時鐘信號或定時功能,因為ALE時刻以時鐘振蕩器的1/6頻率輸出固定的脈沖信號。 值得注意的是:當我們在訪問外部數(shù)據(jù)存儲器時將會跳過一個ALE脈沖。在F1ash存儲器編程期間,該引腳還可用于輸入編程脈沖。還可以通過特殊的功能寄存器中的8EH單元的D0位置來禁止ALE工作。執(zhí)行該操作后,需要通過MOVX和MOVC指令ALE才能被激活,從而恢復工作狀態(tài)。在執(zhí)行單片機外部程序時,ALE應設置為無效。 程序的儲存是在()允許輸出外部程序存儲器時進行,當單片機需要進行讀寫數(shù)據(jù)時,此時該引腳在每個周期下就會兩次有效,從而發(fā)出兩次脈沖,當訪問外部的數(shù)據(jù)存儲器時,則是發(fā)出一次脈沖信號。 /VPP:外部訪問允許。當EA端設置為低電平時,CPU可單獨訪問外部程序存儲器(即:0000H-FFFFH地址)。 XTAL1:振蕩器的反相放大器和內(nèi)部時鐘發(fā)生器的輸入端。
3.1.2單片機最小系統(tǒng)的設置 本次基于單片機交通信號燈控制系統(tǒng)的設計的單片機最小系統(tǒng)設置的如下圖所示:
1.024.jpg (12.53 KB, 下載次數(shù): 66)
下載附件
2016-12-5 02:02 上傳
圖3.2 AT89C51單片機最小系統(tǒng)圖
3.2 LCD1602芯片介紹及應用 3.2.1 液晶顯示器的介紹 液晶顯示器有多種分類方法,通常按顯示的方式分可分為字符式、段式、點陣式等。液晶顯示器即可顯示黑白又可顯示多彩色灰度,因此可分為黑白顯示器和彩色顯示器。如果按驅(qū)動方式分,它又可以分為單純矩陣驅(qū)動(Simple Matrix)、靜態(tài)驅(qū)動(Static)和主動矩陣驅(qū)動(Active Matrix)三種。液晶顯示器它具有厚度薄、體積小,適用于大規(guī)模集成電路的驅(qū)動等特點,目前已廣泛應用在數(shù)字攝像機、便攜式電腦、MP3、MP4、PDA移動通信工具等領(lǐng)域。
3.2.2 液晶顯示器各種圖形的顯示原理 液晶顯示器是利用液晶的物理特性,通過高低電壓來控制顯示的區(qū)域,高電平則亮,低電平則滅,這樣就可以顯示出圖形。液晶顯示器圖形的顯示是通過N*M個液晶顯示單元構(gòu)成,通過控制各個顯示單元的亮暗而達到顯示圖形的目的。例如一個液晶顯示器有64行顯示屏,而每行有128列,每字節(jié)又由8列組成,因此每行可顯示16個字節(jié),即整個顯示器可顯示1024個字節(jié)。最后通過控制液晶顯示相應位置的亮暗從而顯示出每字節(jié)上的內(nèi)容。
3.2.3 LCD1602的基本參數(shù)及引腳功能 LCD1602采用標準的14腳(無背光)或16腳(帶背光)接口,本次設計采用16腳(帶背光)來顯示年、月、日、時、分、秒、星期和溫度。各引腳接口說明如表3.3所示: 第1腳:VSS為地電源。 第2腳:VDD接5V正電源。 第3腳:VL是顯示器對比度調(diào)整端,當接地信號時液晶對比度最高,當接正電源時對比度最弱,對比度的高低將會影響液晶顯示器的顯示,對比度過高時會產(chǎn)生“鬼影”。因此我們通常接一個10K的電位器來調(diào)節(jié)。 第4腳:RS是寄存器的選擇,高電平表示數(shù)據(jù)寄存器、低電平表示指令寄存器。 第5腳:R/W是信號線的讀寫,當高電平時表示正在進行讀操作,當?shù)碗娖綍r表示正在進行寫操作,如果RS和R/W同時為低電平時可進行顯示地址或?qū)懭胫噶睿绻鸕S為低電平且R/W為高電平時可進行讀取信號,如果RS為高電平R/W為低電平時可進行寫入數(shù)據(jù)。 第6腳:E端是使能信號端,當E端由高電平變化為低電平時,液晶模塊命令開始執(zhí)行。 第7~14腳:D0~D7是8位雙向數(shù)據(jù)線。 第15腳:背光源正極。 第16腳:背光源負極。
表3.3引腳接口說明表 編號 | 符號 | 引腳說明 | 編號 | 符號 | 引腳說明 | 1 | VSS | 電源地 | 9 | D2 | 數(shù)據(jù) | 2 | VDD | 電源正極 | 10 | D3 | 數(shù)據(jù) | 3 | VL | 液晶顯示偏壓 | 11 | D4 | 數(shù)據(jù) | 4 | RS | 數(shù)據(jù)/命令選擇 | 12 | D5 | 數(shù)據(jù) | 5 | R/W | 讀/寫選擇 | 13 | D6 | 數(shù)據(jù) | 6 | E | 使能信號 | 14 | D7 | 數(shù)據(jù) | 7 | D0 | 數(shù)據(jù) | 15 | BLA | 背光源正極 | 8 | D1 | 數(shù)據(jù) | 16 | BLK | 背光源負極 |
3.2.4 LCD1602的指令說明及時序 LCD1602內(nèi)部液晶顯示模塊控制器指令共11條,如表3.4所示: LCD1602的讀寫操作、光標操作以及屏幕顯示等都是通過各種指令程序而實現(xiàn)的,具體說明如下:(注:1為高電平,0為低電平) 指令1:清顯示,指令碼由01H復位到00H位置。 指令2:光標復位,執(zhí)行時光標將返回到00H位置。 指令3:光標以及顯示模式的設置。光標的移動方向為:高電平表示右移,低電平則表示左移。S:屏幕文字是否進行右移或者進行左移。高電平表示有效,低電平表示無效。 指令4:顯示控制開關(guān)。B:光標閃爍的控制,高電平表示閃爍,低電平則表示不閃爍。 C:光標開關(guān)的控制,高電平表示有光標,低電平則表示無光標 。D:整體顯示的開關(guān)控制,高電平表示打開顯示,低電平則表示關(guān)閉顯示。 指令5:光標或者顯示移位 S/C的控制。高電平表示文字移動的顯示,低電平表示光標的移動。 指令6:功能命令的設置。DL為高電平表示4位總線,低電平則表示8位總線。F: 低電平表示顯示5x7的點陣字符,高電平表示顯示5x10的點陣字符。 N:低電平表示單行顯示,高電平表示雙行顯示 指令7:字符發(fā)生器RAM地址設置。 指令8:DDRAM地址的設置。 指令9:光標地址和讀忙信號。 BF:表示忙標志位,高電平時表示忙,此時模塊不能進行命令或者數(shù)據(jù)的接受,低電平則表示不忙。 指令10:寫數(shù)據(jù)。 指令11:讀數(shù)據(jù)
表3.4 控制命令表 序號 | 指令 | RS | R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 1 | 清顯示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 光標返回 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | * | 3 | 置輸入模式 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | 4 | 顯示開/關(guān)控制 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B | 5 | 光標或字符移位 | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | * | * | 6 | 置功能 | 0 | 0 | 0 | 0 | 1 | DL | N | F | * | * | 7 | 置字符發(fā)生存貯器地址 | 0 | 0 | 0 | 1 | 字符發(fā)生存貯器地址 | 8 | 置數(shù)據(jù)存貯器地址 | 0 | 0 | 1 | 顯示數(shù)據(jù)存貯器地址 | 9 | 讀忙標志或地址 | 0 | 1 | BF | 計數(shù)器地址 | 10 | 寫數(shù)據(jù)到CGRAM或DDRAM) | 1 | 0 | 寫入的數(shù)據(jù)內(nèi)容 | 11 | 從CGRAM或DDRAM讀數(shù) | 1 | 1 | 讀出的數(shù)據(jù)內(nèi)容 |
LCD1602液晶顯示器有多種,其中市場上最常見的是HD44780。HD44780內(nèi)置了DDRA(80字節(jié)),CGRAM(64字節(jié),用來存放用戶自定義字符,每個字符需要用到8個字節(jié),所以以一共可以存放8個用戶自定義字符),CGROM(內(nèi)存了160個字符,包括了標準的ASCII碼表上的字符等)。與HD44780相兼容的芯片時序表如表3.5所示:
表3.5 基本操作時序表 讀狀態(tài) | 輸入 | RS=L,R/W=H,E=H | 輸出 | D0—D7=狀態(tài)字 | 寫指令 | 輸入 | RS=L,R/W=L,D0—D7=指令碼,E=高脈沖 | 輸出 | 無 | 讀數(shù)據(jù) | 輸入 | RS=H,R/W=H,E=H | 輸出 | D0—D7=數(shù)據(jù) | 寫數(shù)據(jù) | 輸入 | RS=H,R/W=L,D0—D7=數(shù)據(jù),E=高脈沖 | 輸出 | 無 |
讀寫操作時序如圖3.3和3.4所示。
1.025.jpg (14.26 KB, 下載次數(shù): 71)
下載附件
2016-12-5 02:02 上傳
圖3.3 讀操作時序
1.026.jpg (14.94 KB, 下載次數(shù): 75)
下載附件
2016-12-5 02:02 上傳
圖3.4寫操作時序 LCD1602液晶顯示是一個慢顯示器件,所以每次在執(zhí)行指令時一定要先進行確認模塊的忙標志位是否為低電平,否而指令將會失效。要進行字符的顯示,首先要進行輸入顯示字符的地址,實際就是輸入顯示的內(nèi)容。LCD1602內(nèi)部顯示地址如圖3.5所示。
1.027.jpg (3.11 KB, 下載次數(shù): 67)
下載附件
2016-12-5 02:02 上傳
1.028.jpg (21.31 KB, 下載次數(shù): 74)
下載附件
2016-12-5 02:02 上傳
對液晶模塊的初始化中要先設置其顯示模式,在液晶模塊顯示字符時光標將會自動右移。液晶模塊在繁忙狀態(tài)下將不能輸入指令。 3.2.5 LCD1602液晶顯示模塊原理圖 LCD1602顯示模塊電路,首先VSS接地信號,VDD接5V高電平,VEE接10K的變阻器,變阻器兩端分別接5V電壓和大地。接著RS、RW和E是數(shù)據(jù)信號線分別接單片機的P2.5、P2.6和P2.7引腳。最后D0到D7接單片機的P0.0到P0.7引腳,要接排阻。而實際的LCD1602還有兩個背光調(diào)節(jié)引腳,分別是BLA和BLK接5V電壓和大地。
1.029.jpg (22.89 KB, 下載次數(shù): 81)
下載附件
2016-12-5 02:02 上傳
圖3.6 LCD1602顯示電路 3.3 DS1302芯片介紹及應用 DS1302是美國 DALLAS 公司推出的一種高性能、低功耗的時鐘芯片,它采用 SPI 三線接口與 CPU 進行同步通信,并可采用突發(fā)方式一次傳送一個或多個字節(jié)的時鐘信號和 RAM數(shù)據(jù)。它可提供年、月、日、星期、時、分、秒的計時顯示,各月天數(shù)它可進行自動的調(diào)整,同時還具有閏年的補償功能。工作電壓范圍為2.5~5.5V。DS1302芯片采用雙電源供電,即有主電源和備用電源。同時還可設置備用電源的充電方式,提供了對備用電源進行電流充電的能力。DS1302也可用于數(shù)據(jù)的記錄, 特別是對于某些特殊意義的數(shù)據(jù)點的記錄上,它能實現(xiàn)數(shù)據(jù)和數(shù)據(jù)出現(xiàn)的時間同時記錄,因此在各種測量系統(tǒng)中得到廣泛的應用。
3.3.1 DS1302引腳功能 DS1302芯片的外部引腳分配如圖3.7所示。
1.030.jpg (7.39 KB, 下載次數(shù): 76)
下載附件
2016-12-5 02:02 上傳
圖3.7 DS1302的外部引腳分配
Vcc1:表示主電源;Vcc2:表示備份電源。如果 Vcc2>Vcc1+0.2V, 則 Vcc2向 DS1302供電,如果 Vcc2< Vcc1,由則Vcc1向 DS1302供電。 SCLK:串行時鐘,輸入,控制數(shù)據(jù)的輸入與輸出。 I/O:三線接口時的雙向數(shù)據(jù)線。 CE:輸入信號。DS1302在進行讀寫數(shù)據(jù)時,此位必須為高。該引腳有兩個功能:首先是CE 開始控制字進行訪問移位寄存器的邏輯控制;其次是CE 提供結(jié)束單字節(jié)或者多字節(jié)數(shù)據(jù)的傳輸方法。
3.3.2 DS1302讀寫說明 DS1302是 SPI 總線方式來驅(qū)動。它不僅需要向寄存器寫入控制字, 同時還需要讀取相應寄存器的數(shù)據(jù)。
1:DS1302的讀寫寄存器 DS1302的時間寄存器總共有12個,其中讀寄存器(81H-8DH)和寫寄存器(81H-8DH)是以BCD碼格式進行數(shù)據(jù)的存取。 表3.6 DS1302的讀寫寄存器 DS1302小時寄存器(84H、85H)的位7應用于DS1302是運行的模式。即12小時制還是24小時制。當位7為1時,表示12小時模式,此時相應的寄存器位5為高時表示AM,為低時表示PM。當位7為0時, 表示24小時模式。 DS1302秒寄存器(80H、81H)的位7應用于時鐘暫停標志(CH)位。當該位為1時,時鐘振蕩器停止,DS1302處于低功耗狀態(tài);當該位為0時,時鐘開始運行。 DS1302 控制寄存器(8EH、8FH)的位7是寫入保護位,其它7位均為0。當WP位為0時可以開始進行對時鐘和RAW進行寫入,當WP位為1時,禁止對寄存器的寫入操作。
2:DS1302中靜態(tài)RAM地址 DS1302在靜態(tài)工作模式下的RAW地址如表3.7所示。 表3.7 靜態(tài) RAM 的地址表
3:DS1302的工作模式寄存器 DS1302的工作模式寄存器又分為時鐘突發(fā)模式寄存器、RAW突發(fā)模式寄存器等。突發(fā)模式是指一次傳送多個字節(jié)的時鐘信號和 RAM 數(shù)據(jù)。 突發(fā)模式寄存器如表3.8所示。 表3.8突發(fā)模式寄存器
4:DS1302控制字符表 DS1302的控制字最高位(位7)必須是1,才能進行數(shù)據(jù)的寫入,否則不能寫入數(shù)據(jù);次高位(位6)表示RAW數(shù)據(jù)或者時鐘日歷的存取,當為1時表示RAW數(shù)據(jù)存取,為0則表示時鐘日歷的存取;接著是數(shù)據(jù)操作地址(位5-位1);最后是位0表示數(shù)據(jù)的讀寫操作,當為1時表示讀操作,為0表示寫操作。如表3.9所示。 表3.9 控制字(即地址及命令字節(jié))
1.031.jpg (7.88 KB, 下載次數(shù): 63)
下載附件
2016-12-5 02:02 上傳
5:DS1302的讀寫時序 DS1302數(shù)據(jù)的讀寫規(guī)則是在控制字的基礎上從低位到高位的輸出,每當控制字指令輸入后下一個SCLK脈沖上升沿到來時,數(shù)據(jù)就會被寫入到DS1302中,數(shù)據(jù)從最低位開始寫入,下一個SCLK脈沖的下降沿到來時,就會讀出DS1302里面的數(shù)據(jù),讀出的規(guī)則也是從低位到高位。
1.032.jpg (23.74 KB, 下載次數(shù): 59)
下載附件
2016-12-5 02:02 上傳
圖3.8 數(shù)據(jù)讀寫時序
3.3.3 DS1302時鐘采集模塊原理圖
1.033.jpg (16.39 KB, 下載次數(shù): 74)
下載附件
2016-12-5 02:02 上傳
圖3.9 DS1302原理圖 此圖為DS1302時鐘芯片模塊采集原理圖,X1和X2接的是時鐘晶振,,大小為32.768MHz,VCC1和VCC2分別接3V和5V電壓,I/O、SCLK和ST分別接單片機的P1.6、P1.7和P1.5引腳。
3.4 DS18B20芯片介紹及應用 DS18B20數(shù)字溫度計是DALLAS公司生產(chǎn)的One-Wire,即單總線器件,它具有體積小而且線路簡單的優(yōu)點。它只有三個引腳,分別是接高電源、地信號和一條數(shù)據(jù)信號線,設計簡單而又方便。因此它廣泛應用于溫度的測溫系統(tǒng)。 DS18B20除了體積小、線路設計簡單優(yōu)點外,它在實際應用中不需要其它外部任何器件即可實現(xiàn)溫度的測溫功能,測量溫度范圍為-55—+125 °C 之間,如超出檢測的溫度,DS18B20將會發(fā)出報警信號。數(shù)字溫度計的讀取可以從9位到12位選擇。可用數(shù)據(jù)線供電,供電范圍+3.0-5.5V電壓。
3.4.1 DS18B20引腳功能 DS18B20器件的封裝引腳排列及引腳功能的描述如圖3.10和表3.10。
1.034.jpg (1.73 KB, 下載次數(shù): 66)
下載附件
2016-12-5 02:02 上傳
圖3.10(底視圖)
表3.10 DS18B20引腳功能 | | | | | | | | 數(shù)據(jù)輸入/輸出引腳。開漏單總線接口引腳。當被用在寄生電源下,也可以向器件提供電源。 | | | 可選擇的VDD引腳。當工作于寄生電源時,此引腳必須接地。 |
3.4.2 DS18B20的應用及原理圖 DS18B20采用的是one-Wire總線協(xié)議方式連接,實際就是在一根數(shù)據(jù)線進行數(shù)據(jù)的雙向傳輸,,然而對于51單片機在硬件上并不支持單總線協(xié)議方式的連接,因此我們采用軟件的方法來模擬單總線的協(xié)議方式來完成對DS18B20溫度芯片的訪問。 DS18B20的讀寫是在一根I/O線上進行,因此,對數(shù)據(jù)的讀寫有著嚴格的要求。DS18B20的通信協(xié)議也有著嚴格的要求來確保數(shù)據(jù)傳輸?shù)恼_性和完整性。 DS18B20有嚴格的通信協(xié)議來保證各位數(shù)據(jù)傳輸?shù)恼_性和完整性。該通信協(xié)議又細分了幾種信號的時序,即:初始化時序、讀時序、寫時序。然而在這幾種時序的工作下都是以主機作為主設備,單總線器件作為從設備。數(shù)據(jù)的傳輸是在主機先啟動讀入時序,讀出數(shù)據(jù)后進入寫時序命令,從而啟動讀寫時序功能,完成數(shù)據(jù)的傳輸。數(shù)據(jù)和命令的傳輸都是低位在先。下面為DS18B20在本次設計的溫度采集模塊原理圖3.11所示。
1.035.jpg (9.96 KB, 下載次數(shù): 66)
下載附件
2016-12-5 02:02 上傳
圖3.11 DS18B20溫度采集原理圖
溫度采集模塊圖主要是由DS18B20芯片進行,通過AT89C51單片機進行數(shù)據(jù)的傳輸和接受,從而再送到LCD1602,從LCD1602顯示出來。DS18B20只有三個引腳,分別是VCC為正電源接5V電壓,GND地信號接大地,最后是DQ數(shù)據(jù)輸入/輸出引腳連接AT89C51單片機的P1.0引腳。
4 程序的設計流程4.1 交通燈程序設計的流程 4.1.1倒計時顯示的理論分析 利用定時器中斷,設置 TH0= (65536-50000)/256,TH1=(65536-50000)%256,即每0.05秒中斷一次。每到第20次中斷即過了20*0.05秒=1秒時,使時間的計數(shù)值減1,便實現(xiàn)了倒計時的功能。
4.1.2狀態(tài)燈顯示的理論分析 黃燈閃爍同樣可以利用定時器中斷。每到第10次中斷即過了10*0.05秒=0.5秒時,使黃燈標志位反置,即可讓黃燈1秒閃爍一次。
4.1.3 交通燈主程序設計流程 交通燈系統(tǒng)在正常模式下工作的 - 首先,正常進入系統(tǒng)開始運行,交通燈在默認正常模式下工作,數(shù)碼管顯示時間為60。
- 交通信號燈開始正常工作,右轉(zhuǎn)彎為常亮燈(綠色)。南北直行方向綠燈亮,其它方向亮紅燈,數(shù)碼管開始倒計時,南北方向從40倒計,東西方向從60倒計。
- 35S后,南北直行方向滅綠燈,閃爍黃燈,閃爍時間為5S。
- 40S后,南北直行方向亮紅燈,左轉(zhuǎn)方向亮綠燈,亮時15S,同時數(shù)碼管從20倒計,其它不變。
- 55S后,南北左轉(zhuǎn)方向滅綠燈,閃爍黃燈,閃爍時間為5S。
- 60S后,南北左轉(zhuǎn)方向黃燈滅,亮紅燈,數(shù)碼管從60倒計,東西直行方向亮綠燈,數(shù)碼管從40倒計,其它不變。
- 95S后,東西直行方向滅綠燈,閃爍黃燈,閃爍時間為5S。
- 100S后,東西直行方向滅黃燈,亮紅燈,左轉(zhuǎn)方向亮綠燈,亮時為15S,同時數(shù)碼管從20倒計,其它不變。
- 115S后,東西左轉(zhuǎn)方向滅綠燈,閃爍黃燈,閃爍時間為5S。
- 120S后,東西左轉(zhuǎn)方向滅黃燈,亮紅燈,數(shù)碼管從60倒計。南北直行亮綠燈,數(shù)碼管從40倒計。
1.036.jpg (63.13 KB, 下載次數(shù): 80)
下載附件
2016-12-5 02:02 上傳
圖4.1 程序設計流程圖
4.2萬年歷的設計流程 萬年歷的設置一方面可以更好的顯示時間和溫度,其次可以對交通信號燈系統(tǒng)的控制,定時向交通信號燈控制系統(tǒng)發(fā)出外部中斷,從而該變當前工作模式,以致在實際中更具有實用性。
1.037.jpg (18.11 KB, 下載次數(shù): 68)
下載附件
2016-12-5 02:02 上傳
圖4.2 萬年歷主程序流程圖
此次萬年歷的設計功能主要是兩個,一個是通過LCD1602顯示時間和溫度,另一個則是為交通信號燈提供外部定時中斷,從而改變當前的工作模式。而萬年歷的設計流程和普通設計的一樣,開始先是對各種芯片的初始化,接著是從DS1302、DS18B20讀取時間和溫度信息,從而傳送到AT89C51單片機進行時間、溫度的分離轉(zhuǎn)化,再傳送到LCD1602顯示出來,其次是時間的調(diào)整和校正,通過調(diào)整按鍵可以對秒、分、時、星期、日、月和年進行加減1的修改。最近是定時發(fā)出外部中斷,利用IF語句進行判斷,適合條件則輸出低電平到交通信號燈,否則為高電平。從而達到了實驗的目的。
4.3萬年歷時間的調(diào)整流程 本次萬年歷系統(tǒng)的設計只是采用DS1302進行時間的掃描和讀取,而沒用進行掉電保存電路的設計,因此在每次硬件的開啟,系統(tǒng)都是進入初始化設置,以致要進行時間的調(diào)整和校正。
1.038.jpg (79.82 KB, 下載次數(shù): 67)
下載附件
2016-12-5 02:02 上傳
圖4.3 時間調(diào)整控制圖 時間的調(diào)整程序設計。首先,系統(tǒng)在正常工作下,由DS1302時鐘芯片進行時間的讀取,傳遞到AT89C51單片機進行對時間進行分離和轉(zhuǎn)化,最后由LCD1602顯示出來。在進行時間的調(diào)整和校正時,先進入調(diào)整模式,即按下第一個按鍵,執(zhí)行調(diào)整程序,先是進入秒程序調(diào)整,按加減按鍵相應的進行加1或減1,再按調(diào)整切換鍵進入分程序調(diào)整,按加減減進行相應的加1減1,再接著是時、星期、日、月、年的調(diào)整。按加減鍵進行相應的加減1,在進行調(diào)整途中,如果按退出時間調(diào)整按鍵都將會退出時間調(diào)整程序。如圖4.3時間調(diào)整控制圖所示。 4.4交通信號系統(tǒng)工作模式的工作流程
1.039.jpg (58.42 KB, 下載次數(shù): 77)
下載附件
2016-12-5 02:02 上傳
圖4.4 工作模式切換圖 開始進入系統(tǒng)時,默認模式為正常模式60S,到了早上7:00時上班高峰期,萬年歷發(fā)出中斷,從而使系統(tǒng)進入繁忙模式45S,從而可以減少路口上交通的擁堵。時間到了早上9:00,車輛逐漸減少,萬年歷又發(fā)出定時中斷使系統(tǒng)進入正常模式,到了11:00,萬年歷再次發(fā)出定時中斷,重新使系統(tǒng)進入繁忙模式,減少車輛的擁堵。到了下午14:00,萬年歷發(fā)出定時中斷,使系統(tǒng)進入正常模式,在正常模式下運行到下午17:00下班時間,為了減少交通的擁堵,萬年歷發(fā)出定時中斷,使系統(tǒng)進入繁忙模式,到了晚上19:00,道口上車輛減少,萬年歷最后發(fā)出定時中斷,使系統(tǒng)在正常模式下正常運行。系統(tǒng)在正常模式、繁忙模式和特殊模式下運行時,還可以進行外部手動進行中斷來進行通行時間的調(diào)整。如:在正常模式下按下繁忙模式,系統(tǒng)將會進入繁忙模式,當下次中斷再次到來時,系統(tǒng)會根據(jù)中斷的要求而進入相應的模式,不會受上次中斷或下次中斷的影響。
5 軟硬件的仿真調(diào)試5.1 PROTEUS仿真圖 整個交通燈控制系統(tǒng)在PROTEUS仿真圖中的仿真如下所示,雙向通行,倒計時是2位時間提醒。每個路口分別有左轉(zhuǎn)、直行和右轉(zhuǎn),分別有紅燈、綠燈和黃燈提示。每個路口還相應配有行人的紅綠燈指示 。圖右上角數(shù)碼管顯示的工作模式,60代表是在正常模式下工作,45和75分別代表是在繁忙模式和特殊模式,右下角是開關(guān)調(diào)節(jié)按鍵,左邊三個開關(guān)從上到下是交通燈各種模式轉(zhuǎn)換開關(guān),右邊四個是時間調(diào)節(jié)開關(guān),從而更具有實用性。
1.040.jpg (60.34 KB, 下載次數(shù): 63)
下載附件
2016-12-5 02:02 上傳
圖5.1 PROTEUS仿真圖
5.2 硬件實物圖 此次硬件實物的設計分為兩部分,一部分是電子器件的設計,另一部分是顯示界面的設計。電子器件的設計主要是單片機的最小系統(tǒng)設置、DS1302時鐘模塊的設置、DS18B20溫度模塊的設置以及非門74HC04的設置等;顯示界面的設置主要是LCD1602液晶顯示模塊、各個方向數(shù)碼管倒計時、數(shù)碼管顯示系統(tǒng)工作模式、各個道口的交通燈、人行道的交通燈以及控制開關(guān)調(diào)節(jié)按鍵的設置。兩部分的分開設計可以使實物顯得更美觀,同時對于實物的器件的修改和調(diào)整也提供了更好的條件。也更聯(lián)系了實際生活,顯得簡單、整潔和美觀。 顯示界面如圖5.2所示。
1.041.jpg (57.53 KB, 下載次數(shù): 73)
下載附件
2016-12-5 02:02 上傳
圖5.2 硬件實物圖
結(jié) 論本次基于單片機的交通信號燈控制系統(tǒng)的設計是在一般交通燈的基礎上加上時間的智能控制,從而改變各方向通行的時間。因此本次智能交通燈的設計可以更好的解決了車流量較大的十字路口車輛的通行,與一般交通燈相比,它更具有實用性、簡單化和智能化。從而也更好的應用到實際生活中,因此具有一定的實用價值。 此次基于單片機的交通信號燈控制系統(tǒng)的設計可以說得到了成功,但是還是存在很多的不足和缺陷。如:工作模式的時間只有三種選擇,而不能通過按鍵進行隨意更改,工作模式時間的智能切換也不能進行手動調(diào)節(jié),以及對通過道口車流量的統(tǒng)計、車輛速度的檢測和拍攝功能等都還沒實現(xiàn),而且此次設計需要用到的電子元器件較多,從經(jīng)濟上不劃算,因此本次基于單片機的交通信號燈控制系統(tǒng)的設計也還存在著很大的不足,還有待改善。 致 謝歷時三個月的設計已經(jīng)告一段落。經(jīng)過自己不斷的搜索努力以及大家的耐心指導和熱情幫助,本設計已經(jīng)基本完成。同時系里興趣小組實驗室的開放和大部分興趣小組同學也為我的設計提供指導,在他們的幫助和指導下得到了完成。在此對于他們的幫助給與深刻的致謝。 在本次基于單片機的交通信號燈的控制系統(tǒng)設計中一路遇到了很多的困難,首先從開始電路原理圖的設計、畫PCB圖和制板都遇到了困難。先是對芯片的不理解,專業(yè)知識的不夠從而導致在程序的編寫中經(jīng)常出錯。接著是在最后的調(diào)試中,由于本次設計分為兩塊電路板,線路繁多因此也很容易混亂等問題。但是在大家的幫助和鼓勵下一一得到了解決。 通過這次設計,使我對自己有了一個深刻的認識。認識到了自己專業(yè)知識的不足和專業(yè)知識的重要性,同時也理解了理論要聯(lián)系實際含義。通過這次的設計也檢驗了自己的學習成果,認識到了自己的不足和缺陷,在今后的工作和學習中將會繼續(xù)努力,不斷完善,從而為今后的發(fā)展打下良好的基礎。 由于自身水平有限,設計中一定還存在很多不足之處,敬請各位批評指正。
- 附錄單片機程序:
- 1: 十字路口交通燈控制C程序1:
- /***********************************************************
- 十字路口交通燈控制 C 程序
- ***********************************************************/
- #include <reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- /*****定義控制位*******************************************/
- sbit Time_Show_LED1=P2^4; //Time_Show_LED1(直行時間顯示)控制位
- sbit Time_Show_LED2=P2^5; //Time_Show_LED2(直行時間顯示)控制位
- sbit SN_LED1=P2^0; //SN_LED1控制位
- sbit SN_LED2=P2^1; //SN_LED2控制位
- sbit EW_LED1=P2^2; //EW_LED1控制位
- sbit EW_LED2=P2^3; //EW_LED2控制位
- sbit SN_Yellow=P1^6; //SN黃燈
- sbit EW_Yellow=P1^2; //EW黃燈
- sbit EW_ManGreen=P3^0; //EW人行道綠燈
- sbit SN_ManGreen=P3^1; //SN人行道綠燈
- sbit Special_LED=P2^6; //交通特殊指示燈
- sbit Busy_LED=P2^7; //交通繁忙指示燈
- sbit Nomor_Button=P3^5; //交通正常按鍵
- sbit Busy_Btton=P3^6; //交通繁忙按鍵
- sbit Special_Btton=P3^7; //交通特殊按鍵
- sbit EW_ManRed=P3^3; //EW人行道紅燈
- sbit SN_ManRed=P3^4; //SN人行道紅燈
- sbit x=P1^7;
- sbit y=P1^3;
- bit Flag_SN_Yellow; //SN黃燈標志位
- bit Flag_EW_Yellow; //EW黃燈標志位
- char Time_EW; //東西方向倒計時單元
- char Time_SN; //南北方向倒計時單元
- uchar EW=60,SN=40,EWL=19,SNL=19; //程序初始化賦值,正常模式
- uchar EW1=60,SN1=40,EWL1=19,SNL1=19; //用于存放修改值的變量
- uchar code table[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //0-9段選碼
- uchar code S[8]={0x28,0x48,0x98,0x88,0x82,0x84,0x89,0x88};
- //交通信號燈控制代碼
- /**********************延時子程序**************************/
- void Delay(uchar a)
- {
- uchar i;
- i=a;
- while(i--){;}
- }
- /*****************顯示子函數(shù)******************************/
- void Display(void)
- {
- uchar h,l;
- h=Time_EW/10;
- l=Time_EW%10;
- P0=table[l];
- EW_LED2=1; //點亮EW_LED2
- Delay(2);
- EW_LED2=0; //熄滅EW_LED2
- P0=table[h];
- EW_LED1=1; //點亮EW_LED1
- Delay(2);
- EW_LED1=0;
- h=Time_SN/10;
- l=Time_SN%10;
- P0=table[l];
- SN_LED2=1; //點亮SN_LED2
- Delay(2);
- SN_LED2=0;
- P0=table[h];
- SN_LED1=1; //點亮SN_LED1
- Delay(2);
- SN_LED1=0;
-
- h= EW1/10;
- l= EW1%10;
- P0=table[l];
- Time_Show_LED1=1; //點亮Time_Show_LED1
- Delay(2);
- Time_Show_LED1=0;
-
- P0=table[h];
- Time_Show_LED2=1; //點亮Time_Show_LED2
- Delay(2);
- Time_Show_LED2=0;
- }
- /**********************外部0中斷服務程序******************/
- void INT0_srv(void)interrupt 0 using 1
- {
- EX0=0; //關(guān)中斷
- if(Nomor_Button==0) //測試按鍵是否按下,按下為正常狀態(tài)
- {
- EW1=60;
- SN1=40;
- EWL1=19;
- SNL1=19;
- Busy_LED=0; //關(guān)繁忙信號燈
- Special_LED =0; //關(guān)特殊信號燈
- }
- if(Busy_Btton==0) //測試按鍵是否按下,按下為繁忙狀態(tài)
- {
- EW1=45;
- SN1=30;
- EWL1=14;
- SNL1=14;
- Special_LED=0; //關(guān)特殊信號燈
- Busy_LED=1; //開繁忙信號燈
-
- }
- if(Special_Btton==0)//測試按鍵是否按下,按下為特殊狀態(tài)
- {
- EW1=75;
- SN1=55;
- EWL1=19;
- SNL1=19;
- Busy_LED=0; //關(guān)繁忙信號燈
- Special_LED =1;//開特殊信號燈
- }
- EX0=1; //開中斷
- }
- /**********************T0中斷服務程序*******************/
- void timer0(void)interrupt 1 using 1
- {
- static uchar count;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- count++;
- if(count==10)
- {
- if(Flag_SN_Yellow==1) //測試南北黃燈標志位
- {SN_Yellow=~SN_Yellow;}
- if(Flag_EW_Yellow==1) //測試東西黃燈標志位
- {EW_Yellow=~EW_Yellow;}
- }
- if(count==20)
- {
- Time_EW--;
- Time_SN--;
- if(Flag_SN_Yellow==1) //測試南北黃燈標志位
- {SN_Yellow=~SN_Yellow;}
- if(Flag_EW_Yellow==1) //測試東西黃燈標志位
- {EW_Yellow=~EW_Yellow;}
- count=0;
- }
- }
- /*********************主程序開始***********************/
- void main(void)
- {
- Busy_LED=0;
- Special_LED=0;
- IT0=1; //INT0負跳變觸發(fā)
- TMOD=0x01; //定時器工作于方式1
- TH0=(65536-50000)/256; //定時器賦初值
- TL0=(65536-50000)%256;
- EA=1; //CPU開中斷總允許
- ET0=1; //開定時中斷
- EX0=1; //開外部INTO中斷
- TR0=1; //啟動定
- while(1)
- {
- /*******S0狀態(tài)**********/
- SN_ManRed=0;
- SN_ManGreen=1; //SN人行道通行
- EW_ManRed=1; //EW人行道禁止
- EW_ManGreen=0;
- Flag_EW_Yellow=0; //EW關(guān)黃燈顯示信號
- Time_EW=EW;
- Time_SN=SN;
- while(Time_SN>=5)
- {
- P1=S[0]; //SN綠燈,EW紅燈
- Display();
- }
- /*******S1狀態(tài)**********/
- P1=0x00;
- while(Time_SN>=0)
- {
- Flag_SN_Yellow=1; //SN開黃燈信號位
- P1=P1|0x08; //保持EW紅燈
- Display();
- }
- /*******S2狀態(tài)**********/
- SN_ManRed=1; //SN人行道禁止
- SN_ManGreen=0;
- EW_ManRed=1; //EW人行道禁止
- EW_ManGreen=0;
- Flag_SN_Yellow=0; //SN關(guān)黃燈顯示信號
- Time_SN=SNL;
- while(Time_SN>=5)
- {
- P1=S[2]; //SN左拐綠燈亮,EW紅燈
- Display();
- }
- /*******S3狀態(tài)**********/
- P1=0x00;
- while(Time_SN>=0)
- {
- //Flag_SN_Yellow=0; //SN開黃燈信號位
- x=1;
- P1=P1|0x08; //保持EW紅燈
- Display();
- }
- /***********賦值*********/
- EW=EW1;
- SN=SN1;
- EWL=EWL1;
- SNL=SNL1;
- /*******S4狀態(tài)**********/
- SN_ManRed=1; //SN人行道禁止
- SN_ManGreen=0;
- EW_ManRed=0;
- EW_ManGreen=1; //EW人行道通行
- Flag_SN_Yellow=0; //SN關(guān)黃燈顯示信號
- Time_EW=SN;
- Time_SN=EW;
- while(Time_EW>=5)
- {
- P1=S[4]; //EW通行,SN紅燈
- Display();
- }
- /*******S5狀態(tài)**********/
- P1=0X00;
- while(Time_EW>=0)
- {
- Flag_EW_Yellow=1;//EW開黃燈信號位
- P1=P1|0x80; //保持SN紅燈
- Display();
- }
- /*******S6狀態(tài)**********/
- SN_ManRed=1; //SN人行道禁止
- SN_ManGreen=0;
- EW_ManRed=1; //EW人行道禁止
- EW_ManGreen=0;
- Flag_EW_Yellow=0;//EW關(guān)黃燈顯示信號
- Time_EW=EWL;
- while(Time_EW>=5)
- {
- P1=S[6]; //EW左拐綠燈亮,SN紅燈
- Display();
- }
- /*******S7狀態(tài)**********/
- P1=0X00;
- while(Time_EW>=0)
- {
- //Flag_EW_Yellow=0; //EN開黃燈信號位
- y=1;
- P1=P1|0x80; //保持SN紅燈
- Display();
- }
- /***********賦值********/
- EW=EW1;
- SN=SN1;
- EWL=EWL1;
- SNL=SNL1;
- }
- }
- 2:十字路口交通燈控制C程序2
- /***********************************************************
- 十字路口交通燈控制 C 程序
- ***********************************************************/
- #include <reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- /*****定義控制位*******************************************/
- sbit EW_Green1 =P1^0; //EW直行綠燈
- sbit EW_Green12 =P1^1; //EW左轉(zhuǎn)綠燈
- sbit EW_Green13= P1^2; //EW右轉(zhuǎn)綠燈
- sbit EW_Yellow1 =P1^3; //EW直行黃燈
- sbit EW_Yellow2 =P1^4; //EW左轉(zhuǎn)黃燈
- sbit EW_Yellow3 =P1^5; //EW右轉(zhuǎn)黃燈
- sbit EW_Red1=P1^6; //RE直行紅燈
- sbit EW_Red2 =P1^7; //RE左轉(zhuǎn)紅燈
- bit Flag_SN_Yellow; //SN黃燈標志位
- bit Flag_EW_Yellow; //EW黃燈標志位
- uchar EW=60,SN=40,EWL=19,SNL=19; //程序初始化賦值,正常模式
- uchar EW1=60,SN1=40,EWL1=19,SNL1=19; //用于存放修改值的變量
- uchar code table[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //0-9段選碼
- uchar code S[8]={0xA0,0xA0,0x80,0xC0,0xA0,0xA0,0x20,0x24};
- //交通信號燈控制代碼
- /**********************延時子程序**************************/
- void Delay(uchar a)
- {
- uchar i;
- i=a;
- while(i--){;}
- }
- /*****************顯示子函數(shù)******************************/
- void Display(void)
- {
- uchar h,l;
- h=Time_EW/10;
- l=Time_EW%10;
- P0=table[l];
- EW_LED2=1; //點亮EW_LED2
- Delay(2);
- EW_LED2=0; //熄滅EW_LED2
- P0=table[h];
- EW_LED1=1; //點亮EW_LED1
- Delay(2);
- EW_LED1=0;
- h=Time_SN/10;
- l=Time_SN%10;
- P0=table[l];
- SN_LED2=1; //點亮SN_LED2
- Delay(2);
- SN_LED2=0;
- P0=table[h];
- SN_LED1=1; //點亮SN_LED1
- Delay(2);
- SN_LED1=0;
-
- h= EW1/10;
- l= EW1%10;
- P0=table[l];
- Time_Show_LED1=1; //點亮Time_Show_LED1
- Delay(2);
- Time_Show_LED1=0;
- P0=table[h];
- Time_Show_LED2=1; //點亮Time_Show_LED2
- Delay(2);
- Time_Show_LED2=0;
- }
- /**********************外部0中斷服務程序******************/
- void INT0_srv(void)interrupt 0 using 1
- {
- EX0=0; //關(guān)中斷
- if(Nomor_Button==0) //測試按鍵是否按下,按下為正常狀態(tài)
- {
- EW1=60;
- SN1=40;
- EWL1=19;
- SNL1=19;
- Busy_LED=0; //關(guān)繁忙信號燈
- Special_LED =0; //關(guān)特殊信號燈
- }
- if(Busy_Btton==0) //測試按鍵是否按下,按下為繁忙狀態(tài)
- {
- EW1=45;
- SN1=30;
- EWL1=14;
- SNL1=14;
- Special_LED=0; //關(guān)特殊信號燈
- Busy_LED=1; //開繁忙信號燈
- }
- if(Special_Btton==0)//測試按鍵是否按下,按下為特殊狀態(tài)
- {
- EW1=75;
- SN1=55;
- EWL1=19;
- SNL1=19;
- Busy_LED=0; //關(guān)繁忙信號燈
- Special_LED =1;//開特殊信號燈
- }
- EX0=1; //開中斷
- }
- /**********************T0中斷服務程序*******************/
- void timer0(void)interrupt 1 using 1
- {
- static uchar count;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- count++;
- if(count==10)
- {
- if(Flag_SN_Yellow==1) //測試南北黃燈標志位
- {SN_Yellow=~SN_Yellow;}
- if(Flag_EW_Yellow==1) //測試東西黃燈標志位
- {EW_Yellow=~EW_Yellow;}
- }
- if(count==20)
- {
- Time_EW--;
- Time_SN--;
- if(Flag_SN_Yellow==1) //測試南北黃燈標志位
- {SN_Yellow=~SN_Yellow;}
- if(Flag_EW_Yellow==1) //測試東西黃燈標志位
- {EW_Yellow=~EW_Yellow;}
- count=0;
- }
- }
- /*********************主程序開始***********************/
- void main(void)
- {
- Busy_LED=0;
- Special_LED=0;
- IT0=1; //INT0負跳變觸發(fā)
- TMOD=0x01; //定時器工作于方式1
- TH0=(65536-50000)/256; //定時器賦初值
- TL0=(65536-50000)%256;
- EA=1; //CPU開中斷總允許
- ET0=1; //開定時中斷
- EX0=1; //開外部INTO中斷
- TR0=1; //啟動定時
- while(1)
- {
- /*******S0狀態(tài)**********/
- SN_ManGreen=1; //SN人行道通行
- EW_ManGreen=0;
- Flag_EW_Yellow=0; //EW關(guān)黃燈顯示信號
- Time_EW=EW;
- Time_SN=SN;
- while(Time_SN>=5)
- {
- P1=S[0]; //SN綠燈,EW紅燈
- Display();
- }
- /*******S1狀態(tài)**********/
- P1=0x00;
- while(Time_SN>=0)
- {
- x=1;
- y=1;
- P1=P1|0xA0; //保持EW紅燈
- Display();
- }
- /*******S2狀態(tài)**********/
- EW_ManGreen=0;
- Flag_SN_Yellow=0; //SN關(guān)黃燈顯示信號
- Time_SN=SNL;
- while(Time_SN>=5)
- {
- P1=S[2]; //SN左拐綠燈亮,EW紅燈
- Display();
- }
- /*******S3狀態(tài)**********/
- P1=0x00;
- while(Time_SN>=0)
- {
- Flag_SN_Yellow=1; //SN開黃燈信號位
- y=1;
- c=0;
- Display();
- }
- /***********賦值*********/
- EW=EW1;
- SN=SN1;
- EWL=EWL1;
- SNL=SNL1;
- /*******S4狀態(tài)**********/
- SN_ManGreen=0;
- EW_ManGreen=1; //EW人行道通行
- Flag_SN_Yellow=0; //SN關(guān)黃燈顯示信號
- x=1;
- d=0;
- Time_EW=SN;
- Time_SN=EW;
- while(Time_EW>=5)
- {
- P1=S[4]; //EW通行,SN紅燈
- Display();
- }
- /*******S5狀態(tài)**********/
- P1=0X00;
- while(Time_EW>=0)
- {
- x=1;
- P1=P1|0x80; //保持SN紅燈
- Display();
- }
- /*******S6狀態(tài)**********/
- SN_ManGreen=0;
- EW_ManGreen=0;
- Flag_EW_Yellow=0;//EW關(guān)黃燈顯示信號
- Time_EW=EWL;
- while(Time_EW>=5)
- {
- P1=S[6]; //EW左拐綠燈亮,SN紅燈
- Display();
- }
- /*******S7狀態(tài)**********/
- P1=0X00;
- while(Time_EW>=0)
- {
- Flag_EW_Yellow=1; //EN開黃燈信號位
- x=1;
- P1=P1|0x20; //保持SN紅燈
- Display();
- }
- /***********賦值********/
- EW=EW1;
- SN=SN1;
- EWL=EWL1;
- SNL=SNL1;
- }
- }
- 3:萬年歷程序:
- #include <REG51.H>
- #include <intrins.h>
- //#include "LCD1602.h"
- //#include "DS1302.h"
- #define uint unsigned int
- #define uchar unsigned char
- sbit DS1302_CLK = P1^7; //實時時鐘時鐘線引腳
- sbit DS1302_IO = P1^6; //實時時鐘數(shù)據(jù)線引腳
- sbit DS1302_RST = P1^5; //實時時鐘復位線引腳
- sbit wireless_1 = P3^0;
- sbit wireless_2 = P3^1;
- sbit wireless_3 = P3^2;
- sbit wireless_4 = P3^3;
- sbit zhengchang = P3^5; //正常模式切換
- sbit fanmang = P3^6; //繁忙模式切換
- sbit ACC0 = ACC^0;
- sbit ACC7 = ACC^7;
- char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,時到日,月,年位閃的計數(shù)
- void show_time(); //液晶顯示程序
- /***********1602液晶顯示部分子程序****************/
- //Port Definitions**********************************************************
- sbit LcdRs = P2^5;
- sbit LcdRw = P2^6;
- sbit LcdEn = P2^7;
- sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.數(shù)據(jù)端口
- //內(nèi)部等待函數(shù)**************************************************************************
- unsigned char LCD_Wait(void)
- {
- LcdRs=0;
- LcdRw=1; _nop_();
- LcdEn=1; _nop_();
-
- LcdEn=0;
- return DBPort;
- }
- //向LCD寫入命令或數(shù)據(jù)************************************************************
- #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 //顯示關(guān)
- #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 //default
- void LCD_SetInput(unsigned char InputMode)
- {
- LCD_Write(LCD_COMMAND, 0x04|InputMode);
- }
- //初始化LCD************************************************************
- void LCD_Initial()
- {
- LcdEn=0;
- LCD_Write(LCD_COMMAND,0x38); //8位數(shù)據(jù)端口,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++;
- }
- }
- /***********DS1302時鐘部分子程序******************/
- 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) // 轉(zhuǎn)成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) //實時時鐘寫入一字節(jié)(內(nèi)部函數(shù))
- {
- 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) //實時時鐘讀取一字節(jié)(內(nèi)部函數(shù))
- {
- 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: 要寫的數(shù)據(jù)
- {
- DS1302_RST = 0;
- DS1302_CLK = 0;
- DS1302_RST = 1;
- DS1302InputByte(ucAddr); // 地址,命令
- DS1302InputByte(ucDa); // 寫1Byte數(shù)據(jù)
- DS1302_CLK = 1;
- DS1302_RST = 0;
- }
- unsigned char Read1302(unsigned char ucAddr) //讀取DS1302某地址的數(shù)據(jù)
- {
- unsigned char ucData;
- DS1302_RST = 0;
- DS1302_CLK = 0;
- DS1302_RST = 1;
- DS1302InputByte(ucAddr|0x01); // 地址,命令
- ucData = DS1302OutputByte(); // 讀1Byte數(shù)據(jù)
- DS1302_CLK = 1;
- DS1302_RST = 0;
- return(ucData);
- }
- void DS1302_GetTime(SYSTEMTIME *Time) //獲取時鐘芯片的時鐘數(shù)據(jù)到自定義的結(jié)構(gòu)型數(shù)組
- {
- 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) //將時間年,月,日,星期數(shù)據(jù)轉(zhuǎn)換成液晶顯示字符串,放到數(shù)組里DateString[]
- { if(hide_year<2) //這里的if,else語句都是判斷位閃爍,<2顯示數(shù)據(jù),>2就不顯示,輸出字符串為 2012/05/25
- {
- 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'; //星期的數(shù)據(jù)另外放到 week_value[]數(shù)組里,跟年,月,日的分開存放,因為等一下要在最后顯示
- }
- else
- {
- week_value[0] = ' ';
- }
- week_value[1] = '\0';
- Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判斷結(jié)束字符
- }
- void TimeToStr(SYSTEMTIME *Time) //將時,分,秒數(shù)據(jù)轉(zhuǎn)換成液晶顯示字符放到數(shù)組 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) //判斷時鐘芯片是否關(guān)閉
- {
- Write1302(0x8e,0x00); //寫入允許
- Write1302(0x8c,0x12); //以下寫入初始化時間 日期:12/05/25.星期: 5. 時間: 10:59:55
- Write1302(0x88,0x05);
- Write1302(0x86,0x25);
- Write1302(0x8a,0x05);
- Write1302(0x84,0x10);
- Write1302(0x82,0x59);
- Write1302(0x80,0x55);
- Write1302(0x8e,0x80); //禁止寫入
- }
- }
- /***********ds18b20子程序*************************/
- /***********ds18b20延遲子函數(shù)(晶振12MHz )*******/
- void delay_18B20(unsigned int i)
- {
- while(i--);
- }
- /**********ds18b20初始化函數(shù)**********************/
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ復位
- delay_18B20(8); //稍做延時
- DQ = 0; //單片機將DQ拉低
- delay_18B20(80); //精確延時 大于 480us
- DQ = 1; //拉高總線
- delay_18B20(14);
- x=DQ; //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗
- delay_18B20(20);
- }
- /***********ds18b20讀一個字節(jié)**************/
- 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寫一個字節(jié)****************/
- 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); // 啟動溫度轉(zhuǎn)換
- delay_18B20(100); // this message is wery important
- Init_DS18B20();
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0xBE); //讀取溫度寄存器等前兩個就是溫度
- delay_18B20(100);
- a=ReadOneChar(); //讀取溫度值低位
- b=ReadOneChar(); //讀取溫度值高位
- temp_value=b<<4;
- temp_value+=(a&0xf0)>>4;
- }
- void temp_to_str() //溫度數(shù)據(jù)轉(zhuǎn)換成液晶字符顯示
- {
- TempBuffer[0]=temp_value/10+'0'; //十位
- TempBuffer[1]=temp_value%10+'0'; //個位
- TempBuffer[2]=0xdf; //溫度符號
- TempBuffer[3]='C';
- TempBuffer[4]='\0';
- }
- void Delay1ms(unsigned int count)
- {
- unsigned int i,j;
- for(i=0;i<count;i++)
- for(j=0;j<120;j++);
- }
- /*延時子程序*/
- void mdelay(uint delay)
- { uint i;
- for(;delay>0;delay--)
- {for(i=0;i<62;i++) //1ms延時.
- {;}
- }
- }
- void outkey() //跳出調(diào)整模式,返回默認顯示
- { uchar Second;
- if(out==0||wireless_1==1)
- { mdelay(8);
- 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);
- while(wireless_1==1);
- }
- }
- ///////////////////////////////////////////////////////////////////////
- void Upkey()//升序按鍵
- {
- Up=1;
- if(Up==0||wireless_2==1)
- {
- mdelay(8);
- switch(count)
- {case 1:
- temp=Read1302(DS1302_SECOND); //讀取秒數(shù)
- temp=temp+1; //秒數(shù)加1
- up_flag=1; //數(shù)據(jù)調(diào)整后更新標志
- if((temp&0x7f)>0x59) //超過59秒,清零
- temp=0;
- break;
- case 2:
- temp=Read1302(DS1302_MINUTE); //讀取分數(shù)
- temp=temp+1; //分數(shù)加1
- up_flag=1;
- if(temp>0x59) //超過59分,清零
- temp=0;
- break;
- case 3:
- temp=Read1302(DS1302_HOUR); //讀取小時數(shù)
- temp=temp+1; //小時數(shù)加1
- up_flag=1;
- if(temp>0x23) //超過23小時,清零
- temp=0;
- break;
- case 4:
- temp=Read1302(DS1302_WEEK); //讀取星期數(shù)
- temp=temp+1; //星期數(shù)加1
- up_flag=1;
- if(temp>0x7)
- temp=1;
- break;
- case 5:
- temp=Read1302(DS1302_DAY); //讀取日數(shù)
- temp=temp+1; //日數(shù)加1
- up_flag=1;
- if(temp>0x31)
- temp=1;
- break;
- case 6:
- temp=Read1302(DS1302_MONTH); //讀取月數(shù)
- temp=temp+1; //月數(shù)加1
- up_flag=1;
- if(temp>0x12)
- temp=1;
- break;
- case 7:
- temp=Read1302(DS1302_YEAR); //讀取年數(shù)
- temp=temp+1; //年數(shù)加1
- up_flag=1;
- if(temp>0x85)
- temp=0;
- break;
- default:break;
- }
-
- while(Up==0);
- while(wireless_2==1);
- }
- }
- ///////////////////////////////////////////////////////////////////////void Downkey()//降序按鍵
- {
- Down=1;
- if(Down==0||wireless_3==1)
- {
- mdelay(8);
- switch(count)
- {case 1:
- temp=Read1302(DS1302_SECOND); //讀取秒數(shù)
- temp=temp-1; //秒數(shù)減1
- down_flag=1; //數(shù)據(jù)調(diào)整后更新標志
- if(temp==0x7f) //小于0秒,返回59秒
- temp=0x59;
- break;
- case 2:
- temp=Read1302(DS1302_MINUTE); //讀取分數(shù)
- temp=temp-1; //分數(shù)減1
- down_flag=1;
- if(temp==-1)
- temp=0x59; //小于0分,返回59分
- break;
- case 3:
- temp=Read1302(DS1302_HOUR); //讀取小時數(shù)
- temp=temp-1; //小時數(shù)減1
- down_flag=1;
- if(temp==-1)
- temp=0x23;
- break;
- case 4:
- temp=Read1302(DS1302_WEEK); //讀取星期數(shù)
- temp=temp-1; //星期數(shù)減1
- down_flag=1;
- if(temp==0)
- temp=0x7;;
- break;
- case 5:
- temp=Read1302(DS1302_DAY); //讀取日數(shù)
- temp=temp-1; //日數(shù)減1
- down_flag=1;
- if(temp==0)
- temp=31;
- break;
- case 6:
- temp=Read1302(DS1302_MONTH); //讀取月數(shù)
- temp=temp-1; //月數(shù)減1
- down_flag=1;
- if(temp==0)
- temp=12;
- break;
- case 7:
- temp=Read1302(DS1302_YEAR); //讀取年數(shù)
- temp=temp-1; //年數(shù)減1
- down_flag=1;
- if(temp==-1)
- temp=0x85;
- break;
- default:break;
- }
-
- while(Down==0);
- while(wireless_3==1);
- }
- }
- void Setkey()//模式選擇按鍵
- {
- Set=1;
- if(Set==0||wireless_4==1)
- {
- mdelay(8);
- count=count+1; //Setkey按一次,count就加1
- done=1; //進入調(diào)整模式
- while(Set==0);
- while(wireless_4==1);
- }
- }
- void keydone()//按鍵功能執(zhí)行
- { uchar Second;
- if(flag==0) //關(guān)閉時鐘,停止計時
- { Write1302(0x8e,0x00); //寫入允許
- temp=Read1302(0x80);
- Write1302(0x80,temp|0x80);
- Write1302(0x8e,0x80); //禁止寫入
- flag=1;
- }
- Setkey(); //掃描模式切換按鍵
- switch(count)
- {case 1:do //count=1,調(diào)整秒
- {
- outkey(); //掃描跳出按鈕
- Upkey(); //掃描加按鈕
- Downkey(); //掃描減按鈕
- if(up_flag==1||down_flag==1) //數(shù)據(jù)更新,重新寫入新的數(shù)據(jù)
- {
- Write1302(0x8e,0x00); //寫入允許
- Write1302(0x80,temp|0x80); //寫入新的秒數(shù)
- Write1302(0x8e,0x80); //禁止寫入
- up_flag=0;
- down_flag=0;
- }
- hide_sec++; //位閃計數(shù)
- if(hide_sec>3)
- hide_sec=0;
- show_time(); //液晶顯示數(shù)據(jù)
- }while(count==2);break;
- case 2:do //count=2,調(diào)整分
- {
- hide_sec=0;
- outkey();
- Upkey();
- Downkey();
- if(temp>0x60)
- temp=0;
- if(up_flag==1||down_flag==1)
- {
- Write1302(0x8e,0x00); //寫入允許
- Write1302(0x82,temp); //寫入新的分數(shù)
- 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,調(diào)整小時
- {
- hide_min=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
- Write1302(0x8e,0x00); //寫入允許
- Write1302(0x84,temp); //寫入新的小時數(shù)
- 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,調(diào)整星期
- {
- hide_hour=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
- Write1302(0x8e,0x00); //寫入允許
- Write1302(0x8a,temp); //寫入新的星期數(shù)
- 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,調(diào)整日
- {
- hide_week=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
- Write1302(0x8e,0x00); //寫入允許
- Write1302(0x86,temp); //寫入新的日數(shù)
- 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,調(diào)整月
- {
- hide_day=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
- Write1302(0x8e,0x00); //寫入允許
- Write1302(0x88,temp); //寫入新的月數(shù)
- 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,調(diào)整年
- {
- hide_month=0;
- outkey();
- Upkey();
- Downkey();
- if(up_flag==1||down_flag==1)
- {
- Write1302(0x8e,0x00); //寫入允許
- Write1302(0x8c,temp); //寫入新的年數(shù)
- 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; // 跳出調(diào)整模式,返回默認顯示狀態(tài)
- 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() //液晶顯示程序
- {
- DS1302_GetTime(&CurrentTime); //獲取時鐘芯片的時間數(shù)據(jù)
- TimeToStr(&CurrentTime); //時間數(shù)據(jù)轉(zhuǎn)換液晶字符
- DateToStr(&CurrentTime); //日期數(shù)據(jù)轉(zhuǎn)換液晶字符
- ReadTemp(); //開啟溫度采集程序
- temp_to_str(); //溫度數(shù)據(jù)轉(zhuǎn)換成液晶字符
- 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
- Delay1ms(400); //掃描延時
- }
- main()
- {
- flag=1; //時鐘停止標志
- LCD_Initial(); //液晶初始化
- Init_DS18B20( ) ; //DS18B20初始化
- Initial_DS1302(); //時鐘芯片初始化
- up_flag=0;
- down_flag=0;
- done=0; //進入默認液晶顯示
- wireless_1=0;
- wireless_2=0;
- wireless_3=0;
- wireless_4=0;
- while(1)
- {
- while(done==1)
- keydone(); //進入調(diào)整模式
- while(done==0)
- {
- show_time(); //液晶顯示數(shù)據(jù)
- flag=0;
- Setkey(); //掃描各功能鍵
- if((CurrentTime.TimeString[0]=='0'
- && CurrentTime.TimeString[1]=='7'
- && CurrentTime.TimeString[3]=='0'
- &&CurrentTime.TimeString[4]=='0')
- || (CurrentTime.TimeString[0]=='1'
- && CurrentTime.TimeString[1]=='1'
- &&CurrentTime.TimeString[3]=='0
- && CurrentTime.TimeString[4]=='0')
- ||(CurrentTime.TimeString[0]=='1'
- &&CurrentTime.TimeString[1]=='7'
- && CurrentTime.TimeString[3]=='0'
- && CurrentTime.TimeString[4]=='0') )
- fanmang=0;
- else fanmang=1;
- if((CurrentTime.TimeString[0]=='0'
- && CurrentTime.TimeString[1]=='9'
- && CurrentTime.TimeString[3]=='0'
- &&CurrentTime.TimeString[4]=='0')
- || (CurrentTime.TimeString[0]=='1'
- && CurrentTime.TimeString[1]=='4'
- &&CurrentTime.TimeString[3]=='0'
- && CurrentTime.TimeString[4]=='0')
- ||(CurrentTime.TimeString[0]=='1'
- &&CurrentTime.TimeString[1]=='9'
- && CurrentTime.TimeString[3]=='0'
- && CurrentTime.TimeString[4]=='0') )
- zhengchang=0;
- else zhengchang=1;
- }
- }
- }
復制代碼
|