久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標(biāo)題: 單片機(jī)小車(超詳細(xì)設(shè)計資料) [打印本頁]

作者: zzydezzr    時間: 2019-7-17 03:32
標(biāo)題: 單片機(jī)小車(超詳細(xì)設(shè)計資料)
  1. Hello, world!
復(fù)制代碼



                             第一章、 總述

       本智能小車采用80C51單片機(jī)為控制核心,利用超聲波傳感器檢測道路上的障礙,控制電動小汽車的自動避障,快慢速行駛,以及自動停車,并可以自動記錄時間、里程和速度,自動尋跡和尋光功能。整個系統(tǒng)的電路結(jié)構(gòu)簡單,可靠性能高。本文著重介紹了該系統(tǒng)的硬件設(shè)計方法及測試結(jié)果分析。
       采用的技術(shù)主要有:
    (1)通過編程來控制小車的速度;
    (2)傳感器的有效應(yīng)用;
    (3)新型顯示芯片的采用.
    具體實(shí)現(xiàn):在現(xiàn)有玩具電動車的基礎(chǔ)上,加裝光電、紅外線、超聲波傳感器及金屬探測器,實(shí)現(xiàn)對電動車的速度、位置、運(yùn)行狀況的實(shí)時測量,并將測量數(shù)據(jù)傳送至單片機(jī)進(jìn)行處理,然后由單片機(jī)根據(jù)所檢測的各種數(shù)據(jù)實(shí)現(xiàn)對電動車的智能控制。
這種方案能實(shí)現(xiàn)對電動車的運(yùn)動狀態(tài)進(jìn)行實(shí)時控制,控制靈活、可靠,精度高,可滿足對系統(tǒng)的各項要求。本設(shè)計采用MCS-51系列中的80C51單片機(jī)。以80C51為控制核心,利用超聲波傳感器檢測道路上的障礙,控制電動小汽車的自動避障,快慢速行駛,以及自動停車,并可以自動記錄時間、里程和速度,自動尋跡和尋光功能。80C51引腳如下所示:



    80C51芯片資料: 80C51英文資料.pdf (368.61 KB, 下載次數(shù): 15)



第二章、 方案設(shè)計與論證

   一 、直流調(diào)速系統(tǒng)
   方案一:串電阻調(diào)速系統(tǒng)。
    方案二:靜止可控整流器。簡稱V-M系統(tǒng)。
    方案:脈寬調(diào)速系統(tǒng)。


    與V-M系統(tǒng)相比,PWM調(diào)速系統(tǒng)有下列優(yōu)點(diǎn):
   (1)由于PWM調(diào)速系統(tǒng)的開關(guān)頻率較高,僅靠電樞電感的濾波作用就可以獲得脈動很小的直流電流,電樞電流容易連續(xù),系統(tǒng)的低速運(yùn)行平穩(wěn),調(diào)速范圍較寬,可達(dá)1:10000左右。由于電流波形比V-M系統(tǒng)好,在相同的平均電流下,電動機(jī)的損耗和發(fā)熱都比較小。
   (2)同樣由于開關(guān)頻率高,若與快速響應(yīng)的電機(jī)相配合,系統(tǒng)可以獲得很寬的頻帶,因此快速響應(yīng)性能好,動態(tài)抗擾能力強(qiáng)。
   (3)由于電力電子器件只工作在開關(guān)狀態(tài),主電路損耗較小,裝置效率較高。
    根據(jù)以上綜合比較,以及本設(shè)計中受控電機(jī)的容量和直流電機(jī)調(diào)速的發(fā)展方向,本設(shè)計采用了H型單極型可逆PWM變換器進(jìn)行調(diào)速。脈寬調(diào)速系統(tǒng)的主電路采用脈寬調(diào)制式變換器,簡稱PWM變換器。脈寬調(diào)速也可通過單片機(jī)控制繼電器的閉合來實(shí)現(xiàn),但是驅(qū)動能力有限。為順利實(shí)現(xiàn)電動小汽車的前行與倒車,本設(shè)計采用了可逆PWM變換器?赡鍼WM變換器主電路的結(jié)構(gòu)式有H型、T型等類型。在設(shè)計中采用了常用的雙極式H型變換器,它是由4個三極電力晶體管和4個續(xù)流二極管組成的橋式電路。

    二 、檢測系統(tǒng)
    檢測系統(tǒng)主要實(shí)現(xiàn)光電檢測,即利用各種傳感器對電動車的避障、位置、行車狀態(tài)進(jìn)行測量。
    1.行車起始、終點(diǎn)及光線檢測:
    本系統(tǒng)采用反射式紅外線光電傳感器用于檢測路面的起始、終點(diǎn)(2cm寬的黑線),玩具車底盤上沿黑線放置一套,以適應(yīng)起始的記數(shù)開始和終點(diǎn)的停車的需要。利用超聲波傳感器檢測障礙。光線跟蹤,采用光敏三極管接收燈泡發(fā)出的光線,當(dāng)感受到光線照射時,其c-e間的阻值下降,檢測電路輸出高電平,經(jīng)LM393電壓比較器和74LS14施密特觸發(fā)器整形后送單片機(jī)控制。
    本系統(tǒng)共設(shè)計兩個光電三極管,分別放置在電動車車頭的左、右兩個方向,用來控制電動車的行走方向,當(dāng)左側(cè)光電管受到光照時,單片機(jī)控制轉(zhuǎn)向電機(jī)向左轉(zhuǎn);當(dāng)右側(cè)光電管受到光照時,單片機(jī)控制轉(zhuǎn)向電機(jī)向右轉(zhuǎn);當(dāng)左、右兩側(cè)光電管都受到光照時,單片機(jī)控制直行。見圖2.1 電動車的方向檢測電路(a)。
    行車方向檢測電路(見圖2.2 電動車的方向檢測電路(b))采用反射接收原理配置了一對紅外線發(fā)射、接收傳感器。該電路包括一個紅外發(fā)光二極管、一個紅外光敏三極管及其上拉電阻。紅外發(fā)光二極管發(fā)射一定強(qiáng)度的紅外線照射物體,紅外光敏三極管在接收到反射回來的紅外線后導(dǎo)通,發(fā)出一個電平跳變信號。
    此套紅外光電傳感器固定在底盤前沿,貼近地面。正常行駛時,發(fā)射管發(fā)射紅外光照射地面,光線經(jīng)白紙反射后被接收管接收,輸出高電平信號;電動車經(jīng)過黑線時,發(fā)射端發(fā)射的光線被黑線吸收,接收端接收不到反射光線,傳感器輸出低電平信號后送80C51單片機(jī)處理,判斷執(zhí)行哪一種預(yù)先編制的程序來控制玩具車的行駛狀態(tài)。前進(jìn)時,驅(qū)動輪直流電機(jī)正轉(zhuǎn),進(jìn)入減速區(qū)時,由單片機(jī)控制進(jìn)行PWM變頻調(diào)速,通過軟件改變脈沖調(diào)寬波形的占空比,實(shí)現(xiàn)調(diào)速。最后經(jīng)反接制動實(shí)現(xiàn)停車。前行與倒車控制電路的核心是橋式電路和繼電器。電橋上設(shè)置有兩組開關(guān),一組常閉,另一組常開。電橋一端接電源,另一端接了一個三極管。三極管導(dǎo)通時,電橋通過三極管接地,電機(jī)電樞中有電流通過;三極管截止時,電橋浮空,電機(jī)電樞中沒有電流通過。系統(tǒng)通過電橋的輸出端為轉(zhuǎn)向電機(jī)供電。通過對繼電器開閉的控制即可控制電機(jī)的開斷和轉(zhuǎn)速方向進(jìn)而達(dá)到控制玩具車前行與倒車的目的,實(shí)現(xiàn)隨動控制系統(tǒng)的糾偏功能。如圖2.3 前行與倒車控制電路所示。

                                                                                                                                             

                                           圖2.1電動車的方向檢測電路(a)


  


                              圖2.2電動車的方向檢測電路(b)



                                 圖2.3前行與倒車控制電路

    檢測放大器方案:
    方案一:使用普通單級比例放大電路。其特點(diǎn)是結(jié)構(gòu)簡單、調(diào)試方便、價格低廉。但是也存在著許多不足。如抗干擾能力差、共模抑制比低等。
    方案二:采用差動放大電路。選擇優(yōu)質(zhì)元件構(gòu)成比例放大電路,雖然可以達(dá)到一定的精度,但有時仍不能滿足某些特殊要求。例如,在測量本設(shè)計中的光電檢測信號時需要把檢測過來的電平信號放大并濾除干擾,而且要求對共模干擾信號具有相當(dāng)強(qiáng)的抑制能力。這種情況下須采用差動放大電路,并應(yīng)設(shè)法減小溫漂。但在實(shí)際操作中,往往滿足了高共模抑制比的要求,卻使運(yùn)算放大器輸出飽和;為獲得單片機(jī)能識別的TTL電平卻又無法抑制共模干擾。
    方案三:電壓比較器方案。電壓比較器的功能是比較兩個電壓的大小,例如將一個信號電壓Ui和一個參考電壓Ur進(jìn)行比較,在Ui>Ur和Ui<Ur兩種不同情況下,電壓比較器輸出兩個不同的電平,即高電平和低電平。而Ui變化經(jīng)過Ur時,比較器的輸出將從一個電壓跳變到另一個電平。比較器有各種不同的類型。對它的要求是:鑒別要準(zhǔn)確,反應(yīng)要靈敏,動作要迅速,抗干擾能力要強(qiáng),還應(yīng)有一定的保護(hù)措施,以防止因過電壓或過電流而造成器件損壞。
比較器的特點(diǎn):
    ⑴  工作在開環(huán)或正反饋狀態(tài)。放大、運(yùn)算電路為了實(shí)現(xiàn)性能穩(wěn)定并滿足
一定的精度要求,這些電路中的運(yùn)放均引入了深度負(fù)反饋;而為了提高比較器的反應(yīng)速度和靈敏度,它所采用的運(yùn)放不但沒有引入負(fù)反饋,有時甚至還加正反饋。因此比較器的性能分析方法與放大、運(yùn)算電路是不同的。
    ⑵  非線性。由于比較器中運(yùn)放處于開環(huán)或正反饋狀態(tài),它的兩個輸入端之間的電位差與開環(huán)電壓放大倍數(shù)的乘積通常超過最大輸出電壓,使其內(nèi)部某些管子進(jìn)入飽和區(qū)或截止區(qū),因此在絕大多數(shù)情況下輸出與輸入不成線性關(guān)系,即在放大、運(yùn)算等電路中常用的計算方法對于比較器不再適用。
    ⑶  開關(guān)特性。比較器的輸出通常只有高電平和低電平兩種穩(wěn)定狀態(tài),因此它相當(dāng)與一個受輸入信號控制的開關(guān),當(dāng)輸入電壓經(jīng)過閾值時開關(guān)動作,使輸出從一個電平跳變到另一個電平。由于比較器的輸入信號是模擬量,而它的輸出電平是離散的,因此電壓比較器可作為模擬電路與數(shù)字電路之間的過渡電路。  
    由于比較器的上述特點(diǎn),在分析時既不能象對待放大電路那樣去計算放大倍數(shù),也不能象分析運(yùn)算電路那樣去求解輸出與輸入的函數(shù)關(guān)系,而應(yīng)當(dāng)著重抓住比較器的輸出從一個電平跳變到另一個電平的臨界條件所對應(yīng)的輸入電壓值(閾值)來分析輸入量與輸出量之間的關(guān)系。
    如果在比較器的輸入端加理想階躍信號,那么在理想情況下比較器的輸出也應(yīng)當(dāng)是理想的階躍電壓,而且沒有延遲。但實(shí)際集成運(yùn)放的最大轉(zhuǎn)換速率總是有限的,因此比較器輸出電壓的跳變不可能是理想的階躍信號。電壓比較器的輸出從低電平變?yōu)楦唠娖剿毜臅r間稱為響應(yīng)時間。響應(yīng)時間越短,響應(yīng)速度越快。
    減小比較器響應(yīng)時間的主要方法有:
    (1) 盡可能使輸入信號接近理想情況,使它在閾值附近的變化接近理想階躍
