標(biāo)題: 單片機(jī)的交通燈設(shè)計(jì) 自己動(dòng)手DIY 電路原理圖+程序仿真 [打印本頁]

作者: wlxf    時(shí)間: 2018-12-4 23:13
標(biāo)題: 單片機(jī)的交通燈設(shè)計(jì) 自己動(dòng)手DIY 電路原理圖+程序仿真
附件里面有 程序  原理圖    pcb    實(shí)物圖   有興趣的小伙伴  可以看看  

制作出來的實(shí)物圖如下:


第二章  單片機(jī)控制的交通燈的設(shè)計(jì)方案
第一節(jié)  系統(tǒng)工作原理和方案
第二節(jié)  本課題主要內(nèi)容
第三章  交通燈的硬件設(shè)計(jì)
第一節(jié)  電源模塊設(shè)計(jì)
第二節(jié)  單片機(jī)控制模塊設(shè)計(jì)
一、方案選擇
二、復(fù)位電路
三、晶振電路
第三節(jié)  LED顯示模塊
一、LED數(shù)碼管介紹
二、LED數(shù)碼管顯示原理
第四節(jié)  按鍵設(shè)置模塊
第四章  交通燈的軟件設(shè)計(jì)
第一節(jié)  主函數(shù)流程
第二節(jié)  中斷程序模塊
第三節(jié)  數(shù)碼管顯示模塊
第四節(jié)  交通燈電路
第五節(jié)  倒計(jì)時(shí)顯示器電路
第六節(jié)  交通燈設(shè)計(jì)總電路圖
第五章  Proteus仿真
第一節(jié)  Proteus軟件介紹
第二節(jié)  Proteus仿真圖片
第六章  調(diào)試心得
結(jié)  論
致  謝
參考文獻(xiàn)
附  錄
一、英文原文
The General Situation of AT89C51
二、英文翻譯
AT89C51概述
三、源程序

第二章 單片機(jī)控制的交通燈的設(shè)計(jì)方案

第一節(jié) 系統(tǒng)工作原理和方案

設(shè)計(jì)的系統(tǒng)應(yīng)用在一個(gè)車流量大的十字交叉路口,縱向南北方向作為主干道,橫向東西方向?yàn)橹Ц傻馈V、支干道交替通行,兩個(gè)干道上的交通燈工作方式同時(shí)進(jìn)行,主干道每次放行15秒,支干道每次放行10秒;每次綠燈變紅之前,黃燈先亮3秒,此時(shí)另一干道上的紅燈并閃爍。

主干道和支干道各由一組三色交通燈來控制,分別是主干道方向的紅、黃、綠以及支干道方向的紅、黃、綠。邏輯分析可知,當(dāng)主干道為綠燈通行時(shí),支干道必須為紅燈禁行;綠燈結(jié)束后,主干道進(jìn)入黃燈等待狀態(tài),支干道紅燈閃爍;黃燈結(jié)束后,主干道變?yōu)榧t燈禁行,支干道變?yōu)榫G燈通行;支干道綠燈結(jié)束后,支干道進(jìn)入黃燈等待狀態(tài),主干道紅燈閃爍,如此循環(huán)。從這個(gè)過程中可以看出,交通燈控制共分4個(gè)狀態(tài),分別為:S1狀態(tài),主干道方向?yàn)榫G燈,支干道方向?yàn)榧t燈;S2狀態(tài),主干道方向?yàn)辄S燈,支干道紅燈閃爍;S3狀態(tài),主干道方向?yàn)榧t燈,支干道方向?yàn)榫G燈;S4狀態(tài),支干道方向?yàn)辄S燈,主干道紅燈閃爍,這四個(gè)狀態(tài)不斷循環(huán)。由此我們可以列出4個(gè)狀態(tài)的列表和做出4個(gè)狀態(tài)的流程圖。

表2.1  信號燈狀態(tài)表


主干道方向

支干道方向

說明

S1

12s常亮

S2

閃爍

S1->S2

S3

7s常亮

S4

閃爍

S3->S4






圖2.1 交通燈流程圖


系統(tǒng)設(shè)置有4個(gè)按鍵,分別為Enter鍵,+鍵,-鍵和Shift鍵。Enter鍵是對設(shè)置的確認(rèn),+和-是對設(shè)置參數(shù)做調(diào)整,Shift鍵是對程序運(yùn)行和參數(shù)設(shè)置兩種狀態(tài)的切換。當(dāng)系統(tǒng)上電或手動(dòng)復(fù)位之后,默認(rèn)模式下會(huì)按照斷電前程序里記錄的參數(shù)運(yùn)行。若此時(shí)Shift鍵按下,則設(shè)置為參數(shù)設(shè)置狀態(tài),數(shù)碼管上顯示原本記錄的參數(shù)并閃爍,可通過+或-鍵對參數(shù)進(jìn)行修改,最后按下Enter鍵將新參數(shù)保存。


圖2.2 系統(tǒng)整體框架圖

然后系統(tǒng)控制狀態(tài)燈和LED數(shù)碼管的顯示,將狀態(tài)碼值以及顯示的時(shí)間值的個(gè)位和十位送到相應(yīng)IO口,通過定時(shí)器設(shè)定1s定時(shí),當(dāng)定時(shí)時(shí)間達(dá)到時(shí)產(chǎn)生定時(shí)器中斷,在中斷中將時(shí)間減一,然后刷新LED數(shù)碼管的顯示。直到時(shí)間值被減為0,判斷下一個(gè)指示燈狀態(tài)并裝入對應(yīng)的狀態(tài)代碼和時(shí)間值的狀態(tài)。


圖2.2狀態(tài)燈和LED顯示圖



第二節(jié) 本課題主要內(nèi)容

本課題的主要內(nèi)容是設(shè)計(jì)了一種基于AT89C51單片機(jī)的控制的交通燈設(shè)計(jì)。這次設(shè)計(jì)以單片機(jī)為主要控制器,可以方便的實(shí)現(xiàn)十字路口交通燈的控制,實(shí)現(xiàn)行人與車流的分流,該系統(tǒng)控制期間各路轉(zhuǎn)彎不再進(jìn)行。擬解決的主要問題:

①模擬交通信號燈的交替變換。

②系統(tǒng)硬件設(shè)計(jì)與實(shí)現(xiàn)。

③系統(tǒng)軟件設(shè)計(jì)。

④系統(tǒng)軟硬件綜合調(diào)試。

研究主要方法:

本設(shè)計(jì)根據(jù)實(shí)際交通法則模擬基本的交通控制系統(tǒng),用紅色LED表示禁行,綠色LED表示通行,黃色LED表示等待的信號,每個(gè)方向有一組LED數(shù)碼管,可以倒計(jì)時(shí)顯示提醒行駛者。據(jù)此,本設(shè)計(jì)系統(tǒng)以單片機(jī)為控制核心,連接成最小系統(tǒng),和按鍵設(shè)置模塊等產(chǎn)生輸入,信號燈狀態(tài)模塊,LED倒計(jì)時(shí)模塊。

研究要求:

①單片機(jī)型號:AT89C51

②縱向?yàn)橹鞲傻溃瑱M向?yàn)橹Ц傻。主、支干道交替通行,兩個(gè)干道上的交通燈工作方式同時(shí)進(jìn)行。

③主干道每次放行15秒,支干道每次放行10秒。

④每次綠燈變紅之前,黃燈先亮3秒,此時(shí)另一干道上的紅燈并閃爍。

⑤給出整個(gè)系統(tǒng)的結(jié)構(gòu)圖、軟硬件流程


第三章 交通燈的硬件設(shè)計(jì)

第一節(jié) 電源模塊設(shè)計(jì)

系統(tǒng)要想正常而穩(wěn)定的運(yùn)行,必須要有一套穩(wěn)定的電源電路。為了給單片機(jī)和各種芯片提供工作電壓,需要將交流220V轉(zhuǎn)換為直流5V。

根據(jù)模擬電路學(xué)到的知識,轉(zhuǎn)換過程如圖3.1所示:

變壓器經(jīng)過一個(gè)保險(xiǎn)絲連接電源,變壓器或后面的電路如果發(fā)生短路,保險(xiǎn)絲會(huì)因大電流引發(fā)的高溫溶化而斷開,從而保證后續(xù)電路不會(huì)受大電流的損壞。

變壓器后面是一個(gè)橋式整流電路,整流后會(huì)得到一個(gè)紋波很大的直流電源,還需要接一個(gè)1000uF/25V的電解電容濾除紋波。

變壓器輸出端的電壓經(jīng)過橋式整流并電容濾波,如果電容兩端直接接負(fù)載,當(dāng)負(fù)載變化或交流電源電壓出現(xiàn)波動(dòng)時(shí),電解電容C1兩端的電壓會(huì)發(fā)生較大幅度變化,要得到一個(gè)比較穩(wěn)定的電壓,需要在這里接一個(gè)三端穩(wěn)壓器。

