交通燈控制設(shè)計(jì)
????每個(gè)城市的交通就猶如人體的血管蹂空,人類生命的持續(xù)需要心臟為血液提供動力,依靠血液來在人體內(nèi)完成各類物質(zhì)交換果录,完成新陳代謝上枕,保持一個(gè)健康的體魄,而城市的交通于整個(gè)城市的重要性不亞于血液于人體弱恒,城市需要依靠一個(gè)可以正常運(yùn)轉(zhuǎn)的交通系統(tǒng)來推動交流與發(fā)展辨萍。
????交通系統(tǒng)也可以稱作為交通網(wǎng),由各個(gè)部分的道路和相關(guān)設(shè)施組成返弹,現(xiàn)如今的交通網(wǎng)是發(fā)達(dá)但不完善的锈玉,雖然隨著智能化的覆蓋面越來越廣,幾年后就可能不再需要交通燈义起,但交通燈依然是城市規(guī)劃者引導(dǎo)車流人流最實(shí)惠又最穩(wěn)定的工具拉背。步入下一個(gè)時(shí)代前,需要工程師先參透舊時(shí)代默终,有故方能新是經(jīng)過歷史的證明的椅棺,所以下一個(gè)工具的誕生需要對交通燈的工作原理進(jìn)行剖析及穩(wěn)定實(shí)現(xiàn)犁罩,此次設(shè)計(jì)的目的更多的是在于對舊事物的思考,并引出新事物的設(shè)想
????我國交通信號燈分為3種:紅燈代表暫停两疚;黃燈代表緩行床估;綠燈代表通行。本設(shè)計(jì)通過采用電子元件對交通燈控制電路進(jìn)行設(shè)計(jì),實(shí)現(xiàn)十字路口交通管理的自動化鬼雀。
????針對本次交通燈的制作顷窒,設(shè)計(jì)者依次使用Altium designer 2016完成原理圖的設(shè)計(jì),PCB的手動布線源哩,再使用相關(guān)設(shè)備制作電路板,最后依靠keil軟件寫入C語言程序以達(dá)到硬件和軟件的相互兼容的效果鸦做。
????單片機(jī)又稱單片微控制器,它不是完成某一個(gè)邏輯功能的芯片,而是把一個(gè)計(jì)算機(jī)系統(tǒng)集成到一個(gè)芯片上励烦,相當(dāng)于一個(gè)微型的計(jì)算機(jī),和計(jì)算機(jī)相比泼诱,單片機(jī)只缺少了I/O設(shè)備坛掠。概括的講:一塊芯片就成了一臺計(jì)算機(jī)。它的體積小治筒、質(zhì)量輕屉栓、價(jià)格便宜、控制功能強(qiáng)耸袜、使用方便友多、容易產(chǎn)品化,為學(xué)習(xí)堤框、應(yīng)用和開發(fā)提供了便利條件域滥。
????程序設(shè)計(jì)需要編程語言,常用的編程語言有:機(jī)器語言蜈抓、匯編語言和高級語言启绰。
????機(jī)器語言是CPU硬件唯一能夠直接識別的語言,在設(shè)計(jì)CPU時(shí)就已經(jīng)確定了其代碼的含義沟使。要執(zhí)行任何操作委可,都必須轉(zhuǎn)換為相應(yīng)的機(jī)器語言,由CPU識別腊嗡、控制執(zhí)行着倾。機(jī)器語言必須為二進(jìn)制代碼,不便于記憶叽唱、使用和直接編寫程序屈呕。
????匯編語言使用人們便于記憶的符號來描述與之相應(yīng)的機(jī)器語言,這些符號稱為助記符棺亭。用助記符表示的指令稱為匯編語言指令虎眨,用助記符編寫出來的程序稱為匯編語言程序。用匯編語言編寫的程序運(yùn)行速度快、占用內(nèi)存單元少嗽桩、效率高岳守,但程序設(shè)計(jì)者必須熟悉單片機(jī)內(nèi)部資源等硬件設(shè)施。
????目前碌冶,社會上廣泛使用的是高級語言(如C語言)湿痢。單片機(jī)不能識別高級語言的程序,因此需要用編譯器對高級語言程序翻譯成機(jī)器語言程序后再寫入單片機(jī)扑庞。作為一種更接近人們習(xí)慣的程序設(shè)計(jì)語言譬重,它使用人們熟悉的文字舶得、符號及數(shù)學(xué)表達(dá)式來編寫程序在验,因此程序的編寫和操作都十分方便,本次交通燈控制程序也選用C語言强品。
2.1.1系統(tǒng)功能
(1)在LED數(shù)碼管上顯示倒計(jì)時(shí)塔嬉,單位為秒。
(2)采用LED模擬信號燈租悄,信號燈分東西谨究、南北二組,分別有“紅”“黃”“綠”三種顏色泣棋。分別設(shè)定有南北通行狀態(tài)胶哲,東西通行狀態(tài),夜間黃燈閃爍狀態(tài)外傅。
(3)采用矩陣鍵盤控制狀態(tài)切換纪吮,同時(shí)實(shí)現(xiàn)按0——9的數(shù)字鍵能夠修改南北、東西紅綠黃燈亮燈的時(shí)間萎胰。分別設(shè)置一個(gè)紅碾盟、黃、綠燈按鈕設(shè)置鍵技竟,選擇一個(gè)方向設(shè)置冰肴,另外一個(gè)方向通過計(jì)算可知。設(shè)置一個(gè)數(shù)字輸入確認(rèn)鍵榔组。
2.1.2 硬件設(shè)計(jì)
(1)CPU為89C52單片機(jī)熙尉;
(2)鍵盤為4×4行列式鍵盤,接入單片機(jī)的P1口搓扯,用于輸入相關(guān)的控制指令检痰;
(3)兩個(gè)3位LED數(shù)碼管,顯示相應(yīng)通行方向的倒計(jì)時(shí)時(shí)間锨推;
2.1.3 軟件設(shè)計(jì)
??? (1)控制交通燈程序铅歼。軟件需要使交通燈在不同模式下實(shí)現(xiàn)不同的亮閃模式公壤,且需要綠燈、紅燈與黃燈的相互配合椎椰,實(shí)現(xiàn)在同一時(shí)序下嚴(yán)格按照圖2.1的要求實(shí)現(xiàn)功能厦幅;
??? (2)LED數(shù)碼管顯示程序。需要在軟件的設(shè)計(jì)中實(shí)現(xiàn)段選慨飘、位選确憨,同時(shí)運(yùn)用動態(tài)顯示的方式,完成倒計(jì)時(shí)及計(jì)數(shù)輸入顯示的功能瓤的;
??? (3)鍵盤管理程序(包括鍵掃描休弃、鍵處理程序)。鍵盤為4 * 4矩陣鍵盤堤瘤,不同于獨(dú)立按鍵玫芦,需要在軟件的編寫過程中進(jìn)行循環(huán),以實(shí)現(xiàn)不斷掃描鍵盤本辐,檢測是否輸入及其鍵值,一來實(shí)現(xiàn)各種功能的選擇医增,二來完成計(jì)數(shù)值的輸入慎皱。
????鑒于實(shí)驗(yàn)室提供的元器件,設(shè)計(jì)者選擇了STC89C52叶骨,在方案設(shè)計(jì)中選擇P0口為三位數(shù)碼管的段選端口茫多,P1口為位選口,P2口為矩陣鍵盤忽刽,兩個(gè)接數(shù)碼管的I/O口都連接了74LS573來進(jìn)行鎖存天揖,P3則用于交通燈信號的輸出,同時(shí)采用了USB供電跪帝,且為上電復(fù)位今膊,同時(shí)采用12M晶振來構(gòu)成51單片機(jī)的最小系統(tǒng)板。
2.3.1所用元器件
STC89C52芯片? ????1
74LS573? ? ? ? ? ? ?????2
12MHz晶振? ? ? ? ?????1
30PF電容????????????????2
10uf/50V電解電容????1
10kΩ電阻????????????????1
鍵盤????????????????????????1
鍵盤插針????????????????1
按鍵????????????????????????1
1kΩ排阻????????????????2
1kΩ電阻????????????????6
LED燈????????????????????6
USB口????????????????????1
3位共陰極數(shù)碼管????2
?
2.3.2硬件詳細(xì)介紹
(1)STC89C52
????STC89C51RC/RD+系列單片機(jī)(包括STC89C52RC)是宏晶科技推出的新一代超強(qiáng)抗干擾伞剑、高速斑唬、低功耗的單片機(jī),基于Intel 標(biāo)準(zhǔn)的8052黎泣,指令代碼完全兼容傳統(tǒng)的8051 系列單片機(jī)恕刘,12 時(shí)鐘/機(jī)器周期和6 時(shí)鐘/機(jī)器周期可任意選擇。工作電壓:5.5V- 3.4V(5V 單片機(jī)) 抒倚。工作頻率范圍:0 – 40 MHz,相當(dāng)于普通的8051 的0~80 Mhz褐着,實(shí)際工作頻率可達(dá)到48MHz。用戶應(yīng)用程序空間4K托呕、8K含蓉、13K频敛、16K、20K谴餐、32K姻政、64K 字節(jié)。片上集成1280 字節(jié)岂嗓、512 字節(jié)RAM汁展。通用I/O(32個(gè)),復(fù)位后為:P0厌殉、P1食绿、P2、P3是準(zhǔn)雙向口公罕、弱上拉(普通8051 傳統(tǒng)I/O 口)器紧,P0 口是開漏輸出,作為總線拓展用時(shí)楼眷,不用加上拉電阻铲汪,作為I/O 口用時(shí),需要加上拉電阻罐柳。
(2)單片機(jī)供電電路
????89C52為5V單片機(jī)掌腰,采用USB供電是最常用的方式,不管是連接電腦或移動電源都可以達(dá)到相應(yīng)的適配效果张吉。
(3)振蕩電路
????根據(jù)89C52單片機(jī)的相關(guān)設(shè)定齿梁,采用了12MHz晶振,它起到的作用是為單片機(jī)提供基準(zhǔn)的時(shí)針信號肮蛹,單片機(jī)內(nèi)部所有的工作都是以這個(gè)時(shí)鐘信號為步調(diào)基準(zhǔn)來進(jìn)行工作的勺择。除了晶振以外,還需要兩個(gè)30pF的電容伦忠,電容的作用是幫助晶振起振省核,并維持振蕩信號的穩(wěn)定。單片機(jī)晶體振蕩器提供的時(shí)鐘頻率越高缓苛,單片機(jī)運(yùn)行的速度就越快芳撒。
(4)復(fù)位電路
????根據(jù)實(shí)驗(yàn)要求,要實(shí)現(xiàn)上電復(fù)位未桥,且對于89C52而言笔刹,需要實(shí)現(xiàn)上電時(shí)為RST引腳提供一個(gè)高電平以實(shí)現(xiàn)復(fù)位。?
(5)3位數(shù)碼管電路
????數(shù)碼管分為共陰極數(shù)碼管和共陽極數(shù)碼管兩種冬耿。共陰極數(shù)碼管所有LED燈的陰極連在一起舌菜,而共陽極數(shù)碼管則是所有LED燈的所有陽極連接在一起。在實(shí)驗(yàn)中亦镶,由于實(shí)驗(yàn)室提供的元器件選擇了圖2.7所示的共陰極數(shù)碼管日月,選用時(shí)袱瓮,拉低選用位,拉高選用段爱咬,且選擇74LS573作為驅(qū)動尺借,74LS573 的八個(gè)鎖存器都是透明的D 型鎖存器,當(dāng)使能LE引腳為高時(shí)精拟,(O)輸出將隨數(shù)據(jù)(D)輸入而變燎斩。當(dāng)使能為低時(shí),輸出將鎖存在已建立的數(shù)據(jù)電平上蜂绎。輸出控制不影響鎖存器的內(nèi)部工作栅表,即老數(shù)據(jù)可以保持,甚至當(dāng)輸出被關(guān)閉時(shí)师枣,新的數(shù)據(jù)也可以置入怪瓶。實(shí)驗(yàn)中總共6位數(shù)碼管,為了在節(jié)省I/O口的條件下践美,使電流穩(wěn)定輸出洗贰,必須在位選端和段選端都接入74LS573作為驅(qū)動。
(6)鍵盤電路
????為了提高單片機(jī)系統(tǒng)中I/O口的利用率矩陣鍵盤采用四條I/O線作為行線陨倡,四條I/O線作為列組成鍵盤哆姻,在行和列的每個(gè)交叉點(diǎn)上設(shè)置一個(gè)按鍵,采用4 * 4鍵盤共16個(gè)鍵玫膀。
????在一個(gè)循環(huán)中先掃描第一行,即將第一行輸出0電平爹脾,然后讀入列值帖旨,哪一列出現(xiàn)0電平,就說明該列與第一行跨接的按鍵被按下灵妨,若讀入的列值全為1解阅,則說明與第一行跨接的按鍵沒有被按下,然后按以上步驟逐行掃描泌霍,直到找到被按下的按鍵货抄。
????同時(shí)需要在每一條列線都接上拉電阻,這是為了給高阻抗輸入提供一個(gè)穩(wěn)定的高電平朱转,因?yàn)橛行﹩纹瑱C(jī)的I/O口作為輸出時(shí)只能提供高阻抗輸出與低電平輸出蟹地,被稱作“準(zhǔn)三態(tài)門”,在這些“準(zhǔn)三態(tài)門”口線作為鍵盤行線的掃描時(shí)藤为,提供所謂的“高電平”實(shí)際上驅(qū)動能力是很弱的怪与,列線在讀取時(shí),可能會發(fā)生誤判缅疟,所以必須要在讀取時(shí)加上拉電阻分别,將高阻態(tài)轉(zhuǎn)換為穩(wěn)定的高電平遍愿,才能保證讀取的正確
(7)紅綠燈電路
??? 在實(shí)驗(yàn)中采用了南北方向紅綠黃燈和東西方向紅綠黃燈兩組LED,同時(shí)為了保護(hù)LED接入1kΩ電阻耘斩。
??? 本次實(shí)驗(yàn)的原理圖繪制采用了Altium Designer 2016軟件,第一步建立一個(gè)工程括授,在其中建一個(gè)原理圖文件原理圖庫文件坞笙。根據(jù)實(shí)驗(yàn)要求,將所需的元件庫復(fù)制到原理圖庫文件刽脖,等待調(diào)用羞海,由于元件庫的收集過程中不夠全面,還需要自己繪制元器件曲管,同時(shí)繪制相應(yīng)元件的封裝庫却邓。確定具體的電路后,將相應(yīng)的元件放置到原理圖中院水,在不同的硬件電路之間采用網(wǎng)絡(luò)端口腊徙,使得原理圖看起來更加簡潔。
????考慮到P0口和鍵盤需要上拉電阻檬某,選用8位的排阻連接以作為上拉電阻撬腾;LED用P3口控制;數(shù)碼管驅(qū)動電路中恢恼,74LS573的LE端接+5V民傻。
????新建PCB文件,導(dǎo)入原理圖场斑,布置元器件的位置后漓踢,進(jìn)行手動布線,要求電源線和地線寬度至少在50mil到100mil之間漏隐,而一般的線寬度為25mil喧半,線與線之間、線與孔之間間距為20mil至30mil青责,不能再IC腳之間過線挺据,防止短路。一般的IC焊盤大小為80×80mil脖隶,電源管腳的焊盤應(yīng)盡量大一些扁耐,鍵盤的焊盤應(yīng)為80×100mil,因?yàn)閁SB口固定位置的兩個(gè)引腳比較大浩村,所以固定位置的兩個(gè)焊盤要設(shè)置為5×5mm做葵。之后在PCB板空的位置進(jìn)行覆銅,并設(shè)置覆銅與線和焊盤的距離至少50mil心墅。
????腐蝕電路板前要先將PCB文件打印在轉(zhuǎn)印紙上酿矢,用鉆孔機(jī)在銅板的一角鉆孔榨乎,后將銅板和打印好的紙放入環(huán)保型多功能制板系統(tǒng)影印,完成后取出瘫筐,在剛剛打好的孔間穿上繩子蜜暑,浸泡于用于顯影的溶液幾分鐘,之后用清水清洗策肝,再懸掛于腐蝕液上肛捍,浸泡一段時(shí)間后取出。
??? 將元器件按照原理圖焊接在PCB板后使用萬用表對每一段銅線進(jìn)行檢測之众,以排除不必要的麻煩拙毫。???
?
3.4.1 主要程序結(jié)構(gòu)分析
??? 在程序設(shè)計(jì)中要求實(shí)現(xiàn)交通燈功能,在主程序中需要設(shè)置開啟鍵棺禾,為了實(shí)現(xiàn)按鍵功能的更加人性化缀蹄,主程序中設(shè)置了兩個(gè)開啟鍵,分別是白天模式開啟鍵和夜晚模式開啟鍵膘婶,按下相應(yīng)開啟鍵即可進(jìn)入相應(yīng)模式缺前,進(jìn)入到各個(gè)模式的子程序中,期間只要按下停止鍵即可重新返回主函數(shù)悬襟。
??? 而在進(jìn)入白天模式后衅码,鍵盤掃描即進(jìn)入了計(jì)數(shù)值設(shè)置模式階段,期間按下各個(gè)方向通行時(shí)間的設(shè)置鍵即可輸入相關(guān)計(jì)數(shù)值改變倒計(jì)時(shí)時(shí)間脊岳,輸入期間還可在第一個(gè)3位數(shù)碼管上顯示相關(guān)數(shù)值逝段,直至按下數(shù)值確認(rèn)鍵,結(jié)束輸入的同時(shí)返回白天模式割捅,進(jìn)行新一輪的倒計(jì)時(shí)惹恃,同時(shí)完成新一輪的時(shí)序。
(1)鍵盤掃描程序
????在鍵盤掃描子函數(shù)前棺牧,采用while()循環(huán),以實(shí)現(xiàn)對程序的不間斷運(yùn)行朗儒,讓矩陣按鍵的一行輸出低電平艘刚,其它三行輸出高電平林螃,判斷當(dāng)前所有列的狀態(tài),下次中斷時(shí)再讓下一行輸出低電平,其它三行輸出高電平瞬项,再次判斷所有列,通過快速的中斷不停的循環(huán)進(jìn)行判斷望忆,最終確定哪個(gè)按鍵按下了鳄炉,同時(shí)將按鍵的鍵值制作為數(shù)組,根據(jù)行值和列值判斷鍵值烟勋,以輸出Statu值以及Value值以用于各個(gè)程序规求。
????程序中首先對所有的列輸入做了掃描筐付、消抖,然后才切換到了下一次的行輸出阻肿,也就是說中斷每次掃描的實(shí)際是上一次輸出選擇的那行按鍵瓦戚,這樣做是因?yàn)槿魏涡盘枏妮敵龅椒€(wěn)定都需要一個(gè)時(shí)間,有時(shí)它足夠快而有時(shí)卻不夠快丛塌,這里的輸入輸出順序的顛倒就是為了讓輸出信號有足夠的時(shí)間來穩(wěn)定较解,并有足夠的時(shí)間來完成它對輸入的影響
(2)定時(shí)器T0中斷程序
????定時(shí)器 T0中斷程序的主要作用是完成倒計(jì)時(shí)計(jì)數(shù),同時(shí)控制等待時(shí)間中黃燈閃爍功能赴邻。定時(shí)器采用工作模式1印衔,即16位定時(shí)器。通過給定時(shí)器0賦初值的方式可以讓定時(shí)器每隔50ms進(jìn)行一次中斷姥敛,循環(huán)20次完成1S的倒計(jì)時(shí)奸焙,同時(shí)每一次中斷都會判斷一次交通燈的狀態(tài),當(dāng)時(shí)間到達(dá)黃燈等待階段時(shí)徒溪,程序?qū)?zhí)行每半秒對黃燈控制口取反操作忿偷,實(shí)現(xiàn)黃燈閃爍功能。
(3)定時(shí)器T1中斷程序
????定時(shí)器T1中斷程序主要的作用是夜晚模式模式黃燈閃爍功能臊泌。采用的定時(shí)器T1初值與T0相同鲤桥,50ms進(jìn)行一次中斷,在中斷中對黃燈所在I/O口取反渠概,完成黃燈閃爍功能茶凳。在開TO的情況下,另外開啟T1對黃燈實(shí)現(xiàn)閃爍功能播揪,主要是為了排除兩個(gè)模式下黃燈閃爍的相互作用贮喧,充分利用單片機(jī)的閑置資源,同時(shí)讓不同模式下的黃燈閃爍時(shí)間都獨(dú)立可調(diào)猪狈,分離兩種模式箱沦,完全排除聯(lián)系以實(shí)現(xiàn)完全的模塊化。
?
#include
?
//--定義使用的IO口--//
#defineGPIO_DIG?? P0?????????? //段選
#defineGPIO_PLACE P2????????? //位選
#defineGPIO_KEY P1? ?????????? //矩陣鍵盤
#defineGPIO_TRAFFIC P3
?
sbitRED11?? = P3^2;?????????????? //東西方向
sbitYELLOW11= P3^3;
sbitGREEN11 = P3^4;
?
sbitRED01?? = P3^5;?????????????? //南北方向
sbitYELLOW01= P3^6;
sbitGREEN01 = P3^7;
?
//--定義全局變量--//
unsignedchar code DIG_PLACE[6] = {
0x7f,0xbf,0xdf,0xfb,0xf7,0xef};?????????????????????? ? //位選控制??
unsignedchar code DIG_CODE[17] = {
0xeb,0x88,0xd3,0xda,0xb8,0x7a,0x7b,0xc8,
0xfb,0xfa,0x77,0x7c,0x39,0x5e,0x79,0x71};
//0雇庙、1谓形、2、3疆前、4寒跳、5、6竹椒、7童太、8、9、A书释、b翘贮、C、d征冷、E择膝、F的顯示碼
unsignedchar DisplayData[6];???? //用來存放要顯示的8位數(shù)的值
unsigned
char Time,Time1,Time2,Time3,Second;//存放定時(shí)時(shí)間
unsignedchar KeyState;???? ??????? //記錄按鍵的狀態(tài),0沒有检激,1有
unsignedchar KeyValue;??????//用來存放讀取到的鍵值
unsignedchar KeyNum;????????????????????????? //用來存放輸入的鍵值
unsignedchar NS_In;?????????????????????? //南北通行時(shí)間
unsignedchar Y_In;??????????????????????????????? //黃燈時(shí)間
unsignedchar EW_In;?????????????? ? ?//東西通行時(shí)間
?
//--聲明全局函數(shù)--//
voidTimer0Cofig(void);???? ???????????????????????? ??//定時(shí)器0
voidTimer1Cofig(void);???? ???????????????????????? ??//定時(shí)器1
voidDelay10ms(unsigned int c);? ?????????? ??//延時(shí)10ms
voidDigDisplay(unsigned int n);???????????????????? ? //動態(tài)顯示函數(shù)
voidSETMODE(unsigned char keyValue);???????????? ? //設(shè)置計(jì)數(shù)值函數(shù)
voidDayLight(void);????????????????????????????????????? ? ???//白天模式
voidNightLight(void);??????????????????????????????????? ? //夜晚模式
unsignedchar KeyDown(void);??????????????? ? //檢測按鍵函數(shù)
unsignedchar KeyInput(void);??????????????? ? //數(shù)值輸入函數(shù)
?
/*********************************************************
*函 數(shù) 名???????? : main
*函數(shù)功能????????? ?? :主函數(shù)
*輸??? 入???????? : KeyValue
*輸??? 出???????? :無
*********************************************************/
voidmain(void)
{?????
?????? NS_In = 120;
?????? EW_In = 80;
?????? Y_In?= 6;????????????????????????????? //初始時(shí)序
?????? Time = 0;?????????????
?????? Time1 = 0;
?????? Second = 1;?????????????????????????????? ??//初始化計(jì)數(shù)值
?
?????? while(1)
?????? {
????????????? KeyDown();? ??????????????????? ???//執(zhí)行按鍵檢測函數(shù)
????????????? switch(KeyValue)
????????????? {
???????????????????? case 10:
??????????????????????????? Timer0Cofig();? ?//開定時(shí)器0
??????????????????????????? DayLight();????????? ??//調(diào)用白天模式
??????????????????????????? KeyValue = 17;
??????????????????????????? break;
???????????????????? case 11:
??????????????????????????? Timer1Cofig();? ?//開定時(shí)器1
??????????????????????????? NightLight(); ?? //調(diào)用夜晚模式
??????????????????????????? KeyValue = 17;
??????????????????????????? break;
???????????????????? default: break;
????????????? }
?????? }
}
?
/*********************************************************
*函 數(shù) 名???????? :中斷開關(guān)
*函數(shù)功能????????? ?? :打開定時(shí)器T0和T1
*輸??? 入???????? :無
*輸??? 出???????? :無
*********************************************************/
??????
voidTimer0Cofig(void)
{
?????? TMOD = 0x01;????
??? TH0?= 0x3C;?????
??? TL0?= 0xB0; //50ms
??? EA??= 1;???? ????
??? ET0?= 1;???????????
??? TR0?= 1;??????????? ????
}
?
voidTimer1Cofig(void)
{
?????? TMOD = 0x10;????
??? TH1?= 0x3C;?????
??? TL1?= 0xB0; //50ms
?????? EA = 1;
?????? ET1 = 1;
?????? TR1 = 1;
}
?
/*********************************************************
*函 數(shù) 名???????? :中斷0
*函數(shù)功能????????? ?? :定時(shí)器T0中斷函數(shù)
*輸??? 入???????? :無
*輸??? 出???????? : Second
*********************************************************/
?????? ??
voidTimer0() interrupt 1
{
?????? TH0 = 0x3C; ????????????????????????? //設(shè)置初始值
?????? TL0 = 0xB0;
?????? Time++;
?????? if(Time == 20)
?????? {
????????????? Second ++;
????????????? Time = 0;
?????? }??????????????????????????????????????????????? ???? //秒數(shù)計(jì)時(shí)疊加
??????
?????? if((Second < (NS_In + Y_In+1))&&(Second > (NS_In)))
?????? {
????????????? Time2++;
?????????????
????????????? if(Time2 == 10)
????????????? {
???????????????????? YELLOW01 = ~YELLOW01;???
???????????????????? Time2 = 0;
????????????? }
?????? }??????????????????????????????????????????????? ???? //南北方向黃燈閃爍
??????
?????? if(Second > (NS_In + Y_In + EW_In ))
?????? {
????????????? Time3++;
?????????????
????????????? if(Time3 == 10)
????????????? {
???????????????????? YELLOW11 = ~YELLOW11;???????????
???????????????????? Time3 = 0;??????????????????
????????????? }
?????? }??????????????????????????????????????????????? ????? //東西方向黃燈閃爍
}
?
/*********************************************************
*函 數(shù) 名???????? :中斷1
*函數(shù)功能????????? ?? :定時(shí)器T1中斷函數(shù)
*輸??? 入???????? :無
*輸??? 出???????? :無
*********************************************************/
voidTimer1() interrupt 3
{
?????? TH1 = 0x3C; ????????????????????????? //設(shè)置初始值
?????? TL1 = 0xB0;
?????? Time1++;
??????
?????? if(Time1 == 10)
?????? {
????????????? YELLOW01 = ~YELLOW01;??? //黃燈雙閃
?????? ???YELLOW11 = ~YELLOW11;???????????
????????????? Time1 = 0;
?????? }
}
?
/*********************************************************
*函 數(shù) 名???????? :計(jì)數(shù)值設(shè)置函數(shù)
*函數(shù)功能????????? ?? :改變計(jì)數(shù)值
*輸??? 入???????? : KeyValue
*輸??? 出???????? : NS_In,EW_In,Y_In
*********************************************************/
?
voidSETMODE(unsigned char KeyValue)
{
?????? GPIO_TRAFFIC = 0x00;
?????? GPIO_PLACE?? = 0xFF;????????????????????????????? //關(guān)閉交通燈肴捉,數(shù)碼管
?
?????? switch(KeyValue)?????????????????????????????????????????????????? //依照按下的鍵對應(yīng)修改時(shí)間
????????????? {
???????????????????? case 12:
????????????? ????????????? KeyInput();NS_In= KeyNum ;?????? //南北通行時(shí)間輸入
??????????????????????????? break;
???????????????????? case 13:
??????????????????????????? KeyInput();EW_In =KeyNum - Y_In ;//東西通行時(shí)間
??????????????????????????? break;?
???????????????????? case 15:
????????????? ????????????? KeyInput();Y_In? = KeyNum ;?????? //黃燈閃爍時(shí)間輸入
??????????????????????????? break;
???????????????????? default: break;
????????????? }
?????? Second = 1;
?????? EA = 1;
}
?
/*********************************************************
*函 數(shù) 名???????? : DayLight
*函數(shù)功能????????? ?? :白天
*輸??? 入???????? :無
*輸??? 出???????? :無
*********************************************************/
?
voidDayLight(void)
{
?????? unsigned int a;
?????? a = 1;
??????
?????? while(a)
?????? {
????????????? KeyDown();
????????????? if(KeyValue == 11)??????????????????????????????????????????????????????? //清零并停止計(jì)時(shí)
????????????? {
???????????????????? a = 0;
???????????????????? ET0 = 0;
???????????????????? Second = 0;
???????????????????? GPIO_TRAFFIC = 0xff;
????????????? }
????????????? if(Second == NS_In + EW_In + 2 *Y_In) //結(jié)束一個(gè)周期
????????????? {
???????????????????? Second = 1;
????????????? }
?
????????????? if((KeyValue == 12)||(KeyValue==13)||(KeyValue ==15))
????????????? {
???????????????????? EA=0;
???????????????????? SETMODE(KeyValue);
????????????? }
????????????? //--南北方向通行--//
????????????? if(Second < (NS_In + 1))
????????????? {
???????????????????? DisplayData[0] =DIG_CODE[(NS_In - Second) % 1000 / 100];
???????????????????? DisplayData[1] =DIG_CODE[(NS_In - Second) % 100 / 10];
???????????????????? DisplayData[2] =DIG_CODE[(NS_In - Second) % 10];
???????????????????? DisplayData[3] =DIG_CODE[(NS_In + Y_In - Second) % 1000 / 100];
???????????????????? DisplayData[4] =DIG_CODE[(NS_In + Y_In - Second) % 100 / 10];
???????????????????? DisplayData[5] =DIG_CODE[(NS_In + Y_In - Second) % 10];
???????????????????? DigDisplay(6);???????????????????????????????????????????????????????????????????? //第一個(gè)時(shí)序倒計(jì)時(shí)
?
???????????????????? GPIO_TRAFFIC = 0x7B;
????????????????????
???????????????????? Time2 = 0;
????????????? }
?
????????????? //--黃燈等待切換狀態(tài)--//
????????????? else if(Second < (NS_In + Y_In+1))
????????????? {
???????????????????? DisplayData[0] =DIG_CODE[(NS_In + Y_In - Second) % 1000 / 100];
???????????????????? DisplayData[1] =DIG_CODE[(NS_In + Y_In - Second) % 100 / 10];
???????????????????? DisplayData[2] =DIG_CODE[(NS_In + Y_In - Second) % 10];
???????????????????? DisplayData[3] =DisplayData[0];
???????????????????? DisplayData[4] =DisplayData[1];
???????????????????? DisplayData[5] =DisplayData[2];
???????????????????? DigDisplay(6);???????????????????????????????????????????????????????????????????? //第二個(gè)時(shí)序倒計(jì)時(shí)
????????????????????
???????????????????? GREEN01 = 1;
????????????????????
????????????? ?????? RED11= 0;?????? ???????????????????????????????????????????????????????????? //東西方向紅燈持續(xù)?
????????????????????
????????????? }
?
????????????? //--東西方向通行--//
????????????? else if(Second < (NS_In + Y_In+ EW_In +1) )
????????????? {
???????????????????? DisplayData[0] =DIG_CODE[(NS_In + Y_In + EW_In - Second) % 1000 / 100];
???????????????????? DisplayData[1] =DIG_CODE[(NS_In + Y_In + EW_In - Second) % 100 / 10];
???????????????????? DisplayData[2] =DIG_CODE[(NS_In + Y_In + EW_In - Second) % 10];
???????????????????? DisplayData[3] =DIG_CODE[(NS_In + EW_In + 2 * Y_In - Second) % 1000 / 100];
???????????????????? DisplayData[4] =DIG_CODE[(NS_In + EW_In + 2 * Y_In - Second) % 100 / 10];
???????????????????? DisplayData[5] =DIG_CODE[(NS_In + EW_In + 2 * Y_In - Second) % 10];
???????????????????? DigDisplay(6);???????????????????????????????????????????????????????????????????? //第三個(gè)時(shí)序倒計(jì)時(shí)
?
???????????????????? GPIO_TRAFFIC = 0xCF;
????????????????????
???????????????????? Time2 = 0;
????????????? }
?
????????????? //--黃燈等待切換狀態(tài)--//
????????????? else
????????????? {
???????????????????? DisplayData[0] =DIG_CODE[(NS_In + EW_In + 2 * Y_In - Second) % 1000 / 100];
???????????????????? DisplayData[1] =DIG_CODE[(NS_In + EW_In + 2 * Y_In - Second) % 100 / 10];
???????????????????? DisplayData[2] =DIG_CODE[(NS_In + EW_In + 2 * Y_In - Second) % 10];
???????????????????? DisplayData[3] =DisplayData[0];
???????????????????? DisplayData[4] =DisplayData[1];
???????????????????? DisplayData[5] =DisplayData[2];
?????? ????????????? DigDisplay(6);???????????????????????????????????????????????????????????????????? //第四個(gè)時(shí)序倒計(jì)時(shí)
?
???????????????????? GREEN11 = 1;
????????????????????
???????????????????? RED01 = 0;??????? ?????????????????????????????????????????????????????????? //南北方向紅燈亮
????????????? }
?????? }
}
?
/*****************************************************************************
*函 數(shù) 名???????? : NightLight
*函數(shù)功能????????? ?? :夜晚
*輸??? 入???????? :無
*輸??? 出???????? :無
*****************************************************************************/
?
voidNightLight(void)
{
?????? unsigned int a;
?????? a = 1;
?????? GPIO_TRAFFIC = 0xB7;
??????
?????? while(a)
?????? {
????????????? KeyDown();
????????????? if(KeyValue == 10)
????????????? {
???????????????????? a = 0;
???????????????????? ET1 = 0;
????????????? }
?????? }
?????? Time1 = 0;
}
?
/*****************************************************************************
*函 數(shù) 名???????? : DigDisplay
*函數(shù)功能????????? ?? :使用數(shù)碼管顯示
*輸??? 入???????? :無
*輸??? 出???????? :無
*****************************************************************************/
?
voidDigDisplay(unsigned int n)
{
?????? unsigned char i;
?????? unsigned int j;
??????
?????? for(i=0; i< n; i++)
?????? {
????????????? GPIO_PLACE = DIG_PLACE[i];???? ?? //發(fā)送位選
????????????? GPIO_DIG = DisplayData[i];???? //發(fā)送段碼
????????????? j = 10;?????????????????????????????????????? ?? //掃描間隔時(shí)間設(shè)定
????????????? while(j--);?????
????????????? GPIO_DIG = 0x00;?????????? ????//消隱
?????? }
}
?
/*****************************************************************************
*函 數(shù) 名???????? : Delay10ms
*函數(shù)功能????????? ?? :延時(shí)函數(shù),延時(shí)10ms
*輸??? 入???????? :無
*輸??? 出???????? :無
*****************************************************************************/
?
voidDelay10ms(unsigned int c)?? //誤差0us
{
??? unsigned char a, b;
?
??? for (;c>0;c--)
?????? {
????????????? for (b=4;b>0;b--)
????????????? {
???????????????????? for (a=130;a>0;a--);
????????????? }
??????????
?????? }
???????
}
?
/*****************************************************************************
*函 數(shù) 名???????? : KeyDown
*函數(shù)功能????????? ?? :檢測有按鍵按下并讀取鍵值
*輸??? 入???????? :無
*輸??? 出???????? :無
*****************************************************************************/
?
unsignedchar KeyDown(void)
{
??? GPIO_KEY = 0xfe;
?
??? while((GPIO_KEY & 0xf0) != 0xf0)???????
??? {
??????? Delay10ms(1);???????????????????
??????? while((GPIO_KEY & 0xf0) !=0xf0)???
??????? {
???????????????????? KeyState=1;
??????????? switch(GPIO_KEY)???????????????
??????????? {
??????????????????????????? case 0xbe:KeyValue=0;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xee:KeyValue=13;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0x7e:KeyValue=14;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xde:KeyValue=15;
????????????????????????????????????????? ?? break;
??????????? }
???????????????????? while((GPIO_KEY & 0xf0)!= 0xf0)
??????????????????????????? ;
??????? }
??? }
??????
?????? GPIO_KEY = 0xfd;???
?
??? while((GPIO_KEY & 0xf0) != 0xf0)
??? {
????????????? Delay10ms(1);???????????????????
??????? while((GPIO_KEY & 0xf0) != 0xf0)
??????? {
???????????????????? KeyState=1;
???????????????????? switch(GPIO_KEY)???????
??????????? {
??????????????? case 0x7d: KeyValue=7;
????????????????????????????????????????? ?? break;?
??????????????????????????? case 0xbd: KeyValue=8;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xdd:KeyValue=9;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xed:KeyValue=12;
????????????????????????????????????????? ?? break;
??????????? }
???????????????????? while((GPIO_KEY & 0xf0)!= 0xf0)
??????????????????????????? ;
??????? }
??? }
?
??? GPIO_KEY = 0xfb;
?
??? while((GPIO_KEY & 0xf0) != 0xf0)
??? {
????????????? Delay10ms(1);???????????????????
??????? while((GPIO_KEY & 0xf0) != 0xf0)
??????? {
???????????????????? KeyState=1;
???????????????????? switch(GPIO_KEY)?
???????????????????? {
??????????????????????????? case 0x7b:KeyValue=4;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xbb:KeyValue=5;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xdb:KeyValue=6;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xeb:KeyValue=11;
????????????????????????????????????????? ?? break;
??????????? }
???????????????????? while((GPIO_KEY & 0xf0)!= 0xf0)
??????????????????????????? ;
??????? }
??? }
?
??? GPIO_KEY = 0xf7;
?
??? while((GPIO_KEY & 0xf0) != 0xf0)
??? {
????????????? Delay10ms(1);???????????????????
??????? while((GPIO_KEY & 0xf0) != 0xf0)
??????? {
???????????????????? KeyState=1;
???????????????????? switch(GPIO_KEY)?
??????????? {
??????????????? case 0x77: KeyValue=1;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xb7:KeyValue=2;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xd7:KeyValue=3;
????????????????????????????????????????? ?? break;
??????????????????????????? case 0xe7:KeyValue=10;
??????????????????????????? ????????????? ??break;
??????????? }
???????????????????? while((GPIO_KEY & 0xf0)!= 0xf0)
??????????????????????????? ;
??????? }
??? }
??? return KeyValue;
?
}
?
/*****************************************************************************
*函 數(shù) 名???????? : KeyInput
*函數(shù)功能????????? ?? :使用鍵盤輸入數(shù)值
*輸??? 入???????? :無
*輸??? 出???????? :無
*****************************************************************************/
?
unsignedchar KeyInput(void)
{
?????? unsigned int Ge,Shi,Bai,a;
?????? KeyNum = 0;
?????? Ge?= 0;
?????? Shi = 0;
?????? Bai = 0;
?????? a=1;
??????
?????? while(a)
?????? {
????????????? KeyDown();
????????????? if(KeyValue < 10 &&KeyState == 1)
????????????? {
???????????????????? Bai = Shi;
???????????????????? Shi = Ge;
???????????????????? Ge? = KeyValue;
????????????????????
???????????????????? KeyState = 0;
????????????? }????????????????????????????????????????????????????????????? //移位顯示
?????????????
????????????? DisplayData[0] = DIG_CODE[Bai];
????????????? DisplayData[1] = DIG_CODE[Shi];
????????????? DisplayData[2] = DIG_CODE[Ge];
????????????? DigDisplay(3);
?????????????
????????????? if(KeyValue == 14)
????????????? {
???????????????????? a = 0;
???????????????????? KeyNum = 100 * Bai + 10 *Shi + Ge;?????
????????????? }?????????????????????????????????????????????????????? ?? //數(shù)據(jù)確認(rèn)鍵
?????? }
}