且幅度足夠大。
    (2) 選用集成電壓比較器。
    (3) 如果選用集成運(yùn)放構(gòu)成比較器,為了提高響應(yīng)速度可以加限幅措施,以避免集成運(yùn)放內(nèi)部的管子進(jìn)入深飽和區(qū)。具體措施多為在集成運(yùn)放的兩個輸入端并聯(lián)二極管。如圖2.4 電壓比較器電路所示:


圖2.4 電壓比較器電路

    在本設(shè)計中,光電傳感器只輸出一種高低電平信號且伴有外界雜波干擾,所以我們嘗試采用了一種滯回比較器。簡單電壓比較器結(jié)構(gòu)簡單,而且靈敏度高,但它的抗干擾能力差,也就是說如果輸入信號因受干擾在閾值附近變化,則比較器輸出就會反復(fù)的從一個電平跳到另一個電平。如果用這樣的輸出電壓控制電機(jī)或繼電器,將出現(xiàn)頻繁動作或起,F(xiàn)象。這種情況,通常是不允許的。而滯回比較器則解決了這個問題。滯回比較器有兩個數(shù)值不同的閾值,當(dāng)輸入信號因受干擾或其他原因發(fā)生變化時,只要變化量不超過兩個閾值之差,滯回比較器的輸出電壓就不會來回變化。所以抗干擾能力強(qiáng)。但是,滯回比較器畢竟是模擬器件,溫度的漂移是它無法消除的。
    方案四:施密特觸發(fā)器。綜合考慮系統(tǒng)的各項性能,最后我們決定采用數(shù)字器件——施密特觸發(fā)器。施密特觸發(fā)器是雙穩(wěn)態(tài)觸發(fā)器的變形,它有兩個穩(wěn)定狀態(tài),觸發(fā)方式為電平觸發(fā),只要外加觸發(fā)信號的幅值增加到足夠大,它就從一個穩(wěn)定狀態(tài)翻轉(zhuǎn)到另一個穩(wěn)定狀態(tài)。施密特觸發(fā)器具有與滯回比較器相類似的滯回特性,但施密特觸發(fā)器的抗干擾能力比滯回比較器更強(qiáng)。

    2.行車距離檢測
    由于紅外檢測具有反應(yīng)速度快、定位精度高,可靠性強(qiáng)以及可見光傳感器所不能比擬的優(yōu)點(diǎn),故采用紅外光電碼盤測速方案。具體電路同圖2.5 行車距離檢測電路所示:


圖2.5 行車距離檢測電路

    紅外測距儀由測距輪,遮光盤,紅外光電耦合器及凹槽型支架組成的。測長輪的周長為記數(shù)的單位,最好取有效值為單一的數(shù)值(如本設(shè)計中采用0.1米),精度根據(jù)電動車控制的需要確定。測距輪安裝在車輪上,這樣能使記數(shù)值準(zhǔn)確一些。遮光盤有一缺口,盤下方的凹形物為槽型光電耦合器,其兩端高出部分的里面分別裝有紅外發(fā)射管和紅外接收管。遮光盤在凹槽中轉(zhuǎn)動時,缺口進(jìn)入凹槽時,紅外線可以通過,缺口離開凹槽紅外線被阻擋。由此可見,測距輪每轉(zhuǎn)一周,紅外光接收管均能接收到一個脈沖信號經(jīng)過整形器后送入計數(shù)器或直接送入單片機(jī)中。
    為實(shí)現(xiàn)可逆記數(shù)功能,我們在測距儀中并列放置了兩個槽型光電耦合器,遮光盤先后通過凹槽可產(chǎn)生兩個脈沖信號。根據(jù)兩個脈沖信號發(fā)生的先后順序與兩個光電耦合器的位置關(guān)系,即可計算出玩具車的行駛方向(前進(jìn)或后退)。
遮光盤及槽型光電耦合器均安裝在不透光的盒子里,以避免外界光線的干擾,使電路不能正常工作。
    測距原理:將光柵安裝在電機(jī)軸上,當(dāng)電機(jī)轉(zhuǎn)動時,光柵也隨之轉(zhuǎn)動,同時安裝在光柵一側(cè)的紅外發(fā)光二極管點(diǎn)亮,在光柵的另一側(cè)設(shè)有紅外三極管,用于接收紅外發(fā)光二極管發(fā)出的紅外線信號。由于光柵隨電機(jī)高速轉(zhuǎn)動,則紅外線三極管接收到的就是一系列脈沖信號。將該信號傳輸?shù)?0C51單片機(jī)的內(nèi)部計數(shù)器計數(shù),根據(jù)預(yù)先實(shí)測的數(shù)據(jù)換算關(guān)系即可計算出電動機(jī)車的行車距離。

   三、顯示電路
    本設(shè)計中用兩片4位八段數(shù)碼作顯示器,并具有雙重功能,在小車不行駛時其中一片顯示年、月,另一片顯示時、分; 當(dāng)小車行駛時,分別顯示時間和行駛距離。

   、系統(tǒng)原理圖
    簡易智能電動車采用80C51單片機(jī)進(jìn)行智能控制。開始由手動啟動小車,并復(fù)位,當(dāng)經(jīng)過規(guī)定的起始黑線,由超聲波傳感器和紅外光電傳感器檢測,通過單片機(jī)控制小車開始記數(shù)顯示并避障、調(diào)速;系統(tǒng)的自動避障功能通過超聲波傳感器正前方檢測和紅外光電傳感器左右側(cè)檢測,由單片機(jī)控制實(shí)現(xiàn);在電動車進(jìn)駛過程中,采用雙極式H型PWM脈寬調(diào)制技術(shù),以提高系統(tǒng)的靜動態(tài)性能;采用動態(tài)共陰顯示行駛時間和里程。
系統(tǒng)原理圖如圖2.6所示。

圖2.6 系統(tǒng)原理圖



第三章、 硬件設(shè)計

    單片機(jī)應(yīng)用系統(tǒng)的硬件電路設(shè)計包含有兩部分內(nèi)容:
    一是系統(tǒng)擴(kuò)展,即單片機(jī)內(nèi)部的功能單元,如ROM﹑RAM﹑I/O口﹑定時/記數(shù)器﹑中斷系統(tǒng)等能量不能滿足應(yīng)用系統(tǒng)的要求時,必須在片外進(jìn)行擴(kuò)展,選擇適當(dāng)?shù)男酒,設(shè)計相應(yīng)的電路。
    二是系統(tǒng)配置,既按照系統(tǒng)功能要求配置外圍設(shè)備,如鍵盤顯示器﹑打印機(jī)﹑A/D﹑D/A轉(zhuǎn)換器等,要設(shè)計合適的接口電路。

    一 、80C51單片機(jī)硬件結(jié)構(gòu)
    80C51單片機(jī)是把那些作為控制應(yīng)用所必需的基本內(nèi)容都集成在一個尺寸有限的集成電路芯片上[2]。如果按功能劃分,它由如下功能部件組成,即微處理器、數(shù)據(jù)存儲器、程序存儲器、并行I/O口、串行口、定時器/計數(shù)器、中斷系統(tǒng)及特殊功能寄存器。它們都是通過片內(nèi)單一總線連接而成,其基本結(jié)構(gòu)依舊是CPU加上外圍芯片的傳統(tǒng)結(jié)構(gòu)模式。但對各種功能部件的控制是采用特殊功能寄存器的集中控制方式。

    由上可見,80C51單片機(jī)的硬件結(jié)構(gòu)具有功能部件種類全,功能強(qiáng)等特點(diǎn)。特別值得一提的是該單片機(jī)CPU中的位處理器,它實(shí)際上是一個完整的1位微計算機(jī),這個一位微計算機(jī)有自己的CPU、位寄存器、I/O口和指令集。1位機(jī)在開關(guān)決策、邏輯電路仿真、過程控制方面非常有效;而8位機(jī)在數(shù)據(jù)采集,運(yùn)算處理方面有明顯的長處。MCS-51單片機(jī)中8位機(jī)和1位機(jī)的硬件資源復(fù)合在一起,二者相輔相承,它是單片機(jī)技術(shù)上的一個突破,這也是MCS-51單片機(jī)在設(shè)計的精美之處。

   二 、最小應(yīng)用系統(tǒng)設(shè)計
    80C51是片內(nèi)有ROM/EPROM的單片機(jī),因此,這種芯片構(gòu)成的最小系統(tǒng)簡單﹑可靠。用80C51單片機(jī)構(gòu)成最小應(yīng)用系統(tǒng)時,只要將單片機(jī)接上時鐘電路和復(fù)位電路即可,如圖3.1 80C51單片機(jī)最小系統(tǒng)所示。由于集成度的限制,最小應(yīng)用系統(tǒng)只能用作一些小型的控制單元。其應(yīng)用特點(diǎn):
(1)有可供用戶使用的大量I/O口線。
(2)內(nèi)部存儲器容量有限。
(3)應(yīng)用系統(tǒng)開發(fā)具有特殊性。


圖3.1 80C51單片機(jī)最小系統(tǒng)

    1、時鐘電路
    80C51雖然有內(nèi)部振蕩電路,但要形成時鐘,必須外部附加電路。80C51單片機(jī)的時鐘產(chǎn)生方法有兩種。內(nèi)部時鐘方式和外部時鐘方式。
    本設(shè)計采用內(nèi)部時鐘方式,利用芯片內(nèi)部的振蕩電路,在XTAL1、XTAL2引腳上外接定時元件,內(nèi)部的振蕩電路便產(chǎn)生自激振蕩。本設(shè)計采用最常用的內(nèi)部時鐘方式,即用外接晶體和電容組成的并聯(lián)諧振回路。振蕩晶體可在1.2MHZ到12MHZ之間選擇。電容值無嚴(yán)格要求,但電容取值對振蕩頻率輸出的穩(wěn)定性、大小、振蕩電路起振速度有少許影響,CX1、CX2可在20pF到100pF之間取值,但在60pF到70pF時振蕩器有較高的頻率穩(wěn)定性。所以本設(shè)計中,振蕩晶體選擇6MHZ,電容選擇65pF。在設(shè)計印刷電路板時,晶體和電容應(yīng)盡可能靠近單片機(jī)芯片安裝,以減少寄生電容,更好的保證振蕩器穩(wěn)定和可靠地工作。為了提高溫度穩(wěn)定性,應(yīng)采用NPO電容。
    2、復(fù)位電路
    80C51的復(fù)位是由外部的復(fù)位電路來實(shí)現(xiàn)的。復(fù)位引腳RST通過一個斯密特觸發(fā)器用來抑制噪聲,在每個機(jī)器周期的S5P2,斯密特觸發(fā)器的輸出電平由復(fù)位電路采樣一次,然后才能得到內(nèi)部復(fù)位操作所需要的信號。
