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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 14535|回復: 2
打印 上一主題 下一主題
收起左側

單片機小車(超詳細設計資料)

  [復制鏈接]
跳轉到指定樓層
樓主
  1. Hello, world!
復制代碼



                             第一章、 總述

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



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



第二章、 方案設計與論證

   一 、直流調速系統
   方案一:串電阻調速系統。
    方案二:靜止可控整流器。簡稱V-M系統。
    方案:脈寬調速系統。
  • 旋轉變流系統由交流發電機拖動直流電動機實現變流,由發電機給需要調速的直流電動機供電,調節發電機的勵磁電流即可改變其輸出電壓,從而調節電動機的轉速。改變勵磁電流的方向則輸出電壓的極性和電動機的轉向都隨著改      變,所以G-M系統的可逆運行是很容易實現的。該系統需要旋轉變流機組,至少包含兩臺與調速電動機容量相當的旋轉電機,還要一臺勵磁發電機,設備多、體積大、費用高、效率低、維護不方便且技術落后,因此擱置不用。
  • V-M系統是當今直流調速系統的主要形式。它可以是單相、三相或更多相數,半波、全波、半控、全控等類型,可實現平滑調速。V-M系統的缺點是晶閘管的單向導電性,它不允許電流反向,給系統的可逆運行造成困難。它的另一個缺點是運行條件要求高,維護運行麻煩。最后,當系統處于低速運行時,系統的功率因數很低,并產生較大的諧波電流危害附近的用電設備。
  • 采用晶閘管的直流斬波器基本原理與整流電路不同的是,在這里晶閘管不受相位控制,而是工作在開關狀態。當晶閘管被觸發導通時,電源電壓加到電動機上,當晶閘管關斷時,直流電源與電動機斷開,電動機經二極管續流,兩端電壓接近于零。脈沖寬度調制(Pulse Width Modulation),簡稱PWM。脈沖周期不變,只改變晶閘管的導通時間,即通過改變脈沖寬度來進行直流調速。


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

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

                                                                                                                                             

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


  


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



                                 圖2.3前行與倒車控制電路

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


圖2.4 電壓比較器電路

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

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


圖2.5 行車距離檢測電路

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

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

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

圖2.6 系統原理圖



第三章、 硬件設計

    單片機應用系統的硬件電路設計包含有兩部分內容:
    一是系統擴展,即單片機內部的功能單元,如ROM﹑RAM﹑I/O口﹑定時/記數器﹑中斷系統等能量不能滿足應用系統的要求時,必須在片外進行擴展,選擇適當的芯片,設計相應的電路。
    二是系統配置,既按照系統功能要求配置外圍設備,如鍵盤顯示器﹑打印機﹑A/D﹑D/A轉換器等,要設計合適的接口電路。

    一 、80C51單片機硬件結構
    80C51單片機是把那些作為控制應用所必需的基本內容都集成在一個尺寸有限的集成電路芯片上[2]。如果按功能劃分,它由如下功能部件組成,即微處理器、數據存儲器、程序存儲器、并行I/O口、串行口、定時器/計數器、中斷系統及特殊功能寄存器。它們都是通過片內單一總線連接而成,其基本結構依舊是CPU加上外圍芯片的傳統結構模式。但對各種功能部件的控制是采用特殊功能寄存器的集中控制方式。
  • 1、微處理器:該單片機中有一個8位的微處理器,與通用的微處理器基本相同,同樣包括了運算器和控制器兩大部分,只是增加了面向控制的處理功能,不僅可處理數據,還可以進行位變量的處理。
  • 2、數據存儲器:片內為128個字節,片外最多可外擴至64k字節,用來存儲程序在運行期間的工作變量、運算的中間結果、數據暫存和緩沖、標志位等,所以稱為數據存儲器。
  • 3、程序存儲器:由于受集成度限制,片內只讀存儲器一般容量較小,如果片內的只讀存儲器的容量不夠,則需用擴展片外的只讀存儲器,片外最多可外擴至64k字節。
  • 4、中斷系統:具有5個中斷源,2級中斷優先權。
  • 5、定時器/計數器:片內有2個16位的定時器/計數器, 具有四種工作方式。
  • 6、串行口:1個全雙工的串行口,具有四種工作方式。可用來進行串行通訊,擴展并行I/O口,甚至與多個單片機相連構成多機系統,從而使單片機的功能更強且應用更廣。
  • 7、P1口、P2口、P3口、P4口為4個并行8位I/O口。
  • 8、特殊功能寄存器:共有21個,用于對片內的個功能的部件進行管理、控制、監視。實際上是一些控制寄存器和狀態寄存器,是一個具有特殊功能的RAM區。

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

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


圖3.1 80C51單片機最小系統

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

圖3.2 80C51復位電路

    三、 前向通道設計
    單片機用與測控系統時,總要有與被測對象相聯系的前向通道。因此,前向通道設計與被測對象的狀態、特征、所處環境密切相關。在前向通道設計時要考慮到傳感器或敏感元件選擇、通道結構、信號調節、電源配置、抗干擾設計等。在通道電路設計中還涉及到模擬電路諸多問題。

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

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

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


圖 3.3 超聲波檢測電路

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


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

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

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