當(dāng)負(fù)載電流大時(shí)穩(wěn)壓器內(nèi)的電阻會(huì)變小,當(dāng)負(fù)載電流變小時(shí)三端穩(wěn)壓器內(nèi)的電阻又會(huì)變大,使的穩(wěn)壓器的輸出電壓基本保持不變。

單片機(jī)和大多數(shù)功能芯片的輸入電壓都是直流5V,這里我們需要將交流220V經(jīng)過變壓器轉(zhuǎn)換為9V的電壓,整流后經(jīng)7805穩(wěn)壓成直流5V。LM7805最大輸出電流為1A,內(nèi)部有限流式短路保護(hù),短時(shí)間內(nèi)輸出端對地(2腳)短路不會(huì)燒壞7805。

三端穩(wěn)壓器后面接一個(gè)104的瓷片電容,起濾波和阻尼作用。


圖3.1 220V交流穩(wěn)壓成5V直流原理


第二節(jié) 單片機(jī)控制模塊設(shè)計(jì)

一、方案選擇

方案一:AVR單片機(jī)。AVR不是一個(gè)簡單的外設(shè)功能的疊加,但更多的模型以滿足不同設(shè)計(jì)開發(fā)者的實(shí)際需要,同時(shí)可以提供一個(gè)低成本的OTP芯片。此外,PIC是低功耗的睡眠功能、深度睡眠、上電、掉電復(fù)位電路、看門狗電路,外圍設(shè)備,占用空間;成本低,安全技術(shù)也非?煽,能夠最大程度地滿足開發(fā)者的實(shí)際要求。因此,在工業(yè)控制,PIC單片機(jī)被廣泛的應(yīng)用到各行各業(yè)的控制中,其穩(wěn)定性、系統(tǒng)功耗等都為廣大開發(fā)者認(rèn)可。價(jià)格相比同性能產(chǎn)品在中上游水平。

方案二:PIC24H64GP506是16位RISC混合信號處理器,具有以下特點(diǎn):

工作電壓低,最低工作電壓1.8V下正常工作。

功耗小,在運(yùn)行模式下,只有200mA的工作電流,在休眠和待機(jī)模式下只有3ma的電流,在power off狀態(tài)下只需要用0.1mA;運(yùn)行狀態(tài)中包含提供6種運(yùn)行模式,3個(gè)時(shí)鐘信號,包括1個(gè)高頻率的時(shí)鐘,1個(gè)低頻時(shí)鐘和1的DCO,靈活的時(shí)鐘選擇使系統(tǒng)能夠在最合理的時(shí)鐘工作,大大降低了系統(tǒng)功耗,便于系統(tǒng)的設(shè)計(jì)。

豐富的外設(shè)接口,包括標(biāo)準(zhǔn)的UART,SPI、I2C接口,可以和具有相同接口的設(shè)備連接進(jìn)行通訊采集相關(guān)外設(shè)的數(shù)據(jù)。該MCU,具有256位RAM和8 kbit Flash內(nèi)部;中斷喚醒功能,可以通過中斷使單片機(jī)從睡眠模式到主動(dòng)模式。

方案三:選擇價(jià)格低廉的51系列單片機(jī),具有51內(nèi)核的低功耗、高性能的8位單片機(jī),內(nèi)含4K字節(jié)Flash只讀程序存儲(chǔ)器,兼容MCS-51指令和80C5l引腳結(jié)構(gòu),功能強(qiáng)大的微型計(jì)算機(jī)的AT89C51為工業(yè)控制應(yīng)用系統(tǒng)提供低成本、高可靠性的解決方案。它具有如下特點(diǎn):128字節(jié)內(nèi)部RAM,32個(gè)I/O口線,看門狗,兩個(gè)16位定時(shí)和計(jì)數(shù)單元,一個(gè)5兩級中斷結(jié)構(gòu)的向量,一個(gè)UART通信口,內(nèi)部晶振和時(shí)鐘電路。

根據(jù)系統(tǒng)實(shí)際需要,最終選擇成本低廉,便于操作的51系列單片機(jī),型號為STC80C51。如圖3.2所示為51系列單片機(jī)內(nèi)核示意圖,圖3.3所示為AT80C51單片機(jī)最小系統(tǒng)電路圖。



圖3.2 8051單片機(jī)內(nèi)核結(jié)構(gòu)示意圖

圖3.3 STC80C51單片機(jī)最小系統(tǒng)電路圖

二、復(fù)位電路

單片機(jī)最小系統(tǒng)是指一個(gè)微控制器系統(tǒng)可以正常工作需要具備的最少的元件構(gòu)成的系統(tǒng)。51系列單片機(jī)的最小系統(tǒng)一般應(yīng)包括:單片機(jī),晶振電路,復(fù)位電路。

復(fù)位電路由電阻電容和電阻串聯(lián)組成,根據(jù)電容電壓不能突然改變的性質(zhì)可以知道,一個(gè)系統(tǒng)上電,RST引腳默認(rèn)為低電平,RC電路來決定高電平的時(shí)間。一個(gè)典型的51單片機(jī),當(dāng)RST引腳為高電平兩個(gè)機(jī)器周期以上的將被重置,所以RC值要選擇適當(dāng),才能確保可靠的復(fù)位,根據(jù)t=R*C,t要大于兩個(gè)機(jī)器周期,選擇電阻阻值為10k,電容容值為10uF。當(dāng)然還有其他的參數(shù)組合,只要滿足原理使RC組合可以產(chǎn)生在RST引腳置高至少兩個(gè)機(jī)器周期。至于如何具體量化的計(jì)算,可以參考電路分析的書籍。

單片機(jī)復(fù)位電路就像電腦的重啟,按下復(fù)位按鈕內(nèi)部的程序?qū)念^開始運(yùn)行。單片機(jī)系統(tǒng)在運(yùn)行中,可能因?yàn)榄h(huán)境干擾等因素導(dǎo)致運(yùn)行失控,就可以通過復(fù)位按鍵實(shí)現(xiàn)對單片機(jī)系統(tǒng)的重新啟動(dòng)。

在電路圖中,電容器的容值為10uF,電阻器阻值為10k。所以根據(jù)公式,充電電容器增大到0.7倍電源電壓,即設(shè)備電源是5V,充電電容器電壓增長到5*0.7=3.5V這一過程所需要的時(shí)間是10K * 10UF = 0.1S。

也就是說,在計(jì)算機(jī)啟動(dòng)0.1S的過程中,電容兩端的電壓會(huì)從0增大到3.5V。這段時(shí)間內(nèi)在電阻10K兩端的電壓會(huì)降低到1.5V(串聯(lián)周圍電路中的電壓和總電壓)。所以在0.1S,RST引腳電壓為5V?1.5V。微控制器啟動(dòng)之后0.1S,電容C連續(xù)充電到5V,這是10K電阻兩端的電壓接近0V,RST在低電平,以使系統(tǒng)正常工作。當(dāng)按下按鈕時(shí),該開關(guān)被接通時(shí),這時(shí)在電容器兩端形成環(huán)路,電容器被短路,電容器放電。隨著時(shí)間的推移,電容器兩端的電壓,從5V釋放成為1.5V,或甚至更小。這時(shí)10K電阻器兩端的電壓達(dá)到3.5V,或甚至更多,所以RST引腳變?yōu)楦唠娖剑瑔纹瑱C(jī)系統(tǒng)自動(dòng)復(fù)位。

原則是微控制器復(fù)位電路RST引腳接收超過2US的高電平信號,只要電容器充電和放電時(shí)間大于2US,即可復(fù)位,該電路的電容值和電阻值可以根據(jù)實(shí)際電路做修改。按復(fù)位鍵,使電容短路,釋放之前儲(chǔ)存的能量,使電阻兩端電壓升高,從而給RST引腳一個(gè)高電平。


三、晶振電路

晶振電路是由振蕩晶體和兩個(gè)電容組成,為單片機(jī)提供指令時(shí)鐘。對于51系統(tǒng),外部晶振通常選擇11.0592MHz,這樣可以產(chǎn)生精準(zhǔn)的微秒級別的機(jī)器時(shí)間,準(zhǔn)確地得到9600bps和19200bps,用于有串口通訊的場合,方便定時(shí)操作。晶振電路在PCB布線設(shè)計(jì)時(shí)一定要盡量靠近單片機(jī),并且兩個(gè)引腳到單片機(jī)的走線盡量一樣長,如果偏差太大會(huì)導(dǎo)致起振不良,或者計(jì)時(shí)不準(zhǔn)確。晶振電路的地一定要和單片機(jī)的地共地,51單片機(jī)最小系統(tǒng)晶振在正常工作的情況下可以采用更高頻率的晶振,51單片機(jī)最小系統(tǒng)晶振的振蕩頻率直接影響單片機(jī)的處理速度,頻率越大處理速度越快。在晶振頻率的選擇上,在能夠滿足系統(tǒng)需要的前提下盡可能的選擇低頻率的晶振,晶振頻率越低其功耗的能量越低,所以并不是晶振頻率越高越好,要根據(jù)實(shí)際情況對頻率和功耗進(jìn)行取舍。