復(fù)位電路通常采用上電自動復(fù)位和按鈕復(fù)位兩種方式。
    最簡單的上電自動復(fù)位電路中上電自動復(fù)位是通過外部復(fù)位電路的電容充電來實(shí)現(xiàn)的。只要Vcc的上升時間不超過1ms,就可以實(shí)現(xiàn)自動上電復(fù)位。時鐘頻率用6MHZ時C取22uF,R取1KΩ。
    除了上電復(fù)位外,有時還需要按鍵手動復(fù)位。本設(shè)計就是用的按鍵手動復(fù)位。按鍵手動復(fù)位有電平方式和脈沖方式兩種。其中電平復(fù)位是通過RST端經(jīng)電阻與電源Vcc接通而實(shí)現(xiàn)的。按鍵手動復(fù)位電路見圖3.2。時鐘頻率選用6MHZ時,C取22uF,Rs取200Ω,RK取1KΩ。

圖3.2 80C51復(fù)位電路

    三、 前向通道設(shè)計
    單片機(jī)用與測控系統(tǒng)時,總要有與被測對象相聯(lián)系的前向通道。因此,前向通道設(shè)計與被測對象的狀態(tài)、特征、所處環(huán)境密切相關(guān)。在前向通道設(shè)計時要考慮到傳感器或敏感元件選擇、通道結(jié)構(gòu)、信號調(diào)節(jié)、電源配置、抗干擾設(shè)計等。在通道電路設(shè)計中還涉及到模擬電路諸多問題。

    1﹑前向通道的含義
    當(dāng)將單片機(jī)用作測﹑控系統(tǒng)時,系統(tǒng)中總要有被測信號輸入通道,有計算機(jī)拾取必要的輸入信息。作為測試系統(tǒng),對被測對象拾取必要的原始參量信號是系統(tǒng)的核心任務(wù),對控制系統(tǒng)來說,對被控對象狀態(tài)的測試以及對控制條件的監(jiān)測也是不可缺少的環(huán)節(jié)。對被測對象狀態(tài)的測試一般都離不開傳感器或敏感元件,這是因為被測對象的狀態(tài)參數(shù)常常是一些非電物理量,如溫度、壓力、載荷、位移等,而計算機(jī)是一個數(shù)字電路系統(tǒng)。因此,在前向通道中,傳感器、敏感元件及其相關(guān)電路占有重要地位。
    對被測對象的信號的拾取其主要任務(wù)就是最忠實(shí)地反映被測對象的真實(shí)狀態(tài),它包括實(shí)時性與測量精度。同時使這些測量信號能滿足計算機(jī)輸入接口的電平要求。
    因此,單片機(jī)應(yīng)用系統(tǒng)中的前向通道體現(xiàn)了被測對象與系統(tǒng)相互聯(lián)系的信號輸入通道,原始參數(shù)輸入通道。由于在該通道中主要是傳感器與傳感器有關(guān)的信號調(diào)節(jié)、變換電路,故也可稱為傳感器接口通道。
    在單片機(jī)應(yīng)用系統(tǒng)中,對信號輸入、傳感、變換應(yīng)作廣義理解,例如開關(guān)量的檢測及信號輸入,在單片機(jī)的各種應(yīng)用系統(tǒng)中有著廣泛的應(yīng)用。最簡單的開關(guān)量輸入通道就是一個具有TTL電平的狀態(tài)開關(guān),如水銀溫度觸點(diǎn)、溫度晶閘管、時間繼電器、限位開關(guān)等。故只要反映外界狀態(tài)的信號輸入通道都可稱為前向通道。并不是所有單片機(jī)應(yīng)用系統(tǒng)都有前向通道,例如時序控制系統(tǒng),只根據(jù)系統(tǒng)內(nèi)部的時間序列來控制外部的運(yùn)行狀態(tài);分布式測控系統(tǒng)中的智能控制總站完成上級主計算機(jī)與現(xiàn)場測、控子站計算機(jī)之間的指令、數(shù)據(jù)傳送。這些應(yīng)用系統(tǒng)沒有被測對象,故不需要前向通道。

    2﹑前向通道的設(shè)計
  (1)傳感器的比較如下識別障礙的首要問題是傳感器的選擇,下面對幾種傳感器的優(yōu)缺點(diǎn)進(jìn)行說。探測障礙的最簡單的方法是使用超聲波傳感器,它是利用向目標(biāo)發(fā)射超聲波脈沖,計算其往返時間來判定距離的。該方法被廣泛應(yīng)用于移動機(jī)器人的研究上。其優(yōu)點(diǎn)是價格便宜,易于使用,且在10m以內(nèi)能給出精確的測量。不過在ITS系統(tǒng)中除了上文提出的場景限制外,還有以下問題。首先因其只能在10m以內(nèi)有效使用,所以并不適合ITS系統(tǒng)。另外超聲波傳感器的工作原理基于聲,即使可以使之測達(dá)100m遠(yuǎn),但其更新頻率為2Hz,而且還有可能在傳輸中受到它信號的干擾,所以在CW/ICC系統(tǒng)中使用是不實(shí)際的。

    視覺傳感器在CW系統(tǒng)中使用得非常廣泛。其優(yōu)點(diǎn)是尺寸小,價格合理,在一定的寬度和視覺域內(nèi)可以測量定多個目標(biāo),并且可以利用測量的圖像根據(jù)外形和大小對目標(biāo)進(jìn)行分類。但是算法復(fù)雜,處理速度慢。雷達(dá)傳感器在軍事和航空領(lǐng)域已經(jīng)使用了幾十年。主要優(yōu)點(diǎn)是可以魯棒地探測到障礙而不受天氣或燈光條件限制。近十年來隨著尺寸及價格的降低,在汽車行業(yè)開始被使用。但是仍存在性價比的問題。
  (2)超聲波障礙檢測
    超聲波是一種在彈性介質(zhì)中的機(jī)械振蕩,其頻率超過20KHz,分橫向振蕩和縱向振蕩兩種,超聲波可以在氣體、液體及固體中傳播,其傳播速度不同。它有折射和反射現(xiàn)象,且在傳播過程中有衰減。利用超聲波的特性,可做成各種超聲波傳感器,結(jié)合不同的電路,可以制成超聲波儀器及裝置,在通訊、醫(yī)療及家電中獲得廣泛應(yīng)用。
    作為超聲波傳感器的材料,主要為壓電晶體。壓電晶體組成的超聲波傳感器是一種可逆?zhèn)鞲衅,它可以將電能轉(zhuǎn)變成機(jī)械振蕩而產(chǎn)生超聲波,同時它接收到超聲波時,也能轉(zhuǎn)變成電能,故它分為發(fā)送器和接收器。超聲波傳感器有透射型、反射型兩種類型,常用于防盜報警器、接近開關(guān)、測距及材料探傷、測厚等。
本設(shè)計采用T/R-40-12小型超聲波傳感器作為探測前方障礙物體的檢測元件,其中心頻率為40Hz,由80C51發(fā)出的40KHz脈沖信號驅(qū)動超聲波傳感器發(fā)送器發(fā)出40KHz的脈沖超聲波,如電動車前方遇到有障礙物時,此超聲波信號被障礙物反射回來,由接收器接收,經(jīng)LM318兩級放大,再經(jīng)帶有鎖相環(huán)的音頻解碼芯片LM567解碼,當(dāng)LM567的輸入信號大于25mV時,輸出端由高電平變?yōu)榈碗娖,?0C51單片機(jī)處理。超聲波檢測如圖3.3超聲波檢測電路所示。


圖 3.3 超聲波檢測電路

    四、后向通道設(shè)計
     在工業(yè)控制系統(tǒng)中,單片機(jī)總要對控制對象實(shí)現(xiàn)操作,因此,在這樣的系統(tǒng)中,總要有后向通道。后向通道是計算機(jī)實(shí)現(xiàn)控制運(yùn)算處理后,對控制對象的輸出通道接口。
根據(jù)單片機(jī)的輸出和控制對象實(shí)現(xiàn)控制信號的要求,后向通道具有以下特點(diǎn):
   (1) 小信號輸出、大功率控制。根據(jù)目前單片機(jī)輸出功率的限制,不能輸出控制對象所要求的功率信號。
   (2) 是一個輸出通道。輸出伺服驅(qū)動系統(tǒng)控制信號,而伺服驅(qū)動系統(tǒng)中的狀態(tài)反饋信號通常是作為檢測信號輸入前向通道。
   (3) 接近控制對象,環(huán)境惡劣?刂茖ο蠖酁榇蠊β仕欧(qū)動機(jī)構(gòu),電磁、機(jī)械干擾較為嚴(yán)重。但后向通道是一個輸出通道,而且輸出電平較高,不易受到直接損害。但這些干擾易從系統(tǒng)的前向通道竄入。
    單片機(jī)在完成控制處理后,總是以數(shù)字信號通過I/O口或數(shù)據(jù)總線送給控制對象。這些數(shù)字信號形態(tài)主要有開關(guān)量、二進(jìn)制數(shù)字量和頻率量,可直接用于開關(guān)量、數(shù)字量系統(tǒng)及頻率調(diào)制系統(tǒng),但對于一些模擬量控制系統(tǒng),則應(yīng)通過數(shù)/模轉(zhuǎn)換成模擬量控制信號。
    根據(jù)單片機(jī)輸出信號形態(tài)及控制對象要求,后向通道應(yīng)解決:
   (1} 功率驅(qū)動。將單片機(jī)輸出信號進(jìn)行功率放大,以滿足伺服驅(qū)動的功率要求。
   (2)干擾防治。主要防治伺服驅(qū)動系統(tǒng)通過信號通道﹑電源以及空間電磁場對計算機(jī)系統(tǒng)的干擾。通常采用信號隔離﹑電源隔離和對功率開關(guān)實(shí)現(xiàn)過零切換等方法進(jìn)行干擾防治。
   (3)數(shù)/模轉(zhuǎn)換。對于二進(jìn)制輸出的數(shù)字量采用D/A變換器;對于頻率量輸出則可以采用本設(shè)計調(diào)速采用PWM調(diào)速:
    為順利實(shí)現(xiàn)電動小汽車的左轉(zhuǎn)和右轉(zhuǎn),本設(shè)計采用了可逆PWM變換器?赡鍼WM變換器主電路的結(jié)構(gòu)式有H型、T型等類型。我們在設(shè)計中采用了常用的雙極式H型變換器,它是由4個三極電力晶體管和4個續(xù)流二極管組成的橋式電路。圖3.4為雙極式H型可逆PWM變換器的電路原理圖。4個電力晶體管的基極驅(qū)動電壓分為兩組。VT1和VT4同時導(dǎo)通和關(guān)斷,其驅(qū)動電路中Ub1=Ub4;VT2和VT3同時動作,其驅(qū)動電壓Ub2=Ub3= -Ub1。