圖3.5 EM78P458的管腳


  • 該芯片共有20個管腳,管腳LED1LED2LED3LED4分別接10k電阻和三極管后與4位八段數碼管5461中的a1a2a3a4四個數位選擇端相連,這四個數位選擇端用來產生LED選通信號。
  • 管腳a﹑b﹑c﹑d﹑e﹑f﹑g﹑dp分別接680歐電阻后與四位八段數碼管5461中的a﹑b﹑c﹑d﹑e﹑f﹑g﹑dp相連,分別控制各段碼和小數點。
  • 管腳d0﹑d1﹑d2﹑d3接單片機并行口,通過對單片機對芯片進行控制。管腳vss串上10k電阻后與vcc管腳相接后再接+5v電源,管腳gnd接地。
    該芯片所驅動的顯示電路如圖3.6 EM78P458集成顯示電路所示
顯示驅動器支持動態顯示,其顯示功能如表4.2真值表所示,0000-1001顯示從0-9數字,1010是未進位時是小數點清位,1011是進位后加小數點,1100-1111是八段共陰數碼管的位選。


圖3.6 EM78P458集成顯示電路



第四章、軟件設計

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

    一 、主程序設計                                                              
   程序清單如下

  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 ;小數點位
  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
復制代碼
    二、 顯示子程序設計
      
     程序清單如下:
  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
復制代碼

    三 、避障子程序設計


        程序清單如下:
  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>
復制代碼


    四、 整體程序設計如下所示:


       程序清單如下:
  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 ;小數點位
  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
復制代碼


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

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

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

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


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

     本設計采用第三種方案實現“看門狗”電路,下面就對該方案作以介紹。
    (1)基本原理
    CD4060 是帶震蕩器的14位計數器,由該芯片構成的看門狗電路4060記數頻率由RT和CT決定。設實際的程序所需工作周期為T,分頻器記滿時間為T’,當T’>T 且系統正常工作時,程序每隔T對4060進行掃描一次,分頻且永無記滿輸出信號。如系統工作不正常(如程序跑飛、死循環等),程序對4060發不出掃描信號,分頻器記滿輸出一脈沖號使CPU復位。
    (2)參數選擇
    4060的振蕩頻率f由 RT 、CT決定。Rs用于改善振蕩器的穩定性,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)的選擇要根據情況確定。
    (3)幾個原則
    看門狗電路必須由硬件邏輯組成,不宜由可編程計數器充當,因為CPU失控后,可能會修改可編程器件參數,使看門狗失效。4060的RST線上阻容組成的微分電路很重要,因為掃描輸入信號是CPU產生的正脈沖,若此信號變“1”后,由于干擾,程序亂飛,微分電路只能讓上跳沿通過,不會封死4060,看門狗仍能計數起作用。若沒有微分電路,掃描輸入信號上的“1”狀態封死4060,使之不能記數,看門狗不起作用。CPU必須在正確完成所有工作后才能發掃描輸入信號,且程序中發掃描信號的地方不能太多。否則,正好在哪里有死循環,看門狗就不產生記滿輸出信號,不能重新啟動CPU。4060的記滿輸出信號不但要接到MCS-51的RST腳,而且還應接到其它芯片的RST腳,因為程序亂飛后,其它具有RST腳的芯片也混亂了,必須全部復位。


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


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






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

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

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

  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. }
復制代碼
  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;  /* 數據線 */
  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. //應答位控制
  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. //等待應答
  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總線發送數據
  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總線上接收數據
  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. }
復制代碼
  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[]={                       //標準字庫
  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)  //數碼管顯示
  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;                    //設置定時器0為16位自動重裝載外部記數模式
  141.     TH0 = TL0 = 0xff;               //設置定時器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;                //設置定時器模式
  149.         TL1 = 0x00;                //設置定時初值
  150.         TH1 = 0x4C;                //設置定時初值
  151.         TF1 = 0;                //清除TF1標志
  152.         TR1 = 0;                //定時器1開始計時
  153.         ET1 = 1;
  154. }

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

  164. //調整時間
  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()//顯示時間和設置時間                                
  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. //中斷服務程序
  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. }
復制代碼


    附:硬件整體設計如下所示:

   


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

   給大家分享我收集的單片機經典程序:
    單片機經典程序與獨創程序.docx (281.27 KB, 下載次數: 34)



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


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏9 分享淘帖 頂3 踩
回復

使用道具 舉報

沙發
ID:328014 發表于 2019-7-18 03:36 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

板凳
ID:582255 發表于 2020-5-26 16:42 | 只看該作者
不知道樓主實踐驗證了沒?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产成人精品一区 | 久久久国产精品 | 久久久精品一区 | 久久国产99 | 99久久久久 | 99国产精品久久久久久久 | 亚洲成av人片在线观看 | 精品久久久久久久久久 | 毛片黄片 | 涩涩视频在线观看免费 | 午夜免费在线 | 日本在线中文 | 免费网站国产 | 国产精品欧美一区二区三区 | 在线观看国产 | 亚洲每日更新 | 精品国产乱码久久久久久老虎 | 日本久久一区二区三区 | 国产精品日日摸夜夜添夜夜av | 国产三级精品三级在线观看四季网 | 91.com在线观看 | 日韩国产一区 | 欧美另类视频 | 国产精品毛片无码 | 亚洲精品成人av久久 | av网站在线免费观看 | 伊人免费网 | 亚洲一区二区三区四区五区中文 | 日韩欧美国产一区二区三区 | 亚洲欧美综合网 | 欧美成人精品一区二区男人看 | 精品三区 | av影音在线 | 精品一区二区三区在线视频 | 亚洲精品久久久久久久久久久久久 | 欧美视频中文字幕 | 亚洲精品91 | 青青草原精品99久久精品66 | 69电影网| 欧美男人亚洲天堂 | 亚洲精品乱码久久久久久按摩观 |