單片機(jī)的外部晶振如果單獨(dú)跟單片機(jī)連接,理論上也是可以起振使單片機(jī)工作的,只是這樣的結(jié)構(gòu)會(huì)使電路中產(chǎn)生很多其他頻率的諧波,諧波會(huì)降低時(shí)鐘振蕩器的穩(wěn)定性。因此,在外部晶振的旁邊會(huì)通過加一對起振電容去過濾諧波。起振電容的容值沒有特別固定的值,根據(jù)不同的單片機(jī)會(huì)有不同的選擇范圍,51系列單片機(jī)的起振電容一般在15~30pF,在做PCB布線時(shí)起振電容離晶振越近越好,而晶振離單片機(jī)也是越近越好




第三節(jié) LED顯示模塊
一、LED數(shù)碼管介紹

LED數(shù)碼管是由多個(gè)發(fā)光二極管被封裝在一起,以形成“8”字形的裝置,引線被連接在內(nèi)部,每個(gè)二極管有自己的一個(gè)引腳,他們共同具有一個(gè)公共電極。數(shù)碼管里有顯示7段和一個(gè)小數(shù)點(diǎn)的8個(gè)發(fā)光二極管,就會(huì)看到相應(yīng)的數(shù)碼管段被點(diǎn)亮。

當(dāng)一個(gè)特定的段的LED被施加電壓時(shí),這些特定的段將被點(diǎn)亮,以形成我們眼睛看到的圖像。8段LED數(shù)碼管只能顯示簡單的0~9的阿拉伯?dāng)?shù)字和A~F的英文字母,有一些段數(shù)比較多的LED可以顯示更多的內(nèi)容,總之,數(shù)碼管還是以顯示數(shù)字和字母為主,復(fù)雜的顯示信息還是需要考慮使用液晶之類的更為復(fù)雜的電子器件。如圖3.4所示為8段LED數(shù)碼管示意圖。


圖3.4 LED數(shù)碼管示意圖


二、LED數(shù)碼管顯示原理

LED數(shù)碼管主要是通過點(diǎn)亮相應(yīng)段的發(fā)光二極管,在視覺上給人們顯示出各個(gè)數(shù)字和字母的形狀,驅(qū)動(dòng)LED數(shù)碼管的方式有兩種,一種是靜態(tài)顯示驅(qū)動(dòng),另一種是動(dòng)態(tài)顯示驅(qū)動(dòng)。靜態(tài)顯示驅(qū)動(dòng),也被稱為直流驅(qū)動(dòng)。靜態(tài)驅(qū)動(dòng)的裝置,每個(gè)段需要由單片機(jī)的一個(gè)I / O口來驅(qū)動(dòng),或者作為BCD碼兩用。靜態(tài)驅(qū)動(dòng)的優(yōu)點(diǎn)是編程簡單,顯示亮度高,缺點(diǎn)是占用I/ O端口多,加入需要驅(qū)動(dòng)4個(gè)8段的數(shù)碼管,則需要4*8=32個(gè)IO口,而51單片機(jī)可用的I/O端口一共只有32。我們在實(shí)際應(yīng)用中必須增加的編解碼驅(qū)動(dòng)器,來減少I/O口的浪費(fèi),同時(shí)也增加了硬件電路的復(fù)雜性。第二種是動(dòng)態(tài)顯示驅(qū)動(dòng),數(shù)碼管動(dòng)態(tài)顯示方式在微控制器中被廣泛使用。動(dòng)態(tài)顯示是利用了人眼具有視覺停留現(xiàn)象,即人眼在看到某一景物后,在很短的時(shí)間內(nèi),即使該景物消失,在人眼中還會(huì)保留該景物的像。動(dòng)態(tài)顯示就是將數(shù)字按照個(gè)十百千位的格式分開,根據(jù)各個(gè)位的數(shù)字分別控制點(diǎn)亮對應(yīng)數(shù)碼管的發(fā)光二極管的段。每次只點(diǎn)亮一個(gè)位對應(yīng)的數(shù)碼管,其他位的數(shù)碼管被熄滅。

通過依次控制每個(gè)LED數(shù)碼管的COM端,它使每一個(gè)對應(yīng)的數(shù)字顯示,這是一個(gè)動(dòng)態(tài)的過程。反過來顯示,每位數(shù)碼管點(diǎn)亮?xí)r間為1?2毫秒,由于人的視覺和發(fā)光二極管的余輝效應(yīng)的持續(xù)性的現(xiàn)象,盡管你不是在同一時(shí)間點(diǎn)亮數(shù)碼管,但事實(shí)只要掃描速度足夠快,給人的印象是一組穩(wěn)定的顯示數(shù)據(jù),不會(huì)有閃爍感,動(dòng)態(tài)顯示和靜態(tài)顯示的效果是一樣的,但是可以節(jié)省大量的I / O端口,以及更低功耗。因此動(dòng)態(tài)顯示更為廣泛的被應(yīng)用。

第四節(jié) 按鍵設(shè)置模塊

鍵盤是最常用的單片機(jī)系統(tǒng)的人機(jī)界面,根據(jù)組合形式可分為兩種:獨(dú)立式和陣列式。獨(dú)立式鍵盤由于一個(gè)按鍵需要對應(yīng)一個(gè)IO口,因此適合用于按鍵數(shù)量少的場合;陣列式是通過橫向和縱向交叉檢測,可以將IO口的使用數(shù)量呈指數(shù)減少,例如三根橫向和三根縱向線交叉可以實(shí)現(xiàn)9個(gè)鍵碼的分辨,如果按獨(dú)立式鍵盤設(shè)計(jì),需要9個(gè)IO口,而陣列式鍵盤只需要6個(gè)IO口,按鍵數(shù)量越多,可以節(jié)省的IO口就越多,所以陣列式非常適用于需要按鍵較多的情況,本系統(tǒng)需要小按鈕控制,單片機(jī)的I / O端口足夠,可直接使用獨(dú)立式設(shè)計(jì)。按鍵電路原理圖如圖3.7所示。


圖3.7 獨(dú)立式按鍵電路

鍵盤開關(guān)矩陣由多個(gè)按鈕組成,是單芯片系統(tǒng)中最常用的輸入裝置,可以將命令,地址和數(shù)據(jù)輸入給單片機(jī)。通常單片機(jī)系統(tǒng)采用非編碼鍵盤,非編碼鍵盤由軟件識別的鍵盤上的按鍵,它具有結(jié)構(gòu)簡單,靈活的特點(diǎn),因此被廣泛應(yīng)用于微處理器系統(tǒng)。鍵盤按鈕分為接觸式和非接觸式兩種,微控制器應(yīng)用的按鍵通常由一個(gè)機(jī)械鍵盤接觸組成。

當(dāng)開關(guān)K沒有被按下時(shí),KeyIn由于通過4.7K的上拉電阻與5V電源連接,因此輸入為高,當(dāng)K閉合后,KeyIn與GND短接,輸入為低電平。也就是說,程序檢測按鍵是否按下的方法是檢測對應(yīng)IO由高電平變成低電平,就表示該按鍵被按下。

但是由于按鍵結(jié)構(gòu)采用的是機(jī)械觸點(diǎn),機(jī)械觸電在狀態(tài)變化的瞬間會(huì)產(chǎn)生電壓的波動(dòng),這種抖動(dòng)對于人的感知來說是極快的,根本感覺不到,但對于處理速度達(dá)到微秒級甚至納秒級的單片機(jī)來說,這就是一段很長的時(shí)間了,在這段時(shí)間里,所有的電壓波動(dòng)都能被單片機(jī)一一檢測到,單純的只是檢測IO的邊沿變化就會(huì)在機(jī)械觸電處于不穩(wěn)定狀態(tài)時(shí)誤認(rèn)為是按鍵被按下,而且會(huì)出現(xiàn)多次。如果設(shè)置為中斷查詢,程序就是頻繁的進(jìn)入中斷函數(shù)。