雙極式PWM變換器的優(yōu)點(diǎn)如下:
(1)電流一定連續(xù);
(2)可使電動機(jī)在四象限中運(yùn)行;
(3)電機(jī)停止時有微振電流,能消除靜摩擦死區(qū);
(4)低速時,每個晶體管的驅(qū)動脈沖仍較寬,有利于保證晶體管可靠導(dǎo)通;
(5)低速平穩(wěn)性好,調(diào)速范圍可達(dá)20000左右。


圖3.4 雙極式H型可逆PWM變換器電路原理圖

    1、脈寬調(diào)制原理:
    脈寬調(diào)制器本身是一個由運(yùn)算放大器和幾個輸入信號組成的電壓比較器。運(yùn)算放大器工作在開換狀態(tài),稍微有一點(diǎn)輸入信號就可使其輸出電壓達(dá)到飽和值,當(dāng)輸入電壓極性改變時,輸出電壓就在正、負(fù)飽和值之間變化,這樣就完成了把連續(xù)電壓變成脈沖電壓的轉(zhuǎn)換作用。加在運(yùn)算放大器反相輸入端上的有三個輸入信號。一個輸入信號是鋸齒波調(diào)制信號,另一個是控制電壓,其極性大小可隨時改變,與鋸齒波調(diào)制信號相減,從而在運(yùn)算放大器的輸出端得到周期不變、脈寬可變的調(diào)制輸出電壓。只要改變控制電壓的極性,也就改變了PWM變換器輸出平均電壓的極性,因而改變了電動機(jī)的轉(zhuǎn)向.改變控制電壓的大小,則調(diào)節(jié)了輸出脈沖電壓的寬度,從而調(diào)節(jié)電動機(jī)的轉(zhuǎn)速.只要鋸齒波的線性度足夠好,輸出脈沖的寬度是和控制電壓的大小成正比的.
    2、邏輯延時環(huán)節(jié):
    在可逆PWM變換器中,跨接在電源兩端的上下兩個晶體管經(jīng)常交替工作.由于晶體管的關(guān)斷過程中有一段存儲時間和電流下降時間,總稱關(guān)斷時間,在這段時間內(nèi)晶體管并未完全關(guān)斷.如果在此期間另一個晶體管已經(jīng)導(dǎo)通,則將造成上下兩管之通,從而使電源正負(fù)極短路.為避免發(fā)生這種情況,設(shè)置了由RC電路構(gòu)成的延時環(huán)節(jié).
    3、電源的設(shè)計
    本設(shè)計的電源為車載電源。為保證電源工作可靠,單片機(jī)系統(tǒng)與動力伺服系統(tǒng)的電源采用了大功率、大容量的蓄電池;而傳感器的工作電源則采用了小巧輕便的干電池。

    五、 顯示電路設(shè)計
    本設(shè)計中用兩片4位八段數(shù)碼管gem4561ae作顯示器,并具有雙重功能,在小車不行駛時其中一片顯示年月,另一片顯示時.分. 當(dāng)小車行駛時,分別顯示時間和行駛距離原理圖如圖1.
    本設(shè)計中采用新型芯片EM78P458作為顯示驅(qū)動器,它的管腳如圖3.5 EM78P458管腳介紹所示,用單片機(jī)的并行口控制,一個數(shù)碼顯示電路用4個口線,用專用驅(qū)動芯片控制可以減少對CPU的利用時間,單片機(jī)將有更多的時間去完成其他功能.

圖3.5 EM78P458的管腳


    該芯片所驅(qū)動的顯示電路如圖3.6 EM78P458集成顯示電路所示
顯示驅(qū)動器支持動態(tài)顯示,其顯示功能如表4.2真值表所示,0000-1001顯示從0-9數(shù)字,1010是未進(jìn)位時是小數(shù)點(diǎn)清位,1011是進(jìn)位后加小數(shù)點(diǎn),1100-1111是八段共陰數(shù)碼管的位選。


圖3.6 EM78P458集成顯示電路



第四章、軟件設(shè)計

    系統(tǒng)軟件設(shè)計說明
    在進(jìn)行微機(jī)控制系統(tǒng)設(shè)計時,除了系統(tǒng)硬件設(shè)計外,大量的工作就是如何根據(jù)每個生產(chǎn)對象的實(shí)際需要設(shè)計應(yīng)用程序。因此,軟件設(shè)計在微機(jī)控制系統(tǒng)設(shè)計中占重要地位。對于本系統(tǒng),軟件更為重要。
在單片機(jī)控制系統(tǒng)中,大體上可分為數(shù)據(jù)處理、過程控制兩個基本類型。數(shù)據(jù)處理包括:數(shù)據(jù)的采集、數(shù)字濾波、標(biāo)度變換等。過程控制程序主要是使單片機(jī)按一定的方法進(jìn)行計算,然后再輸出,以便控制生產(chǎn)。
    為了完成上述任務(wù),在進(jìn)行軟件設(shè)計時,通常把整個過程分成若干個部分,每一部分叫做一個模塊。所謂“模塊”,實(shí)質(zhì)上就是所完成一定功能,相對獨(dú)立的程序段,這種程序設(shè)計方法叫模塊程序設(shè)計法。
    模塊程序設(shè)計法的主要優(yōu)點(diǎn)是:
    1、單個模塊比起一個完整的程序易編寫及調(diào)試;
    2、模塊可以共存,一個模塊可以被多個任務(wù)在不同條件下調(diào)用;
    3、模塊程序允許設(shè)計者分割任務(wù)和利用已有程序,為設(shè)計者提供方便。
    本系統(tǒng)軟件采用模塊化結(jié)構(gòu),由主程序﹑定時子程序、避障子程序﹑中斷子程序顯示子程序﹑調(diào)速子程序﹑算法子程序構(gòu)成。

    一 、主程序設(shè)計                                                              
   程序清單如下

  1. limiw   equ     30h ;厘米位
  2.         miao    equ     31h ;秒位
  3.         fenmi   equ     32h ;分米位
  4.         fmiao   equ     33h ;分秒位
  5.         meter   equ     34h ;米位
  6.         fenzh   equ     35h ;分位
  7.         point   equ     36h ;小數(shù)點(diǎn)位
  8.         shimi   equ     37h ;十米位
  9.         shifn   equ     38h ;十分位

  10.         sudu    equ     39h ;速度控制
  11.         jishk   equ     3ah ;記時開始

  12.         zhond   equ     3bh
  13.         zhodu   equ     3ch
  14.         zhon    equ     3eh
  15.         maicho  equ     3fh
  16.         jinweb  equ     40h
  17.         bhcs    equ     41h

  18.         dpan    equ     42h
  19.         fenchu  equ     43h
  20.         fencun  equ     44h
  21.         pand    equ     45h

  22.         fenmc   equ     51h
  23.         org      0000h
  24.         ajmp     main
  25.         org      000bh
  26.         ajmp     st0
  27.         org      001bh
  28.         ajmp     st1
  29.         org      0100h
  30.    main:
  31.         mov limiw,#00h
  32.         mov miao,#00h
  33.         mov fenmi,#00h
  34.         mov fmiao,#00h
  35.         mov meter,#00h
  36.         mov fenzh,#00h
  37.         mov point,#0bh
  38.         mov shimi,#00h
  39.         mov shifn,#00h
  40.         mov jishk,#00h
  41.         mov zhond,#00h
  42.         mov zhodu,#00h
  43.         mov zhon,#00h
  44.         mov maicho,#00h
  45.         mov jinweb,#03h
  46.         mov bhcs,#00h
  47.         mov sp,#6fh
  48.         mov tmod,#21h
  49.         mov th0,#3ch
  50.         mov tl0,#0b0h
  51.         mov th1,#9ch
  52.         mov tl1,#9ch
  53.         setb ea
  54.         setb et0
  55.         setb et1
  56.         mov p1,#0aah
  57.         acall xianshi
復(fù)制代碼
    二、 顯示子程序設(shè)計
      
     程序清單如下:
  1. xianshi:
  2.         mov p1,#0aah
  3.         mov p1,#0cch
  4.         mov a,limiw
  5.         swap a
  6.         add a,miao
  7.         mov p1,a
  8.         nop
  9.         nop
  10.         mov p1,#0ddh
  11.         mov a,fenmi
  12.         swap a
  13.         add a,fmiao
  14.         mov p1,a
  15.         nop
  16.         nop
  17.         mov p1,#0eeh
  18.         mov a,#0b0h
  19.         add a,point
  20.         mov p1,a
  21.         nop
  22.         nop
  23.         mov p1,#0eeh
  24.         mov a,meter
  25.         swap a
  26.         add a,fenzh
  27.         mov p1,a
  28.         nop
  29.         nop
  30.         mov p1,#0ffh
  31.         mov a,shimi
  32.         swap a
  33.         add a,shifn
  34.         mov p1,a
  35.         ret
復(fù)制代碼

    三 、避障子程序設(shè)計


        程序清單如下:
  1. <font face="黑體">zhangai:
  2.         jb 25h,stop
  3.         jnb 22h,youzhuan
  4.         jnb 23h,youzhuan
  5.         jnb 24h,zuozhuan
  6.         jnb 26h,zuozhuan
  7.         ajmp jiance
  8. zuozhuan:
  9.          clr p0.5
  10.          clr p0.4
  11.          mov sudu,#05h
  12.          acall delaa
  13.          setb p0.4
  14.          setb p0.5
  15.          mov sudu,#07h
  16.          ajmp jiance
  17. youzhuan:
  18.          clr p0.6
  19.          clr p0.7
  20.          mov sudu,#05h
  21.          acall delaa
  22.          setb p0.7
  23.          setb p0.6
  24.          mov sudu,#07h
  25.          ajmp jiance
  26.     stop:
  27.          acall delay
  28.          jnb 25h,zhangai
  29.          clr tr0
  30.          mov a,fenmi
  31.          mov fenmc,a
  32.          mov a,#02h
  33.          add a,fenmc
  34.          mov fenmc,a
  35.    here: cjne a,fenmi,here
  36.          clr tr1
  37.          setb p2.6
  38.          acall delaa
  39.          setb p2.7
  40.          ajmp $
  41. </font>