解決這種問題的方法也很簡單,就是我們通常所說的去抖。原理就是避開機(jī)械觸點(diǎn)物理上會(huì)產(chǎn)生不穩(wěn)定電壓的時(shí)間段,再去檢測IO口的電平。不管是通過輪詢檢測還是中斷檢測,一旦檢測到按鍵IO口電平狀態(tài)相比默認(rèn)狀態(tài)發(fā)生改變,則加入一小段延時(shí),一般為幾十個(gè)毫秒,延時(shí)過后,再去檢測IO的電平,如果又變回默認(rèn)狀態(tài),就說明這屬于干擾導(dǎo)致的按鍵抖動(dòng),不需要處理;反之,則是真正的按鍵被按下的信號。

根據(jù)去抖的原理,我們也可以發(fā)現(xiàn),去抖的延時(shí)時(shí)間也不能設(shè)置太長,否則會(huì)出現(xiàn)延時(shí)結(jié)束時(shí)按鍵早已經(jīng)被松開,這樣就導(dǎo)致有按鍵被按下卻無法識別到。按鈕在實(shí)際應(yīng)用中千差萬別,要根據(jù)實(shí)際按鍵的方式以及硬件電路等多方面因素去靈活運(yùn)用,但以上的去抖原則是一定要遵循的。

第四章  交通燈的軟件設(shè)計(jì)
第一節(jié) 主函數(shù)流程

在主函數(shù)流程中,首先單片機(jī)要實(shí)現(xiàn)自身寄存器的初始化,定時(shí)器初始化以及數(shù)碼管和紅綠燈狀態(tài)顯示控制,因?yàn)樵谶\(yùn)行過程中,數(shù)碼管需要顯示倒計(jì)時(shí)的時(shí)間,單片機(jī)可利用定時(shí)器T0和T1進(jìn)行計(jì)時(shí),設(shè)置定時(shí)器中斷,在中斷函數(shù)中對時(shí)間進(jìn)行刷新。對于系統(tǒng)按鍵的檢測可以使用主循環(huán)輪詢方式,也可以采用外部中斷處理方式。為了更加快速的響應(yīng)按鍵信息,在程序中通過外部中斷來實(shí)現(xiàn)按鍵的檢測。

根據(jù)系統(tǒng)程序運(yùn)行的特點(diǎn)分析,每個(gè)交通燈的狀態(tài)都是從S1->S2->S3->S4->S1,如此循環(huán)往復(fù),這些狀態(tài)是固定的,而從一個(gè)狀態(tài)轉(zhuǎn)變?yōu)榱硪粋(gè)狀態(tài)的條件也是固定的,所以,在編程時(shí)采用狀態(tài)機(jī)的處理方式是最合適的,狀態(tài)機(jī)會(huì)比普通的邏輯羅列要清楚的多,也不易于出現(xiàn)邏輯上的錯(cuò)誤,只是需要把各個(gè)狀態(tài)都考慮清楚,不要留有狀態(tài)上的漏洞。如圖4.1所示為系統(tǒng)主函數(shù)流程圖。


圖4.1 系統(tǒng)主函數(shù)流程圖

狀態(tài)機(jī)是在軟件程序設(shè)計(jì)中的一個(gè)重要的概念。例如,一個(gè)按鈕命令,它可以被看作是一個(gè)狀態(tài)機(jī):一個(gè)狀態(tài)為A,按下按鈕后切換到B狀態(tài);然后觸發(fā)另一個(gè)鍵切換到C的狀態(tài),或者返回的狀態(tài)。這是關(guān)鍵的狀態(tài)機(jī)的最簡單的例子。實(shí)際分析方法比這些要復(fù)雜的多,但是這并不影響我們的狀態(tài)機(jī)的理解。此外,按鍵本身可以被看作是一個(gè)狀態(tài)機(jī)。一個(gè)小按鍵,包括:釋放,抖動(dòng),閉合,抖動(dòng)等狀態(tài)。

要保證程序高效穩(wěn)定的運(yùn)行,除了各個(gè)功能模塊程序,還需要一個(gè)重要的模塊就是看門狗。在單片機(jī)系統(tǒng)中,由于微控制器的操作可能會(huì)受到來自外部電磁場的干擾,使程序失控陷入死循環(huán)中,程序的正常運(yùn)行被中斷,由MCU控制的系統(tǒng)不能繼續(xù)工作,這將導(dǎo)致整個(gè)系統(tǒng)停頓,造成不可預(yù)料的后果,因此為了對微控制器的運(yùn)行狀況進(jìn)行實(shí)時(shí)監(jiān)控,單片機(jī)中有一個(gè)專門的硬件電路,俗稱“看門狗”。

加入看門狗電路的目的是使微控制器可以實(shí)現(xiàn)連續(xù)工作,避免進(jìn)入程序跑飛的死循環(huán),看門狗功能模塊是內(nèi)嵌在單片機(jī)內(nèi)部的,與單片機(jī)的I / O引腳相連,該引腳可以通過程序的控制,定期向單片機(jī)引腳送出高電平或低電平。一旦受到干擾,單片機(jī)程序跑飛,并陷入一個(gè)無限循環(huán),看門狗引腳發(fā)送電平的功能不能被執(zhí)行,這個(gè)時(shí)候,看門狗電路會(huì)由于缺乏由MCU發(fā)出的信號,向跟它連在一起的復(fù)位電路的引腳發(fā)送一個(gè)復(fù)位信號,使微控制器重新從程序存儲(chǔ)器的起始位置執(zhí)行代碼,這樣就實(shí)現(xiàn)了單芯片自動(dòng)復(fù)位。

以前,看門狗電路需要一個(gè)特殊的看門狗芯片連接到單片機(jī)來實(shí)現(xiàn),但是這會(huì)帶來復(fù)雜的電路設(shè)計(jì)。隨著技術(shù)的不斷進(jìn)步,現(xiàn)在的單片機(jī)基本都內(nèi)置看門狗電路,看門狗定時(shí)器寄存器,查看其相應(yīng)的功能知識點(diǎn)。




第二節(jié) 中斷程序模塊

單片機(jī)的定時(shí)器可以根據(jù)程序設(shè)置的分頻頻率進(jìn)行計(jì)數(shù),當(dāng)計(jì)數(shù)達(dá)到某個(gè)設(shè)定值時(shí),可以產(chǎn)生一個(gè)中斷事件。比如51單片機(jī)外部晶振12M,最大計(jì)數(shù)兩個(gè)字節(jié),也就是65535,計(jì)一個(gè)數(shù)的時(shí)間為1/12M秒,就算計(jì)數(shù)值設(shè)為最大值的65535,也不可能計(jì)時(shí)1s,因此,需要在進(jìn)入定時(shí)中斷后對次數(shù)進(jìn)行累加,比如中斷累計(jì)20次,就表示當(dāng)前計(jì)時(shí)為20*65535/12M=0.109225s。因此想要延時(shí)1s,需要將計(jì)數(shù)值設(shè)置為60000的情況下,進(jìn)入中斷200次。

MCS-51的工作頻率通常情況為12MHz,機(jī)器周期與單片機(jī)工作頻率相關(guān),機(jī)器周期是12倍的工作頻率,因此一個(gè)機(jī)器周期的時(shí)間長度為12 *(1 / 12MHZ)= 1微秒。我們可以知道每個(gè)指令周期的特定數(shù)目,這樣我們就可以由一個(gè)指令執(zhí)行的數(shù)量確定需要的時(shí)間。

中斷程序分為定時(shí)器中斷和外部中斷。中斷初始化函數(shù)和中斷處理服務(wù)函數(shù)模塊如下:

/**************定時(shí)器0初始化***********************

* 名稱 : Time0_Init()

* 功能 : 定時(shí)器的初始化,12MZ晶振,50ms

* 輸入 : 無

* 輸出 : 無

****************************************************/

void Time0_Init()

{

TMOD = 0x11;

TH1 = 0xec;

TL1 = 0x78;

EA = 1;

ET0 = 1;

TR0 = 1;                           

}

/************外部中斷0 的初始化***********************

* 名稱 : Outside_Init()

* 功能 : 外部中斷0 的初始化

* 輸入 : 無

* 輸出 : 無

*******************************************************/

void Outside_Init(void)

{

EX0 = 1;  //開外部中斷0

IT0 = 1;  //負(fù)邊沿觸發(fā)

EA = 1;  //開總中斷

}

/*****************定時(shí)器1***********************************

* 名稱 : Time1_Int()

* 功能 : 顯示定時(shí)器,工作方式1

* 輸入 : 無

* 輸出 : 無

****************************************************************/

void Time1_Int() interrupt 3

{

TH1 = 0xec;

TL1 = 0x78;

TR1=1;

if(key1<=3)

display();

else

ndisplay();                                         

}

中斷0服務(wù)程序

/****************外部中斷0 服務(wù)函數(shù)********************************

* 名稱 : Outside_Int()

* 功能 : 外部中斷0 的中斷處理

* 輸入 : 無

* 輸出 : 無

*******************************************************************/

void Outside_Int(void) interrupt 0

{

EX0 = 0;

delay(30); //對按鍵進(jìn)行抗干擾處理

if(key1 < 6)

{  key1++;}

else

key1=0;

delay(30);

EX0 = 1;            

}




第三節(jié) 數(shù)碼管顯示模塊

表4.1為數(shù)碼管顯示數(shù)字與各個(gè)段的對應(yīng)表:

表4.1 數(shù)碼管段位對照表

顯示數(shù)值

a

b

c

d

e

f

g

dp

驅(qū)動(dòng)代碼(16進(jìn)制)

0

1

1

1

1

1

1

0

0

0xFC

1

0

0

0

1

1

0

0

0

0x18

2

1

0

1

1

0

1

1

0

0xC6

3

1

1

1

0

0

1

1

0

0xE6

4

1

1

0

0

1

0

1

0

0xDA

5

0

1

1

0

1

1

1

0

0x6E

6

0

1

1

1

1

1

1

0

0x7E

7

1

1

0

0

0

1

0

0

0xD4

8

1

1

1

1

1

1

1

0

0xFE

9

1

1

1

0

1

1

1

0

0xEE





第四節(jié) 交通燈電路

設(shè)計(jì)中采用發(fā)光二極管作為交通燈來使用,單片機(jī)的I/O接口直接和交通燈(發(fā)光二極管)連接。在十字路口的四組紅、黃、綠三色交通燈中,東西方向道路上的兩組同色燈連接在一起,南北方向道路上的兩組同色的燈也彼此連接在,受單片機(jī)P2.2~P2.7控制。單片機(jī)的I/O接口與交通燈電路的具體連接方式為:P2.5~P2.7分別接?xùn)|西方向的紅、黃、綠共6個(gè)放光二極管,P2.2~P2.4分別接南北方向的紅、黃、綠共6個(gè)發(fā)光二極管。12個(gè)發(fā)光二極管采用了共陰極的連接方式,因此I/O口輸出高電平時(shí),與之相連的發(fā)光二極管會(huì)亮,I/O口輸出低電平時(shí),相應(yīng)的發(fā)光二極管會(huì)滅。交通燈電路原理圖如下圖所示。


            

圖4.2交通燈電路圖



第五節(jié)倒計(jì)時(shí)顯示器電路

該顯示器選用雙位數(shù)碼管來顯示交通燈轉(zhuǎn)換的剩余時(shí)間,根據(jù)設(shè)計(jì)的要求,每個(gè)路口需要1個(gè)數(shù)碼管,這樣就要4個(gè)數(shù)碼管。我們可以選用共陰型數(shù)碼管。四個(gè)路口倒計(jì)時(shí)顯示被置在同一時(shí)刻顯示不同的數(shù)字。電路如下圖

圖4.3倒計(jì)時(shí)顯示器電路圖



第六節(jié)交通燈設(shè)計(jì)總電路圖

我們把倒計(jì)時(shí)顯示器電路圖、單片機(jī)、其他硬件連接起來,就有了總的電路圖。以下是交通燈總電路圖和PCB圖。


圖4.4 交通燈總電路圖

  

圖4.5 交通燈PCB圖
第五章  Proteus仿真

第一節(jié)  Proteus軟件介紹

Proteus軟件是英國Labcenter electronics公司出版的EDA工具軟件,它不僅具有其它EDA工具軟件的仿真功能,還能仿真單片機(jī)及外圍器件。它是目前最好的仿真單片機(jī)及外圍器件的工具。雖然目前國內(nèi)推廣剛起步,但已受到單片機(jī)愛好者、從事單片機(jī)教學(xué)的教師、致力于單片機(jī)開發(fā)應(yīng)用的科技工作者的青睞。Proteus是世界上著名的EDA工具(仿真軟件),從原理圖布圖、代碼調(diào)試到單片機(jī)與外圍電路協(xié)同仿真,一鍵切換到PCB設(shè)計(jì),真正實(shí)現(xiàn)了從概念到產(chǎn)品的完整設(shè)計(jì)。是目前世界上唯一將電路仿真軟件、PCB設(shè)計(jì)軟件和虛擬模型仿真軟件三合一的設(shè)計(jì)平臺(tái),其處理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,2010年即將增加Cortex和DSP系列處理器,并持續(xù)增加其他系列處理器模型。在編譯方面,它也支持IAR、Keil和MPLAB等多種編譯器。本次設(shè)計(jì)就是用該軟件成功仿真程序運(yùn)行。




第二節(jié)  Proteus仿真圖片

軟件運(yùn)行后,交通燈開始工作(二極管顯示紅、黃、綠三色燈,LED顯示倒計(jì)時(shí)),系統(tǒng)自動(dòng)進(jìn)入狀態(tài)S1:縱向南北主干道方向綠燈亮,橫向東西支干道方向紅燈亮,南北主干道LED倒計(jì)時(shí)12秒,東西支干道LED倒計(jì)時(shí)7秒后,系統(tǒng)進(jìn)入(S1~S2)然后南北方向黃燈亮3秒,東西方向紅燈閃爍。仿真圖片如下。











圖4.6 S1狀態(tài)

圖4.7 S1~S2

3秒之后,系統(tǒng)進(jìn)入S3狀態(tài),縱向南北方向紅燈亮,橫向東西方向綠燈亮,仿真圖如下。

圖4.8 S3狀態(tài)

7秒后系統(tǒng)進(jìn)入轉(zhuǎn)換階段,縱向南北方向紅燈閃爍,橫向東西方向黃燈亮3秒,仿真圖如下。


圖4.9 轉(zhuǎn)換階段


第六章  調(diào)試心得

在整個(gè)系統(tǒng)的調(diào)試過程中,由于自身經(jīng)驗(yàn)的缺乏,不管是在硬件方面還是軟件方面,都遇到了很多問題,經(jīng)過各方查閱資料和老師同學(xué)的幫助,終于將問題一一解決,并總結(jié)了一些經(jīng)驗(yàn)教訓(xùn)。

焊接時(shí)首先焊接電源部分的器件,如果發(fā)現(xiàn)電源部分工作電壓異常,要立即斷電,檢查焊接線和器件的焊接方向是否正確。確保電源正常后,再焊接電路其他部分,避免其他器件被高電壓損壞。如果焊接一個(gè)功能模塊后發(fā)現(xiàn)調(diào)試不正常時(shí)候,首先應(yīng)該先檢查原理圖連線是否正確,在查看原理圖和焊接的板子是否一致。如果都是正確的,就應(yīng)該確定原理圖和芯片手冊的引腳對應(yīng)是否正確,檢查是否有漏焊、虛焊、引腳短路的現(xiàn)象出現(xiàn)。可以利用示波器芯片引腳的電平進(jìn)行測試,找到問題所在。有時(shí)我們可以將現(xiàn)在IO口轉(zhuǎn)到別的上去看是否是IO口出現(xiàn)問題引起的。在焊接時(shí)候最好一起焊接兩個(gè)板子進(jìn)行對比,排除因?yàn)槿藶楹附釉蛟斐慑e(cuò)誤發(fā)生。軟件和硬件的調(diào)試時(shí)相互配合的,如果遇到問題時(shí)候不一定都是硬件出現(xiàn)問題造成系統(tǒng)錯(cuò)誤。

軟件調(diào)試首先根據(jù)系統(tǒng)的整體要求繪制出系統(tǒng)的程序流程圖,根據(jù)程序流程圖里的相關(guān)要求,利用KEIL編譯軟件利用C語言對系統(tǒng)硬件進(jìn)行驅(qū)動(dòng)首先要配置單片機(jī)各個(gè)寄存器的狀態(tài),配置相關(guān)的IO口,調(diào)試過程中盡量使用LED燈來觀察程序的運(yùn)行狀態(tài)以判斷單片機(jī)IO口是否已根據(jù)程序的要求輸出相應(yīng)的電平?刂评^電器驅(qū)動(dòng)時(shí)候要注意電路的控制,以避免外部的輸入干擾對單片機(jī)系統(tǒng)造成影響,同時(shí)系統(tǒng)運(yùn)行過程中要加如看門狗,當(dāng)程序跑飛的時(shí)候及時(shí)復(fù)位單片機(jī),是系統(tǒng)能夠正常的運(yùn)行,在按鍵檢測電路的時(shí)候要注意對按鍵的抖動(dòng)造成程序誤操作。










結(jié)  論