復(fù)制代碼


    四、 整體程序設(shè)計如下所示:


       程序清單如下:
  1. limiw   equ     30h ;厘米位
  2.         miao    equ     31h ;秒位
  3.         fenmi   equ     32h ;分米位
  4.         fmiao   equ     33h ;分秒位
  5.         meter   equ     34h ;米位
  6.         fenzh   equ     35h ;分位
  7.         point   equ     36h ;小數(shù)點(diǎn)位
  8.         shimi   equ     37h ;十米位
  9.         shifn   equ     38h ;十分位

  10.         sudu    equ     39h ;速度控制
  11.         jishk   equ     3ah ;記時開始

  12.         zhond   equ     3bh
  13.         zhodu   equ     3ch
  14.         zhon    equ     3eh
  15.         maicho  equ     3fh
  16.         jinweb  equ     40h
  17.         bhcs    equ     41h

  18.         dpan    equ     42h
  19.         fenchu  equ     43h
  20.         fencun  equ     44h
  21.         pand    equ     45h

  22.         fenmc   equ     51h
  23.         org      0000h
  24.         ajmp     main
  25.         org      000bh
  26.         ajmp     st0
  27.         org      001bh
  28.         ajmp     st1
  29.         org      0100h
  30.    main:
  31.         mov limiw,#00h
  32.         mov miao,#00h
  33.         mov fenmi,#00h
  34.         mov fmiao,#00h
  35.         mov meter,#00h
  36.         mov fenzh,#00h
  37.         mov point,#0bh
  38.         mov shimi,#00h
  39.         mov shifn,#00h
  40.         mov jishk,#00h
  41.         mov zhond,#00h
  42.         mov zhodu,#00h
  43.         mov zhon,#00h
  44.         mov maicho,#00h
  45.         mov jinweb,#03h
  46.         mov bhcs,#00h
  47.         mov sp,#6fh
  48.         mov tmod,#21h
  49.         mov th0,#3ch
  50.         mov tl0,#0b0h
  51.         mov th1,#9ch
  52.         mov tl1,#9ch
  53.         setb ea
  54.         setb et0
  55.         setb et1
  56.         mov p1,#0aah
  57.         acall xianshi
  58. qidong:
  59.         jb p0.0,qidong
  60.         acall delay
  61.         jb p0.0,qidong
  62.         mov sudu,#03h
  63.         clr p2.6
  64.         clr p2.7
  65.         setb tr1
  66.   start:
  67.         jnb p2.3,start
  68.         acall delay
  69.         jnb p2.3,start
  70.         mov sudu,#07h
  71.         setb tr0
  72.         mov jishk,#01h
  73.         call delaa
  74.         call delaa
  75.         call delaa
  76.         call delaa
  77.         call delaa
  78. jiance:
  79.         mov c,p2.0
  80.         mov 22h,c
  81.         mov c,p2.1
  82.         mov 23h,c
  83.         mov c,p2.2
  84.         mov 24h,c
  85.         mov c,p2.3
  86.         mov 25h,c
  87.         mov c,p2.4
  88.         mov 26h,c
  89. zhangai:
  90.         jb 25h,stop
  91.         jnb 22h,youzhuan
  92.         jnb 23h,youzhuan
  93.         jnb 24h,zuozhuan
  94.         jnb 26h,zuozhuan
  95.         ajmp jiance
  96. zuozhuan:
  97.          clr p0.5
  98.          clr p0.4
  99.          mov sudu,#05h
  100.          acall delaa
  101.          setb p0.4
  102.          setb p0.5
  103.          mov sudu,#07h
  104.          ajmp jiance
  105. youzhuan:
  106.          clr p0.6
  107.          clr p0.7
  108.          mov sudu,#05h
  109.          acall delaa
  110.          setb p0.7
  111.          setb p0.6
  112.          mov sudu,#07h
  113.          ajmp jiance
  114.     stop:
  115.          acall delay
  116.          jnb 25h,zhangai
  117.          clr tr0
  118.          mov a,fenmi
  119.          mov fenmc,a
  120.          mov a,#02h
  121.          add a,fenmc
  122.          mov fenmc,a
  123.    here: cjne a,fenmi,here
  124.          clr tr1
  125.          setb p2.6
  126.          acall delaa
  127.          setb p2.7
  128.          ajmp $
  129.     st0:
  130.         push acc
  131.         push psw
  132.         mov th0,#3ch
  133.         mov tl0,#0b0h
  134.         inc zhond
  135.         mov a,#0ah
  136.         cjne a,zhond,out
  137.         mov zhond,#00h
  138.         inc zhodu
  139.         mov a,#02h
  140.         cjne a,zhodu,miepo
  141.         mov point,#0bh
  142.         mov zhodu,#00h
  143.         inc miao
  144.         mov a,#0ah
  145.         cjne a,miao,out
  146.         mov miao,#00h
  147.         inc fmiao
  148.         mov a,#06h
  149.         cjne a,fmiao,out
  150.         mov fmiao,#00h
  151.         inc fenzh
  152.         mov a,#0ah
  153.         cjne a,fenzh,out
  154.         mov fenzh,#00h
  155.         inc shifn
  156.     out:
  157.         call xianshi
  158.    outb:
  159.         pop psw
  160.         pop acc
  161.         reti
  162.   miepo:
  163.         mov point,#0ah
  164.         ajmp out
  165.     st1:
  166.         push acc
  167.         push psw
  168.         inc zhon
  169.         mov a,sudu
  170.         cjne a,zhon,hig
  171.         setb p2.7
  172.         ajmp outi
  173.     hig:
  174.         mov a,#0ah
  175.         cjne a,zhon,outi
  176.         mov zhon,#00h
  177.         clr p2.7
  178.     outi:
  179.         mov a,#01h
  180.         cjne a,jishk,outb
  181.         jb p2.5,gao
  182.         mov c,p2.5
  183.         mov 21h,c
  184.         orl c,20h
  185.         clr 20h
  186.         jc  youbh
  187.         ajmp outb
  188.     gao:
  189.         setb 20h
  190.         ajmp outb
  191.   youbh:
  192.         inc maicho
  193.         mov a,jinweb
  194.         cjne a,maicho,outb
  195.         mov maicho,#00h
  196.         inc bhcs
  197.         mov a,#02h
  198.         cjne a,bhcs,jici
  199.         mov jinweb,#03h
  200.    goon:inc limiw
  201.         mov a,#0ah
  202.         cjne a,limiw,out
  203.         mov limiw,#00h
  204.         inc fenmi
  205.         cjne a,fenmi,out
  206.         mov fenmi,#00h
  207.         inc meter
  208.         cjne a,meter,out
  209.         mov meter,#00h
  210.         inc shimi
  211.         ajmp out
  212.    jici:
  213.         mov jinweb,#02h
  214.         ajmp goon
  215. xianshi:
  216.         mov p1,#0aah
  217.         mov p1,#0cch
  218.         mov a,limiw
  219.         swap a
  220.         add a,miao
  221.         mov p1,a
  222.         nop
  223.         nop
  224.         mov p1,#0ddh
  225.         mov a,fenmi
  226.         swap a
  227.         add a,fmiao
  228.         mov p1,a
  229.         nop
  230.         nop
  231.         mov p1,#0eeh
  232.         mov a,#0b0h
  233.         add a,point
  234.         mov p1,a
  235.         nop
  236.         nop
  237.         mov p1,#0eeh
  238.         mov a,meter
  239.         swap a
  240.         add a,fenzh
  241.         mov p1,a
  242.         nop
  243.         nop
  244.         mov p1,#0ffh
  245.         mov a,shimi
  246.         swap a
  247.         add a,shifn
  248.         mov p1,a
  249.         ret
  250.   delay:
  251.         mov 46h,#0ffh
  252.         mov 47h,#0ffh
  253.       i:djnz 47h,i1
  254.      i1:djnz 46h,i
  255.         ret
  256. delaa:
  257.        mov 48h,#0ah
  258.     ii:mov 49h,#0afh
  259.     ii2:mov 50h,#0ffh
  260.     ii3:djnz 50h,ii3
  261.         djnz 49h,ii2
  262.         djnz 48h,ii
  263.         ret
復(fù)制代碼


   五、軟件抗干擾技術(shù)
    提高玩具車智能控制的可靠性,僅靠硬件抗干擾是不夠的,需要進(jìn)一步借助于軟件抗干擾技術(shù)來克服某些干擾。在單片機(jī)控制系統(tǒng)中,如能正確的采用軟件抗干擾技術(shù),與硬件干擾措施構(gòu)成雙道抗干擾防線,無疑為了將大大提高控制系統(tǒng)的可靠性。經(jīng)常采用的軟件抗干擾技術(shù)是數(shù)字濾波技術(shù)、開關(guān)量的軟件抗干擾技術(shù)、指令冗余技術(shù)、軟件陷阱技術(shù)等。
    1、數(shù)字濾波技術(shù):
     一般單片機(jī)應(yīng)用系統(tǒng)的模擬輸入信號中,均含有種種噪音和干擾,它們來自被測量本身、傳感器、外界干擾等。為了進(jìn)行準(zhǔn)確測量和控制,必須消除被測信號中的噪音和干擾。對于這類信號,采用積分時間等于20ms的整數(shù)倍的雙積分A/D轉(zhuǎn)換器,可有效的消除其影響。后者為隨機(jī)信號,它不是周期信號。對于隨機(jī)干擾,我們可以用數(shù)字濾波方法予以削弱或濾除。所謂數(shù)字濾波,就是通過一定的計算或判斷程序減少干擾在有用信號中的比重。故實(shí)質(zhì)上它是一種程序濾波。數(shù)字濾波克服了模擬濾波器的不足,它與模擬濾波器相比 ,有以下幾個優(yōu)點(diǎn):
  • 數(shù)字濾波是用程序?qū)崿F(xiàn)的,不需要增加硬設(shè)備,所以可靠性高,穩(wěn)定性好。
  • 數(shù)字濾波可以根據(jù)信號的不同,采用不同的濾波方法或濾波參數(shù),具有靈活、方便,功能強(qiáng)的特點(diǎn)。
  • 數(shù)字濾波可以對頻率很低的信號實(shí)現(xiàn)濾波,克服了模擬濾波器的缺陷。
  • 數(shù)字濾波器具有以上優(yōu)點(diǎn),所以數(shù)字濾波在微機(jī)應(yīng)用系統(tǒng)中得到了廣泛應(yīng)用。

    2、開關(guān)量的軟件抗干擾技術(shù):
    干擾信號多呈毛刺狀,作用時間短,利用這一點(diǎn),我們在采集某一開關(guān)量信號時,可多次重復(fù)采集,直到連續(xù)兩次或兩次以上結(jié)果完全一致方為有效。若多次采樣后,信號總是變化不定,可停止采集,給出報警信號,由于開關(guān)量信號主要是來自各類開
關(guān)型狀態(tài)傳感器,如限位開關(guān)、操作按鈕、電氣觸點(diǎn)等,對這些信號的采集不能用多次平均的方法,必須絕對一致才行。如果開關(guān)量信號超過8個,可按8個一組進(jìn)行分組處理,也可定義多字節(jié)信息暫存區(qū),按類似方法處理。在滿足實(shí)時性要求的前提下,如果在各次采集數(shù)字信號之間接入一段延時,效果會好一些,就能對抗較寬的干擾。
    輸出設(shè)備是電位控制型還是同步鎖存型,對干擾的敏感性相對較大。前者有良好的抗‘毛刺’干擾能力,后者不耐干擾,當(dāng)鎖存線上出現(xiàn)干擾時,它就會盲目鎖存當(dāng)前的數(shù)據(jù),也不管此時數(shù)據(jù)是否有效。輸出設(shè)備和慣性(響應(yīng)速度)與干擾的耐受能力也有很大關(guān)系。慣性大的輸出設(shè)備(如各類電磁執(zhí)行機(jī)構(gòu))對‘毛刺’干擾有一定的耐受能力。慣性小的輸出設(shè)備(如通行口、顯示設(shè)備)耐受能力就小一些。在軟件上,最為有效的方法就是重復(fù)輸出同一個數(shù)據(jù)。只要有可能,其重復(fù)周期盡可能短些。外設(shè)設(shè)備接受到一個被干擾的錯誤信息后,還來不及作出有效的反應(yīng),一個正確的信息又來了,就可及時防止錯誤動作的產(chǎn)生。另外,各類數(shù)據(jù)鎖存器盡可能和CPU安裝在同一電路板上,使傳輸線上傳送的都是鎖存好的電位控制信號,對于重要的輸出設(shè)備,最好建立檢測通道,CPU可以檢測通道來確定輸出結(jié)果的正確性。
    3、指令冗余技術(shù):