通過這次設(shè)計(jì),我對所學(xué)的專業(yè)知識有了更深的理解,尤其是單片機(jī)方面。在51單片機(jī)方面做了很多的資料方面的學(xué)習(xí),掌握了單片機(jī)的基本工作的方法,以及焊接調(diào)試的流程。在設(shè)計(jì)過程中,查閱了大量的中外文資料,解決了不少難題,使我在分析問題解決問題的能力方面有了提升,增強(qiáng)了對學(xué)習(xí)的信心,并對電子專業(yè)產(chǎn)生了濃厚的興趣,相信這對我以后的工作和學(xué)習(xí)有重要的幫助。

本次設(shè)計(jì)初步實(shí)現(xiàn)了51單片機(jī)控制十字路口交通等,實(shí)現(xiàn)行人與車流的分流的目的。運(yùn)用了傳統(tǒng)的8位MCU、性能全面、成本造價(jià)低、能夠在室溫下安全可靠運(yùn)行,運(yùn)行電子制圖軟件和KEIL編程軟件,同時(shí)完成系統(tǒng)原理圖和MCU的底層驅(qū)動(dòng)代碼的編寫。能夠在設(shè)計(jì)過程中完成對電子專業(yè)的各個(gè)節(jié)本技能的強(qiáng)化和所有應(yīng)用課程的實(shí)踐應(yīng)用,其中包括單片機(jī)課程、數(shù)字電路、模擬電路、單片機(jī)c語言編程的各個(gè)專業(yè)課程的綜合運(yùn)用,在設(shè)計(jì)完成時(shí)我對自己本專業(yè)的四年所有科目進(jìn)行的簡單并全面的運(yùn)行。

系統(tǒng)由于能力和精力的限制,整個(gè)系統(tǒng)還存在很多的不足,還可以實(shí)現(xiàn)更多的擴(kuò)展,比如可以加入一些測量道路經(jīng)過車輛數(shù)量的傳感器,根據(jù)傳感器的數(shù)據(jù)可以更加智能的實(shí)現(xiàn)對紅綠燈時(shí)間的設(shè)置,使道路的利用率更高;還可以將單片機(jī)通過有線或無線的形式與交通指揮中心實(shí)現(xiàn)通信,使指揮中心可以根據(jù)實(shí)際交通情況實(shí)時(shí)的調(diào)整紅綠燈的時(shí)間參數(shù)等等,我會(huì)在以后的學(xué)習(xí)中繼續(xù)完善知識體系,盡可能的改善不足。隨著單片機(jī)技術(shù)的進(jìn)一步發(fā)展,這些問題都將被繼續(xù)研究解決。


致  謝

經(jīng)過幾個(gè)月資料的查找和對本畢業(yè)設(shè)計(jì)相關(guān)知識的學(xué)習(xí),已經(jīng)完成整個(gè)系統(tǒng)的設(shè)計(jì),在這個(gè)畢業(yè)設(shè)計(jì)過程中曝露出我許多的問題,由于對有些專業(yè)知識的了解不夠深入,設(shè)計(jì)有些方面還是不夠完善。在老師的幫助下,解決了遇到的很多設(shè)計(jì)難題,才使得畢業(yè)設(shè)計(jì)能夠順利的完成。再次對我的指導(dǎo)教師表示深深的感謝,老師在忙碌的工作中,對我畢業(yè)設(shè)計(jì)的進(jìn)行耐心的指導(dǎo),從設(shè)計(jì)最初我查找資料的時(shí)候,給我很大幫助讓我在眾多的資料中梳理出需要的知識的重點(diǎn),在畢業(yè)設(shè)計(jì)的中期我提出系統(tǒng)的設(shè)計(jì)方案和解決方法,老師對我的設(shè)計(jì)方案進(jìn)行了評估,指導(dǎo)我方案中出現(xiàn)的我的問題,并提出了寶貴的經(jīng)驗(yàn)。在畢業(yè)設(shè)計(jì)后期對我設(shè)計(jì)電路和程序進(jìn)行了指導(dǎo)。使我對單片機(jī)硬件電路和軟件程序有了更深入的了解。把我繁瑣的設(shè)計(jì)變得簡潔、系統(tǒng)功能更合理。深深感受到了張清蓉老師對整個(gè)系統(tǒng)全局統(tǒng)籌性很強(qiáng),使我也從中學(xué)到很多在課堂上學(xué)不到設(shè)計(jì)經(jīng)驗(yàn)。在此,對張老師的嚴(yán)謹(jǐn)?shù)闹螌W(xué)態(tài)度和對學(xué)生負(fù)責(zé)的態(tài)度表示深深欽佩。其次對和我一起做畢設(shè)的同學(xué)表示深深的感謝,當(dāng)我遇到問題時(shí)候,幫助我解決好多我能力之外的困難,如果沒有他們的幫助我能這么順利的完成我畢業(yè)設(shè)計(jì)。
最后感謝大學(xué)所有任課教師,他們在我在學(xué)校的四年里耐心的傳授我知識,對我的各個(gè)方面能力培養(yǎng)付出太多的艱辛工作。為我在以后的工作中更好的學(xué)習(xí)打下了堅(jiān)實(shí)的基礎(chǔ),同時(shí)感謝所有的同學(xué)們正式有你們鼓勵(lì)和支持,才讓我在做畢業(yè)設(shè)計(jì)這段時(shí)間不斷改掉缺點(diǎn),努力的把我的畢業(yè)設(shè)計(jì)認(rèn)真的完成。