當(dāng)CPU受到干擾后,往往將一些操作數(shù)當(dāng)作指令碼來執(zhí)行,引起程序混亂。當(dāng)程序彈飛到某一字節(jié)指令上時,便自動納入正軌。當(dāng)彈飛到某一雙字節(jié)指令上時,有可能落到其操作數(shù)上,從而繼續(xù)出錯。當(dāng)程序彈飛到三字節(jié)指令上時,因它有兩個操作數(shù),繼續(xù)出錯的機(jī)會就更大。因此,我們應(yīng)多采用單字節(jié)指令(NOP)或?qū)巫止?jié)指令重復(fù)書寫,這便是指令冗余。指令冗余無疑會降低系統(tǒng)的效率,但在絕大多數(shù)情況下,CPU還不至于忙到不能多執(zhí)行幾條指令的程度,故這種方法還是被廣泛采用。
在一些對程序流向起決定作用的指令之前插入兩條NOP指令,以保證彈飛的程序迅速納入正確軌道。在某些對系統(tǒng)工作狀態(tài)重要的指令前也可插入兩條NOP指令,以保證正確執(zhí)行。指令冗余技術(shù)可以減少程序彈飛的次數(shù),使其很快進(jìn)入程序軌道,但這并不能保證在失控期間不干壞事,更不能保證程序納入正常軌道后就太平無事了,解決這個問題必須采用軟件容錯技術(shù)。
    4﹑軟件陷阱技術(shù):
指令冗余使彈飛的程序安定下來是有條件的。首先,彈飛的程序必須落到程序區(qū);其次,必須執(zhí)行到冗余指令。所謂軟件陷阱,就是一套引導(dǎo)指令,強(qiáng)行將捕獲的程序引向一個指定的地址,在那里有一段專門對程序出錯進(jìn)行處理的程序。如果我們把這段程序的入口標(biāo)號記為 ERR 的話,軟件陷阱即為一條無條件轉(zhuǎn)移指令,為了加強(qiáng)其捕捉效果,一般還在它前面加兩條 NOP 指令,因此真正的軟件陷阱由3條指令構(gòu)成:                           
  1. NOP
  2. NOP
  3. ERR
復(fù)制代碼
   軟件陷阱安排在以下四種地方:

    (1)未使用的中斷向量區(qū)。
    (2)未使用的大片ROM空間
    (3)表格

    5、程序區(qū)
    由于軟件陷阱都安排在正常程序執(zhí)行不到的地方,故不影響程序執(zhí)行效率,在當(dāng)前EPROM容量不成問題的條件下,還是多多益善。


   六 、看門狗技術(shù)
    PC受到干擾而失控,引起程序亂飛,也可能使程序陷入“死循環(huán)” [6]。指令技術(shù)、軟件陷阱技術(shù)不能使失控的程序擺脫“死循環(huán)”的困境,這時系統(tǒng)完全癱瘓。如果操作者在場,就可以按下人工復(fù)位安鈕,強(qiáng)制系統(tǒng)復(fù)位。但操作者不能一直監(jiān)視著系統(tǒng),也往往是在引起不良后果之后才進(jìn)行人工復(fù)位。為使程序脫離“死循環(huán)”,通常采用“看門狗技術(shù)”!翱撮T狗”技術(shù)就是不斷監(jiān)視程序循環(huán)運(yùn)行時間,若發(fā)現(xiàn)時間超過已知的循環(huán)設(shè)定時間,則認(rèn)為系統(tǒng)陷入了“死循環(huán)”,然后強(qiáng)迫程序返回到0000H入口,在0000H處安排一段出錯處理程序,使系統(tǒng)運(yùn)行納入正規(guī)。
   “看門狗”技術(shù)可由硬件實(shí)現(xiàn),可由軟件實(shí)現(xiàn),也可由兩者結(jié)合實(shí)現(xiàn)。本系統(tǒng)采用硬件“看門狗”電路。
    實(shí)現(xiàn)硬件“看門狗”電路方案較多,目前采用較多的方案有以下幾種:
  • 采用微處理器監(jiān)控器;
  • 采用單穩(wěn)態(tài)電路來實(shí)現(xiàn)“看門狗”,單穩(wěn)定電路可采用74LS123;
  • 采用內(nèi)帶震蕩器的記數(shù)芯片。

     本設(shè)計采用第三種方案實(shí)現(xiàn)“看門狗”電路,下面就對該方案作以介紹。
    (1)基本原理
    CD4060 是帶震蕩器的14位計數(shù)器,由該芯片構(gòu)成的看門狗電路4060記數(shù)頻率由RT和CT決定。設(shè)實(shí)際的程序所需工作周期為T,分頻器記滿時間為T’,當(dāng)T’>T 且系統(tǒng)正常工作時,程序每隔T對4060進(jìn)行掃描一次,分頻且永無記滿輸出信號。如系統(tǒng)工作不正常(如程序跑飛、死循環(huán)等),程序?qū)?060發(fā)不出掃描信號,分頻器記滿輸出一脈沖號使CPU復(fù)位。
    (2)參數(shù)選擇
    4060的振蕩頻率f由 RT 、CT決定。Rs用于改善振蕩器的穩(wěn)定性,Rs 要大于RT。一般取Rs=10RT,且RT>1kΩ,CT≥100pF。如果Rs=450Ω,RT=45Ω,CT=1uF,則f=10HZ。4060的振蕩頻率和Qi(i=6,7,8,9,10,12,13,14)的選擇要根據(jù)情況確定。
    (3)幾個原則
    看門狗電路必須由硬件邏輯組成,不宜由可編程計數(shù)器充當(dāng),因為CPU失控后,可能會修改可編程器件參數(shù),使看門狗失效。4060的RST線上阻容組成的微分電路很重要,因為掃描輸入信號是CPU產(chǎn)生的正脈沖,若此信號變“1”后,由于干擾,程序亂飛,微分電路只能讓上跳沿通過,不會封死4060,看門狗仍能計數(shù)起作用。若沒有微分電路,掃描輸入信號上的“1”狀態(tài)封死4060,使之不能記數(shù),看門狗不起作用。CPU必須在正確完成所有工作后才能發(fā)掃描輸入信號,且程序中發(fā)掃描信號的地方不能太多。否則,正好在哪里有死循環(huán),看門狗就不產(chǎn)生記滿輸出信號,不能重新啟動CPU。4060的記滿輸出信號不但要接到MCS-51的RST腳,而且還應(yīng)接到其它芯片的RST腳,因為程序亂飛后,其它具有RST腳的芯片也混亂了,必須全部復(fù)位。


   六、可編程邏輯器件
    可編程邏輯器件GAL16V8是LATTICE公司研制的一種電可擦除的可重復(fù)編程的低密度PLD器件。它采用更為靈活的可編I/O結(jié)構(gòu),并采用了先進(jìn)的EECOMS工藝,數(shù)秒內(nèi)即可完成芯片的擦除和編程過程,并可反復(fù)改寫,是產(chǎn)品開發(fā)研制的理想器件之一。
GAL16V8技術(shù)特性
(1)電可擦除工藝     
      可重編程單元
      100%成品率
      可重配置邏輯
(2)高性能E2CMOS工藝      
     低功耗:45mA最大運(yùn)行功耗,35mA最大維持功耗
     高速度:15~25us最快存取速度
(3)8個輸出邏輯單元
     對于復(fù)雜邏輯設(shè)計具有最大靈活性,GAL16V8可仿真20條引腳的PAL器件,具有功能 / 熔絲圖 /參數(shù)的完全兼容性
(4)預(yù)置、加電復(fù)位全部寄存器
(5)具有保密單元、電子標(biāo)簽
(6)數(shù)據(jù)保持超過20年。


  80C51按鍵電路直接由80C51接口電路查詢。消抖(延時20ms)由軟件延時完成。






實(shí)現(xiàn)電壓測量、頻率測量與實(shí)時時鐘功能的程序如下:(顯示和操作通過矩陣鍵盤實(shí)現(xiàn))

  1. #include "STC15.h"
  2. #include <intrins.h>

  3. sbit SCK=P1^7;               
  4. sbit SDA=P2^3;               
  5. sbit RST = P1^3;   // DS1302復(fù)位                                                                                                

  6. void Write_Ds1302_Byte(unsigned  char temp)
  7. {
  8.         unsigned char i;
  9.         for (i=0;i<8;i++)            
  10.         {
  11.                 SCK=0;
  12.                 SDA=temp&0x01;
  13.                 temp>>=1;
  14.                 SCK=1;
  15.         }
  16. }   

  17. void Write_Ds1302( unsigned char address,unsigned char dat )     
  18. {
  19.          RST=0;
  20.         _nop_();
  21.          SCK=0;
  22.         _nop_();
  23.          RST=1;        
  24.            _nop_();  
  25.          Write_Ds1302_Byte(address);        
  26.          Write_Ds1302_Byte(dat);               
  27.          RST=0;
  28. }

  29. unsigned char Read_Ds1302 ( unsigned char address )
  30. {
  31.          unsigned char i,temp=0x00;
  32.          RST=0;
  33.         _nop_();
  34.          SCK=0;
  35.         _nop_();
  36.          RST=1;
  37.         _nop_();
  38.          Write_Ds1302_Byte(address);
  39.          for (i=0;i<8;i++)         
  40.          {               
  41.                 SCK=0;
  42.                 temp>>=1;        
  43.                  if(SDA)
  44.                  temp|=0x80;        
  45.                  SCK=1;
  46.         }
  47.          RST=0;
  48.         _nop_();
  49.          RST=0;
  50.         SCK=0;
  51.         _nop_();
  52.         SCK=1;
  53.         _nop_();
  54.         SDA=0;
  55.         _nop_();
  56.         SDA=1;
  57.         _nop_();
  58.         return (temp);                        
  59. }
復(fù)制代碼
  1. #include "STC15.h"
  2. #include "intrins.h"

  3. #define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}   


  4. #define SlaveAddrW 0xA0
  5. #define SlaveAddrR 0xA1

  6. //總線引腳定義
  7. sbit SDA = P2^1;  /* 數(shù)據(jù)線 */
  8. sbit SCL = P2^0;  /* 時鐘線 */


  9. //總線啟動條件
  10. void IIC_Start(void)
  11. {
  12.         SDA = 1;
  13.         SCL = 1;
  14.         somenop;
  15.         SDA = 0;
  16.         somenop;
  17.         SCL = 0;        
  18. }

  19. //總線停止條件
  20. void IIC_Stop(void)
  21. {
  22.         SDA = 0;
  23.         SCL = 1;
  24.         somenop;
  25.         SDA = 1;
  26. }

  27. //應(yīng)答位控制
  28. void IIC_Ack(bit ackbit)
  29. {
  30.         if(ackbit)
  31.         {        
  32.                 SDA = 0;
  33.         }
  34.         else
  35.         {
  36.                 SDA = 1;
  37.         }
  38.         somenop;
  39.         SCL = 1;
  40.         somenop;
  41.         SCL = 0;
  42.         SDA = 1;
  43.         somenop;
  44. }

  45. //等待應(yīng)答
  46. bit IIC_WaitAck(void)
  47. {
  48.         SDA = 1;
  49.         somenop;
  50.         SCL = 1;
  51.         somenop;
  52.         if(SDA)   
  53.         {   
  54.                 SCL = 0;
  55.                 IIC_Stop();
  56.                 return 0;
  57.         }
  58.         else  
  59.         {
  60.                 SCL = 0;
  61.                 return 1;
  62.         }
  63. }

  64. //通過I2C總線發(fā)送數(shù)據(jù)
  65. void IIC_SendByte(unsigned char byt)
  66. {
  67.         unsigned char i;
  68.         for(i=0;i<8;i++)
  69.         {   
  70.                 if(byt&0x80)
  71.                 {        
  72.                         SDA = 1;
  73.                 }
  74.                 else
  75.                 {
  76.                         SDA = 0;
  77.                 }
  78.                 somenop;
  79.                 SCL = 1;
  80.                 byt <<= 1;
  81.                 somenop;
  82.                 SCL = 0;
  83.         }
  84. }

  85. //從I2C總線上接收數(shù)據(jù)
  86. unsigned char IIC_RecByte(void)
  87. {
  88.         unsigned char da;
  89.         unsigned char i;
  90.         
  91.         for(i=0;i<8;i++)
  92.         {   
  93.                 SCL = 1;
  94.                 somenop;
  95.                 da <<= 1;
  96.                 if(SDA)
  97.                 da |= 0x01;
  98.                 SCL = 0;
  99.                 somenop;
  100.         }
  101.         return da;
  102. }