單片機(jī)源程序如下:


  1. <font style="font-size: 12pt">#include <reg52.h>                 //調(diào)用單片機(jī)頭文件
  2. #define uchar unsigned char   //宏定義"uchar"代替"unsigned char"。
  3. #define u8 unsigned char   //宏定義"uchar"代替"unsigned char"。
  4. #define uint  unsigned int          //宏定義"uint"用來定義無符號整型數(shù)。

  5. //上下南北主干道
  6. //左右東西輔干道

  7. u8 code DisplayOther[]={
  8. 0xff,                 //0                空
  9. 0x7f,                 //1                "."
  10. 0xbf,                        //2                "-"
  11. 0xa7                        //3                c
  12. };

  13. //數(shù)碼管段選定義                                                0                        1                2                        3                4                        5                6                        7                8                        9                A                        b                C                        d                        E                F                -
  14. uchar code smg_du[17] = {
  15. 0xc0,                //0
  16. 0xf9,                //1
  17. 0xa4,                //2
  18. 0xb0,                //3
  19. 0x99,                //4
  20. 0x92,                //5
  21. 0x82,                //6
  22. 0xf8,                //7
  23. 0x80,                //8
  24. 0x90,                //9
  25. 0x88,                //A
  26. 0x83,                //b
  27. 0xc6,                //C
  28. 0xa1,                //d
  29. 0x86,                //E
  30. 0x8e                //F
  31. };               
  32. uchar dis_smg[8 ] = {0xc0,0xf5,0x8c,0x94,0xb1,0x92,0x82,0xf4};               
  33. uchar smg_i = 4;    //顯示數(shù)碼管的個(gè)位數(shù)

  34. //數(shù)碼管位選定義
  35. sbit smg_we1 = P2^0;            //東西數(shù)碼管2
  36. sbit smg_we2 = P2^1;                        //東西數(shù)碼管1
  37. sbit smg_we3 = P2^3;                        //南北數(shù)碼管2
  38. sbit smg_we4 = P2^2;                        //南北數(shù)碼管1


  39. char dx_s = 0;        //東西  南北 倒計(jì)時(shí)變量

  40. sbit nb_red    = P1^0;                //南北紅燈
  41. sbit nb_green  = P1^2;                //南北綠燈
  42. sbit nb_yellow = P1^1;                //南北黃燈        1

  43. sbit dx_red    = P1^3;            //東西紅燈
  44. sbit dx_green  = P1^5;                //東西綠燈1
  45. sbit dx_yellow = P1^4;                //東西黃燈1

  46. uchar flag_jtd_mode;  //交通燈的模式 根據(jù)時(shí)間
  47. bit flag_1s = 1;                //進(jìn)入南北方向切換的標(biāo)志位
  48. bit flag_500ms;
  49. bit flag_dx_nb;                 //東西南北模式
  50. uchar flag_5m_value;
  51. uchar i;
  52. uchar flag_alarm;        //模式
  53. //uchar dx_time = 30,nb_time = 20;   //東西、南北的時(shí)間
  54. uchar dx_time = 20,nb_time = 30;   //東西、南北的時(shí)間
  55. uchar flag_jdgz ;     //交通管制

  56. /********************************************************************
  57. * 名稱 : u8 ChangeFor(u8 dat)
  58. * 功能 : 交換一個(gè)字節(jié)位的位置,用于數(shù)碼管顯示
  59. * 輸入 : 需要改變的數(shù)
  60. * 輸出 : 改變后的數(shù)
  61. ***********************************************************************/
  62. #define LED_a                6        //數(shù)碼管段選的a段接在段選IO口的第0位
  63. #define LED_b                5
  64. #define LED_c                0
  65. #define LED_d                2
  66. #define LED_e                1
  67. #define LED_f                4
  68. #define LED_g                3
  69. #define LED_dp        7

  70. u8 ChangeFor(u8 dat)
  71. {
  72.         u8 temp=0;
  73.         if(dat&0x01)                //判斷數(shù)據(jù)的第一位是否為1
  74.                 temp|=0x01<<LED_a;//如果為1,放到控制數(shù)碼管a段的位置
  75.         if(dat&0x02)
  76.                 temp|=0x01<<LED_b;
  77.         if(dat&0x04)
  78.                 temp|=0x01<<LED_c;
  79.         if(dat&0x08)
  80.                 temp|=0x01<<LED_d;
  81.         if(dat&0x10)
  82.                 temp|=0x01<<LED_e;
  83.         if(dat&0x20)
  84.                 temp|=0x01<<LED_f;
  85.         if(dat&0x40)
  86.                 temp|=0x01<<LED_g;
  87.         if(dat&0x80)
  88.                 temp|=0x01<<LED_dp;
  89.         return temp;
  90. }

  91. /***********************數(shù)碼位選函數(shù)*****************************/
  92. //i:        0,東西數(shù)碼管2
  93. //                1,東西數(shù)碼管1
  94. //                2,南北數(shù)碼管2
  95. //                3,南北數(shù)碼管1
  96. void smg_we_switch(uchar i)
  97. {
  98.         switch(i)
  99.         {
  100.                 case 0: smg_we1 = 0;  smg_we2 = 1; smg_we3 = 1;  smg_we4 = 1; break;
  101.                 case 1: smg_we1 = 1;  smg_we2 = 0; smg_we3 = 1;  smg_we4 = 1; break;
  102.                 case 2: smg_we1 = 1;  smg_we2 = 1; smg_we3 = 0;  smg_we4 = 1; break;
  103.                 case 3: smg_we1 = 1;  smg_we2 = 1; smg_we3 = 1;  smg_we4 = 0; break;
  104.         }        
  105. }


  106. /********************************************************************
  107. * 名稱 : delay_1ms()
  108. * 功能 : 延時(shí)1ms函數(shù)
  109. * 輸入 : q
  110. * 輸出 : 無
  111. ***********************************************************************/
  112. void delay_1ms(uint q)
  113. {
  114.         uint i,j;
  115.         for(i=0;i<q;i++)
  116.                 for(j=0;j<110;j++);
  117. }


  118. /********************************************************************
  119. * 名稱 : display()
  120. * 功能 : 數(shù)碼管顯示
  121. * 輸入 : 無
  122. * 輸出 : 無
  123. ***********************************************************************/
  124. void DisplayScan()
  125. {
  126.         static uchar i;
  127. //        if(T_MS_SCAN>=3)
  128.         {
  129.                 {               
  130.                 P0 = 0xff;                  //消隱
  131.                         smg_we_switch(i);                                    //位選
  132.                 P0 =        ChangeFor(dis_smg[i]);                  //段選         
  133.                 delay_1ms(3);
  134.                 }
  135.                 i++;
  136.                 if(i>=4)
  137.                         i=0;
  138. //                T_MS_SCAN=0;
  139.         }
  140. }
  141. /*********************定時(shí)器0、定時(shí)器1初始化******************/
  142. void time0_init()         
  143. {
  144.         TMOD = 0x01;                    //設(shè)置定時(shí)器0為工作模式1 (16-bit)
  145.         TL0 = 15536;                    //給定時(shí)器低位賦初始值                65536-15536=50000us=50ms,即50ms一個(gè)中斷
  146.         TH0 = 15536 >> 8;               //給定時(shí)器高位賦初始值
  147.         TR0 = 1;                        //開啟定時(shí)器0
  148.         ET0 = 1;                        //允許定時(shí)器0中斷
  149.         EA = 1;                         //開啟全局中斷
  150. }

  151. /*********************交通燈處理函數(shù)*********************************/
  152. void jiaotongdeng_dis()
  153. {
  154.         if(flag_1s == 1)//如果切換標(biāo)志為1
  155.         {
  156.                 flag_1s = 0;        //清零標(biāo)志位
  157.                 if(dx_s == 0)
  158.                 {
  159.                         if(flag_dx_nb == 1)
  160.                                 dx_s = nb_time;          //南北時(shí)間
  161.                         else
  162.                                 dx_s = dx_time;          //東西時(shí)間
  163.                         flag_dx_nb = ~flag_dx_nb;                //切換南北時(shí)間
  164.                 }
  165.                 dx_s --;
  166.         }

  167. /***********************南北時(shí)間*********************************/
  168.                 if(flag_dx_nb == 0)  
  169.                 {
  170.                         if(dx_s > 3)
  171.                         {
  172.                                 dis_smg[0] = smg_du[dx_s % 10] ;
  173.                                 dis_smg[1] = smg_du[dx_s / 10] ;
  174.                                 dis_smg[2] = smg_du[(dx_s-3) % 10] ;
  175.                                 dis_smg[3] = smg_du[(dx_s-3) / 10] ;

  176.                                 dx_red    = 1;  //滅
  177.                                 dx_yellow = 1;        //滅
  178.                                 nb_green  =        1;        //滅
  179.                                 nb_yellow = 1;        //滅
  180.                                 dx_green  =        0;        //亮
  181.                                 nb_red    = 0;  //亮
  182.                                 flag_5m_value = 0;        
  183.                         }else if(dx_s <= 3)                 //當(dāng)小于3秒時(shí)  黃燈要閃了
  184.                         {
  185.                                 dis_smg[0] = smg_du[dx_s % 10] ;
  186.                                 dis_smg[1] = smg_du[dx_s / 10] ;
  187.                                 dis_smg[2] = smg_du[dx_s % 10] ;
  188.                                 dis_smg[3] = smg_du[dx_s / 10] ;

  189.                                 dx_red    = 1;    //滅
  190.                                 dx_green  =        1;          //滅
  191.                                 nb_green  =        1;          //滅
  192.                                 nb_yellow = 1;          //滅
  193.                                 nb_red    = 0;    //亮
  194.                                 if(flag_500ms == 0)
  195.                                 {
  196.                                         dx_yellow = 0;//亮        
  197.                                 }
  198.                                 else
  199.                                 {
  200.                                         dx_yellow = 1;//滅        
  201.                                 }
  202.                         }
  203.                 }
  204. /***********************東西時(shí)間*********************************/
  205.                 if(flag_dx_nb == 1)  
  206.                 {
  207.                         if(dx_s > 3)
  208.                         {
  209.                                 dis_smg[2] = smg_du[dx_s % 10] ;
  210.                                 dis_smg[3] = smg_du[dx_s / 10] ;
  211.                                 dis_smg[0] = smg_du[(dx_s-3) % 10] ;
  212.                                 dis_smg[1] = smg_du[(dx_s-3) / 10] ;

  213.                                 dx_red    = 0;     //亮
  214.                                 nb_green  =        0;           //亮
  215.                                 nb_yellow = 1;           //滅
  216.                                 dx_green  =        1;           //滅
  217.                                 dx_yellow = 1;           //滅
  218.                                 nb_red    = 1;     //滅
  219.                                 flag_5m_value = 0;        
  220.                         }else if(dx_s <= 3)                 //當(dāng)小于3秒時(shí)  黃燈要閃了
  221.                         {
  222.                                 dis_smg[0] = smg_du[dx_s % 10] ;
  223.                                 dis_smg[1] = smg_du[dx_s / 10] ;
  224.                                 dis_smg[2] = smg_du[dx_s % 10] ;
  225.                                 dis_smg[3] = smg_du[dx_s / 10] ;

  226.                                 dx_red    = 0;     //滅
  227.                                 dx_green  =        1;           //滅
  228.                                 dx_yellow = 1;           //滅
  229.                                 nb_red    = 1;     //滅
  230.                                 nb_green  =        1;           //滅
  231.                                 if(flag_500ms == 0)           //黃燈閃爍
  232.                                 {
  233.                                         nb_yellow = 0;        //亮        
  234.                                 }
  235.                                 else
  236.                                 {
  237.                                         nb_yellow = 1;        //滅        
  238.                                 }
  239.                         }
  240.         }                        
  241. }
  242. uchar key_can;         //按鍵值

  243. //按鍵
  244. sbit Key1=P1^6;                                 //設(shè)置鍵
  245. sbit Key2=P1^7;                                 //加按鍵
  246. sbit Key3=P3^2;                                 //減按鍵
  247. sbit Key4=P3^3;                                 //交通管制鍵
  248. //========================================================================
  249. // 函數(shù): u8 Key_Scan()
  250. // 應(yīng)用: temp=u8 Key_Scan();
  251. // 描述: 按鍵掃描并返回按下的鍵值
  252. // 參數(shù): NONE
  253. // 返回: 按下的鍵值
  254. // 版本: VER1.0
  255. // 日期: 2015-05-29
  256. // 備注: 該函數(shù)帶松手檢測,按下鍵返回一次鍵值后返回0,直至第二次按鍵按下
  257. //========================================================================
  258. u8 Key_Scan()
  259. {         
  260.         static u8 key_up=1;//按鍵按松開標(biāo)志
  261.         if(key_up&&(Key1==0||Key2==0||Key3==0||Key4==0))
  262.         {
  263.                 delay_1ms(10);//去抖動(dòng)
  264.                 key_up=0;
  265.                 if(Key1==0)                        return 1;
  266.                 else if(Key2==0)return 2;
  267.                 else if(Key3==0)return 3;
  268.                 else if(Key4==0)return 4;
  269.         }
  270.         else if(Key1==1&&Key2==1&&Key3==1&&Key4==1)
  271.                 key_up=1;            
  272.          return 0;// 無按鍵按下
  273. }


  274. uchar flag_s;
  275. uchar menu_1;//縱橫加減標(biāo)示


  276. /********************設(shè)置函數(shù)*****************/
  277. void key_with()
  278. {
  279.         if(key_can == 4)   //交通管制按鍵
  280.         {
  281.                 flag_jdgz ++;
  282.                 if(flag_jdgz > 5)
  283.                         flag_jdgz = 0;        
  284.                 if(flag_jdgz == 1)         //  全部亮紅燈
  285.                 {
  286.                         dx_red    = 0;  //亮
  287.                         nb_red    = 0;  //亮
  288.                         dx_green  =        1;        //滅
  289.                         dx_yellow = 1;        //滅
  290.                         nb_green  =        1;        //滅
  291.                         nb_yellow = 1;        //滅                        
  292.                 }
  293.                 if(flag_jdgz == 2)         //  東西綠燈  南北紅燈
  294.                 {
  295.                         dx_red    = 0;  //亮
  296.                         nb_green  =        0;        //亮
  297.                         dx_green  =        1;        //滅
  298.                         dx_yellow = 1;        //滅
  299.                         nb_red    = 1;  //滅
  300.                         nb_yellow = 1;        //滅                        
  301.                 }
  302.                 if(flag_jdgz == 3)         //  南北綠燈  東西紅燈
  303.                 {
  304.                         dx_green  =        0;        //亮
  305.                         nb_red    = 0;  //亮
  306.                         dx_red    = 1;  //滅
  307.                         dx_yellow = 1;        //滅
  308.                         nb_green  =        1;        //滅
  309.                         nb_yellow = 1;        //滅                        
  310.                 }
  311.                 if(flag_jdgz == 4)         //  南北綠燈  東西綠燈
  312.                 {
  313.                         dx_green  =        0;        //亮
  314.                         nb_green  =        0;        //亮
  315.                         dx_red    = 1;  //滅
  316.                         dx_yellow = 1;        //滅
  317.                         nb_red    = 1;  //滅
  318.                         nb_yellow = 1;        //滅                        
  319.                 }
  320.                 if(flag_jdgz == 5)         //  南北黃燈  東西黃燈
  321.                 {
  322.                         dx_red    = 1;  //滅
  323.                         dx_green  =        1;        //滅
  324.                         nb_red    = 1;  //滅
  325.                         nb_green  =        1;        //滅
  326.                         nb_yellow = 0;        //亮                        
  327.                         dx_yellow = 0;        //亮
  328.                 }
  329.         }
  330.         if(key_can == 1)          //設(shè)置鍵
  331.         {
  332.                 menu_1 ++;
  333.                 if(menu_1 >= 3)
  334.                 {
  335.                         menu_1  = 0;
  336.                 }
  337.         }

  338.         if(menu_1 == 1)           //設(shè)置東西的時(shí)間
  339.         {
  340.                 if(key_can == 2)
  341.                 {
  342.                         dx_time ++ ;                //加1
  343.                         if(dx_time > 99)        //時(shí)間最大值為99s
  344.                                 dx_time = 99;
  345.                 }
  346.                 if(key_can == 3)
  347.                 {
  348.                         dx_time -- ;                //減1
  349.                         if(dx_time <= 5)//時(shí)間最小值為5s
  350.                                 dx_time = 5;
  351.                 }
  352.                 dis_smg[0] = smg_du[(dx_time-1) % 10] ;        //顯示為A
  353.                 dis_smg[1] = smg_du[(dx_time-1) / 10] ;        //顯示為A
  354.                 dis_smg[2] = DisplayOther[2] ;                //顯示東西設(shè)置的時(shí)候
  355.                 dis_smg[3] = DisplayOther[2] ;        
  356.         }        
  357.         if(menu_1 == 2)           //設(shè)置南北的時(shí)間
  358.         {
  359.                 if(key_can == 2)
  360.                 {
  361.                         nb_time ++ ;                //加1
  362.                         if(nb_time > 99)//時(shí)間最大值為99s
  363.                                 nb_time = 99;
  364.                 }
  365.                 if(key_can == 3)
  366.                 {
  367.                         nb_time -- ;                //減1
  368. ……………………

  369. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
Keil代碼與Proteus仿真文檔等資料下載:

交通燈全套資料.7z (5.65 MB, 下載次數(shù): 782)




作者: tieq1952    時(shí)間: 2018-12-5 07:53
謝謝分享!!!
作者: 土豆子00    時(shí)間: 2019-4-7 10:11
樓主太棒啦,謝謝分享!
作者: juice123456    時(shí)間: 2019-4-9 08:36
感謝樓主分享
作者: 無線強(qiáng)大    時(shí)間: 2019-4-24 17:46
非常感謝啊,,我也會(huì)努力學(xué)習(xí)的
作者: cyf123    時(shí)間: 2019-5-13 22:52
謝謝分享
作者: 1250266916    時(shí)間: 2019-5-31 00:51
厲害了
作者: 摸魚師兄    時(shí)間: 2019-6-5 17:59
請問一下,有pcb封裝的文件嗎? 不要截圖的那種
作者: cczy    時(shí)間: 2019-6-5 21:16
感謝分享。。。
作者: cloudewey    時(shí)間: 2019-6-7 13:49
謝謝分享!
作者: fantasty_w    時(shí)間: 2019-6-14 14:09
課程設(shè)計(jì)很好的例子
作者: 呃呃呃呃    時(shí)間: 2019-6-28 09:12
感謝樓主分享
作者: system123    時(shí)間: 2019-10-5 17:21
樓主  為啥時(shí)間改不了啊?  我沒有改出來
作者: czx13    時(shí)間: 2019-10-15 13:45
  if(T_MS_SCAN>=3)這個(gè)里面沒有定義?
作者: lexbunre    時(shí)間: 2019-10-15 14:52
很有用
作者: lexbunre    時(shí)間: 2019-10-16 22:50
謝謝樓主分享
作者: 101558879    時(shí)間: 2019-10-30 15:48
非常詳細(xì),十分的感謝
作者: mark51wz    時(shí)間: 2019-12-1 17:37
讓人一目了然
作者: 2416086966    時(shí)間: 2019-12-23 10:09
感謝樓主分享!
作者: biggalelee    時(shí)間: 2019-12-23 11:01
感謝樓主的分享。。!
作者: 2416086966    時(shí)間: 2019-12-24 09:48
實(shí)物圖怎么連接 求回答!感謝!
作者: Manshow12138    時(shí)間: 2019-12-24 09:59
真棒,真的喜歡
作者: 69907    時(shí)間: 2019-12-28 21:39
好,有用
作者: 潘志豪    時(shí)間: 2020-1-1 17:42
正需要,非常感謝樓主
作者: 蘇荷很女    時(shí)間: 2020-1-4 19:37
謝謝分享
作者: xgasus    時(shí)間: 2020-2-27 22:57

感謝樓主的分享。。。
作者: 真的猛士    時(shí)間: 2021-12-22 10:04
樓主大大,想要PCB文件,急
作者: 320550248    時(shí)間: 2022-12-8 18:31
內(nèi)容齊全,真不錯(cuò)
作者: existence    時(shí)間: 2024-6-16 14:56
非常詳細(xì),十分的感謝
作者: kinglucifun    時(shí)間: 2024-6-16 17:32
很詳細(xì),必須贊一個(gè)
作者: huwanli    時(shí)間: 2024-12-5 08:58
內(nèi)容較詳細(xì),符合實(shí)際交通燈,主干道支干道倒計(jì)時(shí)不一樣,proteus7.8可以使用
作者: gemxie    時(shí)間: 2025-1-15 11:13

樓主太棒啦,謝謝分享!




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1