復(fù)制代碼
  1. #include "STC15.h"
  2. #include "ds1302.h"
  3. #include "iic.h"
  4. #include "intrins.h"
  5. typedef     unsigned char   u8;
  6. typedef     unsigned int    u16;
  7. typedef     unsigned long   u32;

  8. u8 e_write_flag=0;
  9. u8 mode=0;
  10. u8 code t_display[]={                       //標(biāo)準(zhǔn)字庫
  11. //   0    1    2    3    4    5    6    7    8    9           -
  12.     0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};

  13. void Delay1ms()                //@11.0592MHz
  14. {
  15.         unsigned char i, j;

  16.         _nop_();
  17.         _nop_();
  18.         _nop_();
  19.         i = 11;
  20.         j = 190;
  21.         do
  22.         {
  23.                 while (--j);
  24.         } while (--i);
  25. }

  26. void delay_ms(u16 i)
  27. {
  28.         while(i--)
  29.                 Delay1ms();
  30. }

  31. void dis_num(u8 x,u8 num)  //數(shù)碼管顯示
  32. {
  33.         P0=0X01<<x;
  34.         P2=0XC0;
  35.         P2=0X00;
  36.         P0=~t_display[num];
  37.         P2=0XE0;
  38.         Delay1ms();
  39.         P0=0XFF;
  40.         P2=0X00;
  41. }

  42. u8 ad()                //AD采集
  43. {
  44.         u8 i;
  45.         IIC_Start();
  46.         IIC_SendByte(0x90);
  47.         IIC_WaitAck();
  48.         IIC_SendByte(0x03);
  49.         IIC_WaitAck();
  50.         IIC_Start();
  51.         IIC_SendByte(0x91);
  52.         IIC_WaitAck();
  53.         i=IIC_RecByte();
  54.         IIC_Stop();                                                                                                                                                                                          
  55.         return i;
  56. }

  57. void DS1302_Init()         //1302初始化
  58. {
  59.         Write_Ds1302(0x8e,0x00);
  60.         Write_Ds1302(0x80,0x55);
  61.         Write_Ds1302(0x82,0x59);
  62.         Write_Ds1302(0x84,0x23);
  63.         Write_Ds1302(0x8e,0x80);
  64. }

  65. void show_time()          //顯示時間
  66. {
  67.         u8 i;
  68.         i=Read_Ds1302(0x85);
  69.         dis_num(0,(i&0xf0)>>4);
  70.         dis_num(1,(i&0x0f));
  71.         dis_num(2,10);
  72.         i=Read_Ds1302(0x83);
  73.         dis_num(3,(i&0xf0)>>4);
  74.         dis_num(4,(i&0x0f));
  75.         dis_num(5,10);
  76.         i=Read_Ds1302(0x81);
  77.         dis_num(6,(i&0xf0)>>4);
  78.         dis_num(7,(i&0x0f));
  79. }

  80. void write_eeprom(u8 adr,u8 dat)   //寫入EEPROM
  81. {
  82.         IIC_Start();
  83.         IIC_SendByte(0xa0);
  84.         IIC_WaitAck();
  85.         IIC_SendByte(adr);
  86.         IIC_WaitAck();
  87.         IIC_SendByte(dat);
  88.         IIC_WaitAck();
  89.         IIC_Stop();                                                                                                                                                                          
  90. }

  91. u8 read_eeprom(u8 adr)           //讀取EEPROM
  92. {
  93.         u8 i;
  94.         IIC_Start();
  95.         IIC_SendByte(0xa0);
  96.         IIC_WaitAck();
  97.         IIC_SendByte(adr);
  98.         IIC_WaitAck();
  99.         IIC_Start();
  100.         IIC_SendByte(0xa1);
  101.         IIC_WaitAck();
  102.         i=IIC_RecByte();
  103.         IIC_Stop();                                                                                                                                                                                          
  104.         return i;
  105. }

  106. u8 scan_key()        //按鍵掃描
  107. {
  108.         u8 key,i;
  109.         for(i=0;i<2;i++)
  110.         {        
  111.                 P3|=0X0F;
  112.                 switch(i)
  113.                 {
  114.                         case 0:{P44=0;P42=1;}break;
  115.                         case 1:{P44=1;P42=0;}break;
  116.                 }
  117.                 key=P3&0X0F;
  118.                 if(key!=0x0f)
  119.                 {
  120.                         delay_ms(30);
  121.                         key=P3&0X0F;
  122.                         if(key!=0x0f)
  123.                         {
  124.                                 while((P3&0X0F)!=0X0F);
  125.                                 switch(key)
  126.                                 {
  127.                                         case 0x0e:return i*4+7;break;
  128.                                         case 0x0d:return i*4+6;break;
  129.                                         case 0x0b:return i*4+5;break;
  130.                                         case 0x07:return i*4+4;break;
  131.                                 }
  132.                         }
  133.                 }
  134.         }
  135.         return 0;
  136. }

  137. void Time0_Init()
  138. {
  139.         AUXR = 0x80;                    //定時器0為1T模式
  140.     TMOD = 0x04;                    //設(shè)置定時器0為16位自動重裝載外部記數(shù)模式
  141.     TH0 = TL0 = 0xff;               //設(shè)置定時器0初始值
  142.     TR0 = 0;                        //定時器0開始工作
  143.     ET0 = 1;                        //開定時器0中斷
  144. }

  145. void Timer1Init(void)                //50毫秒@11.0592MHz
  146. {
  147.         AUXR &= 0xBF;                //定時器時鐘12T模式
  148.         TMOD &= 0x0F;                //設(shè)置定時器模式
  149.         TL1 = 0x00;                //設(shè)置定時初值
  150.         TH1 = 0x4C;                //設(shè)置定時初值
  151.         TF1 = 0;                //清除TF1標(biāo)志
  152.         TR1 = 0;                //定時器1開始計時
  153.         ET1 = 1;
  154. }

  155. void Timer2Init(void)                //50毫秒@11.0592MHz
  156. {
  157.         AUXR &= 0xFB;                //定時器時鐘12T模式
  158.         T2L = 0x00;                //設(shè)置定時初值
  159.         T2H = 0x4C;                //設(shè)置定時初值
  160.         IE2  |=  (1<<2);    //允許中斷
  161.         AUXR |= 0x10;                //定時器2開始計時
  162.         IE2 |= 0x04;                    //開定時器2中斷
  163. }

  164. //調(diào)整時間
  165. bit change_time()
  166. {
  167.         u8 x,k,temp_0,temp_1,show_flag;
  168.         u8 time[3]={0};
  169.         x=Read_Ds1302(0x85);
  170.         time[0]=((x&0xf0)>>4)*10+(x&0x0f);
  171.         x=Read_Ds1302(0x83);
  172.         time[1]=((x&0xf0)>>4)*10+(x&0x0f);
  173.         x=Read_Ds1302(0x81);
  174.         temp_0=x;
  175.         time[2]=((x&0xf0)>>4)*10+(x&0x0f);
  176.         x=0;
  177.         show_flag=1;
  178.         while(1)
  179.         {
  180.                 if(show_flag)
  181.                 {
  182.                         dis_num(x*3,time[x]/10);
  183.                         dis_num(x*3+1,time[x]%10);
  184.                 }
  185.                 switch(x)
  186.                 {
  187.                 case 0:{dis_num(2,10);dis_num(3,time[1]/10);dis_num(4,time[1]%10);dis_num(5,10);dis_num(6,time[2]/10);dis_num(7,time[2]%10);}break;
  188.                 case 1:{dis_num(0,time[0]/10);dis_num(1,time[0]%10);dis_num(2,10);dis_num(5,10);dis_num(6,time[2]/10);dis_num(7,time[2]%10);}break;
  189.                 case 2:{dis_num(0,time[0]/10);dis_num(1,time[0]%10);dis_num(2,10);dis_num(3,time[1]/10);dis_num(4,time[1]%10);dis_num(5,10);}break;
  190.                 }
  191.                 k=scan_key();
  192.                 if(k==7)
  193.                 {
  194.                         Write_Ds1302(0x8e,0x00);
  195.                         Write_Ds1302(0x80,(((time[2]/10)<<4)|(time[2]%10)));
  196.                         Write_Ds1302(0x82,(((time[1]/10)<<4)|(time[1]%10)));
  197.                         Write_Ds1302(0x84,(((time[0]/10)<<4)|(time[0]%10)));
  198.                         Write_Ds1302(0x8e,0x80);
  199.                         return 0;
  200.                 }
  201.                 if(k!=0)
  202.                 {
  203.                         switch(k)
  204.                         {
  205.                                 case 4:{x++;if(x==3)x=0;}break;
  206.                                 case 11:{time[x]++;if(time[x]>59)time[x]=0;}break;
  207.                                 case 10:{if((x!=0)&(time[x]==0))time[x]=60;if((x==0)&(time[x]==0))time[x]=13;time[x]--;}break;
  208.                         }
  209.                 }
  210.                 temp_1=Read_Ds1302(0x81);
  211.                 if(temp_1!=temp_0)
  212.                 {
  213.                         temp_0=temp_1;
  214.                         show_flag=!show_flag;
  215.                 }
  216.                         
  217.         }
  218. }

  219. bit menu_1()//顯示時間和設(shè)置時間                                
  220. {
  221.         u8 k,x;
  222.         x=0;
  223.         while(1)
  224.         {
  225.                 show_time();
  226.                 k=scan_key();
  227.                 if(k==4)
  228.                 {
  229.                         change_time();
  230.                 }
  231.                 switch(k)
  232.                 {
  233.                 case 6:{mode=1;return 1;}break;
  234.                 case 5:{mode=2;return 1;}break;
  235.                 case 9:{mode=3;return 1;}break;
  236.                 }
  237.         }
  238. }

  239. u8 V[2]={0,0};

  240. bit change_V() //修改電壓上下限
  241. {
  242.         u8 k,x,show_flag,temp_0,temp_1;
  243.         x=0;
  244.         show_flag=1;
  245.         temp_0=Read_Ds1302(0x81);
  246.         while(1)
  247.         {
  248.                 if(show_flag)
  249.                 {
  250.                         if(x)
  251.                         {
  252.                                 dis_num(4,V[1]/10);
  253.                                 dis_num(5,V[1]%10);
  254.                                 dis_num(6,0);
  255.                                 dis_num(7,0);
  256.                         }
  257.                         else
  258.                         {
  259.                                 dis_num(0,V[0]/10);
  260.                                 dis_num(1,V[0]%10);
  261.                                 dis_num(2,0);
  262.                                 dis_num(3,0);
  263.                         }
  264.                 }
  265.                 if(x)
  266.                 {
  267.                         dis_num(0,V[0]/10);
  268.                         dis_num(1,V[0]%10);
  269.                         dis_num(2,0);
  270.                         dis_num(3,0);
  271.                 }
  272.                 else
  273.                 {
  274.                         dis_num(4,V[1]/10);
  275.                         dis_num(5,V[1]%10);
  276.                         dis_num(6,0);
  277.                         dis_num(7,0);
  278.                 }

  279.                 k=scan_key();

  280.                 temp_1=Read_Ds1302(0x81);
  281.                 if(temp_1!=temp_0)
  282.                 {
  283.                         temp_0=temp_1;
  284.                         show_flag=!show_flag;
  285.                 }

  286.                 if(k!=0)
  287.                 {
  288.                         switch(k)
  289.                         {
  290.                         case 4:{x++;if(x==2)x=0;}break;
  291.                         case 11:{
  292.                                         if((x==1)&(V[0]>V[1])&(V[1]<95))
  293.                                                 V[x]+=5;
  294.                                         if((x==0)&(V[0]<95))
  295.                                                 V[x]+=5;
  296.                                         }break;
  297.                         case 10:{
  298.                                         if((x==0)&(V[0]>V[1])&(V[0]>4))
  299.                                                 V[x]-=5;
  300.                                         if((x==1)&(V[1]>4))
  301.                                                 V[x]-=5;
  302.                                         }break;
  303.                         }
  304.                 }
  305.                 if(k==6)
  306.                 {
  307.                         write_eeprom(0,V[0]);
  308.                         delay_ms(50);
  309.                         write_eeprom(1,V[1]);        
  310.                         return 1;                 
  311.                 }
  312.         }
  313. }

  314. bit menu_2() //顯示電壓
  315. {
  316.         u16 i;
  317.         u8 k;
  318.         while(1)
  319.         {
  320.                 dis_num(0,10);
  321.                 dis_num(1,1);
  322.                 dis_num(2,10);
  323.                 i=ad();
  324.                 i=(u16)((float)i*19.6+0.5);
  325.                 dis_num(4,i/1000);
  326.                 dis_num(5,i%1000/100);
  327.                 dis_num(6,i%100/10);
  328.                 dis_num(7,i%10);
  329.                 k=scan_key();
  330.                 if(k==4)
  331.                 {
  332.                         change_V();
  333.                 }
  334.                 switch(k)
  335.                 {
  336.                 case 7:{mode=0;return 1;}break;
  337.                 case 5:{mode=2;return 1;}break;
  338.                 case 9:{mode=3;return 1;}break;
  339.                 }
  340.         }

  341. }

  342. u16 timer=0;
  343. u16 zhouqi=0;
  344. u16 c_flag=0;
  345. u8 over_flag=0;

  346. bit menu_3() //頻率周期顯示
  347. {
  348.         u8 k,ft=0;
  349.         u16        f,t;
  350.         EA=1;
  351.         TR0=1;
  352.         TR1=1;
  353.         while(1)
  354.         {
  355.                 dis_num(0,10);
  356.                 dis_num(1,2);
  357.                 dis_num(2,10);
  358.         
  359.                 if(over_flag)
  360.                 {        
  361.                         ET0=1;
  362.                         TR0=1;
  363.                         TR1=1;
  364.                         over_flag=0;
  365.                         f=c_flag*10;
  366.                         c_flag=0;
  367.                         
  368.                 }
  369.                 k= scan_key();
  370.                 if(k==4)
  371.                         ft=!ft;
  372.                 switch(k)
  373.                 {
  374.                 case 7:{mode=0;return 1;}break;
  375.                 case 6:{mode=1;return 1;}break;
  376.                 case 9:{mode=3;return 1;}break;
  377.                 }
  378.                 if(ft)          //f
  379.                 {               
  380.                         dis_num(3,f/10000);
  381.                         dis_num(4,f%10000/1000);
  382.                         dis_num(5,f%10000%1000/100);
  383.                         dis_num(6,f%100/10);
  384.                         dis_num(7,f%10);        
  385.                 }
  386.                 else
  387.                 {
  388.                         t=1000000/f;
  389.                         dis_num(3,t/10000);
  390.                         dis_num(4,t%10000/1000);
  391.                         dis_num(5,t%10000%1000/100);
  392.                         dis_num(6,t%100/10);
  393.                         dis_num(7,t%10);
  394.                 }
  395.         }        
  396. }


  397. bit menu_4()        //查詢
  398. {
  399.         u8 k;
  400.         while(1)
  401.         {
  402.                 dis_num(6,0);
  403.                 dis_num(7,read_eeprom(2));
  404.                 k= scan_key();
  405.                 if(k==4)
  406.                 {
  407.                         k=0;
  408.                         while(1)
  409.                         {
  410.                                 dis_num(0,read_eeprom(3)/10);
  411.                                 dis_num(1,read_eeprom(3)%10);
  412.                                 dis_num(2,10);
  413.                                 dis_num(3,read_eeprom(4)/10);
  414.                                 dis_num(4,read_eeprom(4)%10);
  415.                                 dis_num(5,10);
  416.                                 dis_num(6,read_eeprom(5)/10);
  417.                                 dis_num(7,read_eeprom(5)%10);
  418.                                 k=scan_key();
  419.                                 if((k==7)|(k==6)|(k==5)|(k==4))
  420.                                         break;        
  421.                         }
  422.                 }

  423.                 switch(k)
  424.                 {
  425.                 case 7:{mode=0;return 1;}break;
  426.                 case 6:{mode=1;return 1;}break;
  427.                 case 5:{mode=2;return 1;}break;
  428.                 }
  429.                         
  430.         }
  431. }

  432. void main()
  433. {
  434.         u16 i,j;
  435.         P0=0X00;
  436.         P2=0XA0;
  437.         P2=0X00;
  438.         P0=0XFF;
  439.         P2=0X80;
  440.         P2=0X00;
  441.         V[0]=read_eeprom(0);
  442.         delay_ms(10);
  443.         V[1]=read_eeprom(1);
  444.         DS1302_Init();
  445.         Time0_Init();
  446.         Timer1Init();
  447.         Timer2Init();
  448.         EA=1;
  449.         while(1)
  450.         {
  451.                 switch(mode)
  452.                 {
  453.                         case 0:menu_1();break;        //shijian
  454.                         case 1:menu_2();break;        //dianya
  455.                         case 2:menu_3();break;        //zhouqi
  456.                         case 3:menu_4();break;        //chaxun
  457.                 }
  458.         }
  459. }
  460. //中斷服務(wù)程序
  461. void t0int() interrupt 1            //中斷入口
  462. {
  463.         c_flag++;        
  464. }
  465. bit t1_c=0;

  466. void t1int() interrupt 3
  467. {
  468.         if(t1_c==0)
  469.                 t1_c=1;
  470.         else
  471.         {
  472.                 t1_c=0;
  473.                 ET0=0;
  474.                 TR0=0;
  475.                 TR1=0;
  476.                 over_flag=1;
  477.         }
  478. }

  479. u8 t2_flag=0;
  480. void timer2_int (void) interrupt 12        //50ms *100  5s
  481. {
  482.         u16 i;
  483.         t2_flag++;
  484.         if(t2_flag>=100)
  485.         {
  486.                 t2_flag=0;
  487.                
  488.             i=ad();
  489.                 i=(u16)((float)i*19.6+0.5);
  490.                 if(i>V[0]*100)
  491.                 {
  492.                         write_eeprom(2,1);
  493.                         delay_ms(8);
  494.                         i=Read_Ds1302(0x85);
  495.                         i=((i&0xf0)>>4)*10+i&0x0f;
  496.                         write_eeprom(3,i);
  497.                         delay_ms(8);
  498.                         i=Read_Ds1302(0x83);
  499.                         i=((i&0xf0)>>4)*10+i&0x0f;
  500.                         write_eeprom(4,i);
  501.                         delay_ms(8);
  502.                         i=Read_Ds1302(0x81);
  503.                         i=((i&0xf0)>>4)*10+i&0x0f;
  504.                         write_eeprom(5,i);               
  505.                 }
  506.                 if(i<V[1]*100)
  507.                 {
  508.                         write_eeprom(2,0);
  509.                         delay_ms(8);
  510.                         i=Read_Ds1302(0x85);
  511.                         i=((i&0xf0)>>4)*10+(i&0x0f);
  512.                         write_eeprom(3,i);
  513.                         delay_ms(8);
  514.                         i=Read_Ds1302(0x83);
  515.                         i=((i&0xf0)>>4)*10+(i&0x0f);
  516.                         write_eeprom(4,i);
  517.                         delay_ms(8);
  518.                         i=Read_Ds1302(0x81);
  519.                         i=((i&0xf0)>>4)*10+(i&0x0f);
  520.                         write_eeprom(5,i);        
  521.                 }
  522.         }
  523. }
復(fù)制代碼


    附:硬件整體設(shè)計如下所示:

   


    本篇文章部分代碼:
    單片機(jī)小車部分程序下載.doc (67 KB, 下載次數(shù): 33)

   給大家分享我收集的單片機(jī)經(jīng)典程序:
    單片機(jī)經(jīng)典程序與獨(dú)創(chuàng)程序.docx (281.27 KB, 下載次數(shù): 34)



最后求贊,求支持,謝謝大家!



作者: 51hei團(tuán)團(tuán)    時間: 2019-7-18 03:36
好資料,51黑有你更精彩!!!
作者: aktuan007    時間: 2020-5-26 16:42
不知道樓主實(shí)踐驗證了沒?




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 成人毛片网 | 欧美a级成人淫片免费看 | www亚洲精品 | 欧美在线视频一区二区 | 精品久久久久久亚洲综合网 | 久久久国产精品视频 | 中文字幕在线观看一区 | 一区二区三区在线观看免费视频 | 天天干天天玩天天操 | a爱视频 | 亚洲精品久久久一区二区三区 | av免费看在线 | 精品国产黄色片 | 青青草一区二区三区 | 国产1区| 91国内外精品自在线播放 | 国产精品av久久久久久毛片 | 国产a区 | 国产偷久久一级精品60部 | 中文字幕人成乱码在线观看 | 亚洲欧洲精品一区 | 久久久.com| 欧美一级二级三级 | 国产二区三区 | 9色视频在线 | 久久成人免费 | 久久久久久久电影 | 国产黄色在线 | 国产情侣在线看 | 欧美日韩国产一区二区三区不卡 | 欧美最猛性xxxxx亚洲精品 | 国产一区二区三区高清 | 正在播放国产精品 | 午夜不卡一区二区 | 日一区二区 | 日韩在线视频免费观看 | 国产日韩欧美电影 | 欧美不卡 | 国产精品99免费视频 | 男女午夜免费视频 | 91av视频在线免费观看 |