電子科技大學成都學院
××××系
?
課
程
設
計
題目名稱? ?基于STC51的車載超聲波防撞雷達
學生姓名 ?????????????????????????????????
學 號 ?????????????????????????????????
專 業 ?????????????????????????????????
指導教師 ?????????????????????????????????
2019年5月制
基于STC51的車載超聲波防撞雷達
摘 要
隨著中國經濟的不斷發展與提升,汽車在人們的生活中已經得到了全面的普及,因此與汽車相關的配件以及安全系統的研發在市場上具有非常廣泛的需求?;诔暡ㄔ鞸TC51單片機控制的車載防撞雷達在各個方面具有非常明顯的優勢,這一車載防撞雷達系統目前在汽車配件市場上更是供不應求。這一系統不受光照度、電磁場、圖像色彩等多個因素的的影響,加之超聲波傳感器目前的產品已經趨于成熟,而且成本低廉。
本次課程設計主要是基于STC51單片機為控制系統,超聲波傳感器為信號采集系統的原理集成設計的。充分利用了超聲波本身在車載雷達方面所具有的廣泛優勢,利用C語言作為軟件開發的基礎,將軟件與硬件充分地進行結合來綜合設計。本次課程設計由兩個組員一起共同設計開發,產品主要由軟件和硬件兩個部分集合而成,組員1主要負責硬件方面的設計,組員2主要負責軟件開發設計。硬件部分包括了STC51單片機最小系統,超聲波發射、接收電路,數碼管顯示電路,電源電路以及報警電路組成;軟件部分則包括了超聲波發射接收中斷程序、距離測試程序,數碼管顯示程序等幾個模塊組成。這一系統經過與汽車嵌入式系統集成以后,可以讓駕駛員在停車、倒車、入庫等多個易撞擊操作中在駕駛艙內做到心中有數,極大地提高了汽車駕駛的安全性、可操作性以及舒適性。
關鍵詞:單片機;防撞報警;超聲波;
目 錄
2.1.1??????? 超聲波發射/接收電路設計... 2
2.1.4??????? STC89C51單片機最小系統電路設計... 5
[if !supportLists]1.1??????[endif]課程設計立項背景
隨著國家經濟的以及人民生活水平的不斷提高,現在私家車的已經得到了全方位的普及,交通擁擠這一問題也變得越來越嚴重。而倒車、入庫扥一系列問題也成為了一些駕駛技術不是非常熟練的駕駛員的困擾之一。這不僅會給駕駛員帶來財產以及經濟上的損失以及一些不必要的糾紛,甚至有時還會對駕駛員的生命安全構成一定的威脅。為更加優質高效地解決當前一些駕駛員所面臨的倒車入庫困境,安全倒車雷達的設計與生產也漸漸地成為一項重要的課題。51單片機不僅具有開發環境成熟,廉價,產品生態環境好等特征,而且在市面上已經得到了非常廣泛的應用,同時超聲波傳感器具有精度高,質量好等優點,經過對自身知識水平的評估,我們小組課程最終確定采用以51單片機為主要的控制系統,以超聲波傳感器為核心的信息采集原件的設計方案,同時兩位組員各自發揮自身的興趣愛好以及優長,分別負責系統的軟件和硬件開發。
本次課程設計主要論述了超聲波的測距工作原理。從小的應用方面來說,本課題的研究直接解決了司機倒車時的困擾,更能有效地降低倒車過程中發生的大小事故。但從更廣泛的應用來講,超聲波測距系統的研究在許多工業、交通運輸業、軍事等等方面有著更為廣泛顯著的應用;并且詳細介紹了超聲波傳感器的工作特性和系統發射和接收等多種電路同時還有單片機的硬件設計與軟件設計及其實現,突出以單片機為核心所設計的防撞報警器對于在汽車安全領域的突破與拓展有一定的作用。
[if !supportLists]2.1??????[endif]綜合電路設計
本次課程設計的超聲波倒車雷達測距系統主要由超聲波發射/接收電路,單片機最小系統復位電路,現實電路,報警電路等幾個硬件電路系統組成,下面將逐一地對這幾個電路系統進行系統的闡述,在確定最終采用各方面綜合性能優越的51單片機的前提之下,進行了最終的電路的設計開發。
[if !supportLists]2.1.1?????[endif]超聲波發射/接收電路設計
超聲波發射和接收電路的設計必須要考慮到傳感器的靈敏度問題,對于這一系統的設計與研發,首先的難點在于40KHz超聲波信號工作頻率的產生,由于超聲波倒車雷達所使用的超聲波傳感器所需的核心頻率為40KHz超聲波工作頻率,只有在這個頻段工作的超聲波傳感器才具有良好的靈敏性。當超聲波傳感器偏離這一工作頻率之時,接收電路的設計不僅會大幅度地增加難度,而且將會使得接收的靈敏度大幅度地降低。因此課程設計關于超聲波發射/接收電路的設計原則將會圍繞這一思路進行。對于超聲波傳感器所需要的40KHz電路驅動信號的產生,實現的方法種類非常多,可以采用電容、電感震蕩電路來實現與產生,但是綜合考慮到其信號驅動的穩定性比較差,因此課程設計最終決定采用單片機來產生驅動信號,由于單片機采用的是晶振作為信號產生的源,因此其具有良好的穩定性以及非常高的穩定性,同時僅僅需要通過對軟件編程進行一定的修改,便能夠得到不同頻率的驅動信號。
在進行超聲波接收電路的設計時,通常會以超聲波碰撞障礙物所返回的信號值作為距離判斷的依據,因此對于超聲波傳感器的起控點的選擇也是本設計成功的關鍵組成部分,超聲波在傳播的過程中受到環境的影響因素非常大,其信號強弱與環境因素關系密切,因此在進行接收與發射電路調試的過程中必須小心謹慎,合理地選擇電壓比較環節的起控點,從而達到當距離小于設定值時警報回響起的報警功能。超聲波模塊如圖2-1-1:
??????????????????????? 圖2-1-1:超聲波模塊
[if !supportLists]2.1.2?????[endif]距離顯示模塊電路
在進行顯示系統電路設計的之時,考慮到顯示器應該具有良好的可見性,同時應該顯示器產品還需要具有較好的成熟性,因此最終選擇了4位的8段數碼管最為電路對超聲波測量的距離進行顯示。這不僅充分地利用了單片機的接口資源,同時也使得顯示電路具有非常良好的可見性,在進行顯示電路的設計過程中,為了最大限度地利用單片機的接口資源,現實電路采用的是串行驅動的LED驅動方式,運用4個數碼管中的三個來對側臉距離在400cm的超聲波測量距離進行數值顯示。
LED8段數碼管顯示器的驅動方式通??梢圆捎么擈寗雍筒⒙擈寗觾煞N方式,即我們通常所說的靜態驅動和動態驅動兩種方式,靜態驅動通常需要與一些寄存器來進行配合,通過給每一位的8段LED數碼管特定的電流,然后利用余暉效應來進行顯示。顯示之時單片機需要將顯示字符碼發送到相應的數碼管段端口,然后維持電流即可。如果需要顯示新的數字,則可以通過重新發送字符來進行顯示。使用這種驅動方式進行顯示CPU開支通常非常小,但是當進行多位的數碼管顯示時不僅會使得連線的數量大幅度的增加,還需要一些寄存器和譯碼器的支持,因此當多位顯示的時候相應的成本自然也會增加。而動態顯示一般用在多數碼管顯示方面,采用動態顯示原理的多位數碼管的顯示通常能夠大幅度地節約單片機的接口資源,其采用的分時段顯示僅僅需要在軟件方面稍微做一下改動就可以實現多位顯示,其主要的原理是人類眼睛的余暉效應。LED8位數碼管段動態顯示的方法可以使得數碼管在顯示的時候亮度趨于均勻,因為動態顯示的方法主要是通過輪流控制單片機各端口來對數碼管進行驅動現實的。綜合單片機資源以及成本節約的考量,本次課程設計最終決定采用動態顯示的方法來對超聲波距離測量數據進行顯示,顯示的過程中采用8155芯片作為單片機的I/O拓展端口,P1作為LED數字字符輸出端口,同時經過74LS244反向驅動放大器來進行放大,進一步地提高LED的亮度。
在單片機應用系統中,發光二極管LED顯示器常用兩種驅動方式;靜態顯示驅動和動態顯示驅動。所謂靜態顯示驅動,就是給要點亮的LED通過恒定的電流,即每一位LED顯示器各引腳都要占用單獨的具有鎖存功能的I/O接口。單片機只需要把要顯示的字形段碼發送到接口電路并保持不變即可,如果要顯示新的數據,在發送新的自行段碼。因此,使用這種方法單片機中的CPU開銷小,但這種驅動方法需要寄存器、編譯碼等硬件設備。當需要顯示的位數增加時,所需要的期間和連線也應該增加,成本也增加。而所謂動態顯示驅動就是給欲點亮的LED通以脈沖電流,即采用分時的方法,輪流控制各個顯示器的COM端,使各個顯示器輪流點亮,這是LED的亮度就是通斷的平均亮度??紤]各種因素,本設計選用動態驅動顯示。設計選用8155芯片作為單片機應用系統拓展的I/O口。PA口作為LED的字形輸出口,為提高顯示亮度,采用8路反相驅動器74LS244驅動;PC口作為LED的為選控制口,采用共陽極的LED顯示器,由于8端全亮時位控線的驅動電流較大,采用6路反應驅動器74LS06以提高驅動能力。LED驅動顯示電路的電路設計原理圖主要如圖2-1-2:
圖4-2? 顯示電路
[if !supportLists]2.1.3?????[endif]距離碰撞電路報警設計
報警電路主要由蜂鳴器進行報警,因此報警電路設計相對比較簡單,主要是由放大電路以及揚聲器電路進行組成,放大電路則采用一個三極管進行放大。由于單片機本身所產生的電流信號比較小,不能夠驅動蜂鳴器電路,因此采用一個三極管來對單片機所產生的電流進行放大,通過三極管放大的電流來對蜂鳴器進行驅動。蜂鳴器采用的是有源蜂鳴器,因此其驅動方式相對簡單,僅僅需要給其一段加上高電位,另一端加上低電位即可,如果要對蜂鳴器的頻率進行控制,則需要簡單地對加上高電位的時間進行控制即可,蜂鳴器報警電路的電路設計原理圖如圖2-1-3:
? 圖2-1-3? 蜂鳴器報警電路
[if !supportLists]2.1.4?????[endif]STC89C51單片機最小系統電路設計
單片機最小系統電路當中最為核心的就是復位電路和外部震蕩電路,前者主要是給單片機進行復位,類似于電腦的重啟功能,而護著主要提供時鐘震蕩,滿足單片機的時序功能的恩需要和定時時頻率的需求。主要的硬件包括:復位按鍵,11.0592頻率的晶振,由于使用stc-isp下載,同時也為了降低成本,省去了自動下載調路而用CH340外接電路進行下載。通常,復位電路包括上電時的自動復位和通過按鍵進行復位兩種復位形式。
時鐘電路:STC89C52單片機的時鐘震蕩電路主要包括外接時鐘震蕩和內部電路時鐘震蕩兩種方式。外部的時鐘震蕩電路由兩個電容串聯,然后中間加一個石英晶振即可,兩個電容的值一般在5~30pF當中選擇,常用的比較典型的值是22pF和30pF,石英晶振的選擇值一般在1.2MHz~12MHz當中,典型的選擇值是11.0592MHz,6MHz,12MHz,三種值。我們的設計當中采用的是11.0592MHz的設計值。兩個電容的作用就是維持外部適中的震蕩穩定和快速起振,由兩個電容和一個石英晶振構成的自激震蕩為內部電路提供有序的時鐘脈沖周期信號。
單片機最小系統電路當中最為核心的就是復位電路和外部震蕩電路,前者主要是給單片機進行復位,類似于電腦的重啟功能,而護著主要提供時鐘震蕩,滿足單片機的時序功能的恩需要和定時時頻率的需求。主要的硬件包括:復位按鍵,11.0592頻率的晶振,由于使用stc-isp下載,同時也為了降低成本,省去了自動下載調路而用CH340外接電路進行下載。通常,復位電路包括上電時的自動復位和通過按鍵進行復位兩種復位形式。
時鐘電路:STC89C52單片機的時鐘震蕩電路主要包括外接時鐘震蕩和內部電路時鐘震蕩兩種方式。外部的時鐘震蕩電路由兩個電容串聯,然后中間加一個石英晶振即可,兩個電容的值一般在5~30pF當中選擇,常用的比較典型的值是22pF和30pF,石英晶振的選擇值一般在1.2MHz~12MHz當中,典型的選擇值是11.0592MHz,6MHz,12MHz,三種值。我們的設計當中采用的是11.0592MHz的設計值。兩個電容的作用就是維持外部適中的震蕩穩定和快速起振,由兩個電容和一個石英晶振構成的自激震蕩為內部電路提供有序的時鐘脈沖周期信號。
???? 圖2-1-4? 上電復位電路
[if !supportLists]2.2??????[endif]電路調試以及評估
[if !supportLists]2.2.1?????[endif]電路板焊接
在完成電路設計的基礎上,接下來就是將電路設計進行實物焊接,實物焊接時單片機產品設計過程中非常重要的一環,單片機系統設計除了需要優秀的產品設計以外,還需要良好的焊接工藝,只有將優秀的產品設計與良好的焊接工藝相結合,才能順利地完成單片機的設計,對于單片機元器件的焊接則主要考慮到以下幾點:
(1)可靠的電氣焊接工藝:焊接座位電子產品從物理上的原理實現到電子產品電氣連接的重要一環,電路的連線需要美觀,可靠的電氣連接來對元器件和電路辦的合金層進行固定,從而達到產品電氣連接的目的。
(2)連接焊點具有足夠的機械強度:連接的重要目的之一便是固定元器件,同時也為了滿足電氣連接的需要,因此需要有足夠的機械強度來對元器件和電路板的焊點進行固定。
(3)整齊光滑的外觀,焊接工藝需要讓焊點具光滑的外表,良好的焊點對焊接錫料的要求剛好到位,因此焊點上面會比較的光滑,只有整潔光滑的焊點外表才不會出現橋接以及粒尖現象。
[if !supportLists]2.2.2?????[endif]電路調試分析
車載單片機防撞雷達系統工作的前提是電源電路模塊工作正常,因此首先要對單片機電源部分進行測試,接上電源進行測試所得電源輸出部分應該為5V。同時需要對單片機驅動超聲波模塊進行測試,運用示波器對電路進行測量,測得P01端口的輸出頻率為39.96KHz,與超聲波模塊所需的40KHz基本一致,因此符合實際的應用需求。依據超聲波傳感器在不同環境場合的需要,可在接收轉換器上接上濾波電容以提高超聲波傳感器的抗干擾能力。
[if !supportLists]3.1??????[endif]硬件與軟件設計
[if !supportLists]3.1.1?????[endif]硬件設計
STC89C51單片機作為控制中心的控制單元,不僅僅具有價格低廉,超低功耗,可拓展性強等優點。而且在IO驅動能力拓展,性價比,抗電磁干擾,抗噪音干擾等多個方面性能均非常優異。在性能方面,STC89C52是以流行的8051單片機內核為核心,且兼容所有8051單片機的內核程序設計,在硬件不改變得條件下,可以直接使用ISP系統編程,不管是程序的燒寫,修改,程序的調動方面,都給我們帶來了不言而喻的方便性。
STC89C51 單片機的I/O端口的編程可以依據實際的需要來對其進行相應的軟件修改,即對其端口所對應的寄存器端口進行讀寫編程,具體的步驟主要如下:
(1)初始化的端口數據輸出的寄存器,應該避免端口作為輸出的時侯,開始階段顯現不確定的狀態,影響到外圍的電路正常工作;
(2)根據外圍的電路功能,確定I/O端口id方向,初始化的端口數據方向寄存器。把用作輸入的端口可以不用考慮其方向的初始化,因為I/O復位缺省值是輸入;
(3)對于用作輸入的I/O管腳,如需上拉,再經過輸入上拉讓其能寄存器為它內部配置個上拉電阻;
(4)最后對I/O的端口進行輸出(寫數據輸出的寄存器)與輸入(讀端口)編程,完成對外圍的電路的相應功能[8]。
根據系統設計要求,各接口功能如下:
??P1.0:產生輸出一個40KHz的脈沖信號。(用于后方的測距電路)
??P1.1:產生輸出一個40KHz的脈沖信號。(用于右側的測距電路)
??P1.2:產生輸出一個40KHz的脈沖信號。(用于左側的測距電路)
?? [if !vml]
[endif]:產生中斷請求,接后方測距電路。
?? [if !vml]
[endif]:產生中斷請求,接后方測距電路。
??P1.3:接ICA3輸入端,用于中斷優先級的判斷。
??P1.4:接ICA3輸入端,用于中斷優先級的判斷。
??P0.0~P0.7:用于顯示輸出,接顯示器。
??P2.7:接報警電路。
??P2.0:接報警電路。
??P2.1:接報警電路。
??XTAL1:接入外部晶振的引腳。在單片機的內部,它是一個反相放大器的輸入端,???????????????????? 這一個放大器構成出片內振蕩器。采用外部振蕩器的時侯,有些引腳應該接地。
??XTAL2:接入外部晶振的引腳。在片內接到振蕩器反相放大器輸出端與內部時鐘發生器的輸入端。當采用外部振蕩器的時侯,此引腳接外部振蕩的信號輸入。
??RST:STC89C51復位信號的輸入引腳,高電位的工作,當要對芯片復位的時侯,只須將此引腳電位提至高電位,并且持續不變兩個機器的周期以上時間,STC89C51就能完成系統的復位各項工作,使內部特殊的功能寄存器內部都被設成已知狀態。整體的電路硬件連接圖如下:
圖3-1-1:硬件原理圖
[if !supportLists]3.1.2?????[endif]軟件設計
主程序為單片機程序主體,整一個單片機端的系統的軟件功能的實現都在其中完成,在此過程里主程序調用子程序和中斷服務程序。程序第一步完成初始化過程,第二步是一個重復控制發射信號的過程,即調用發射子程序幾遍,并且次次發射的周期結束會判斷在發射的信號后延時等待過程中是否會發生;中斷,即是否回波的產生判斷程序的流程。
圖5-2? 單片機軟件主程序流程
????????????????????????? 圖5-3(a)? 單片機軟件子程序流程圖
功能說明?:TH0*256時間值+TLO中讀取出來的時間差數據并不能作為距離值直接顯示輸出,因為時間差值與實際的距離值之間轉換公式為Outcome=TH0*256+TL0; Outcome=(Outcome*1.7)/100。其中,V為聲音在常溫下的傳播速度,T為發射信號到接收之間經歷的時間,在這個部分中,信號處理包括計數值與距離值換算,二進制與十進制轉換。
[if !vml]
[endif]?
????????? 圖5-3(b)?單片機軟件子程序流程圖
功能說明?:顯示報警程序中,當小車距離障礙物大于5cm且小于40cm時,車上左右燈閃爍,會報警鳴聲處于警告區;當小車距離障礙物小于5cm時,車上左右燈顯示紅色并且會報警鳴聲比之前的大,處于危險區;當小車距離障礙物大于40cm時,車上左右燈綠色,處于安全區。
在系統硬件表現出的超聲波測距基本功能的同時,系統軟件所實現功能主要是系統功能的實現和數據處理與應用。根據上節所述系統硬件設計和所完成的功能,系統軟件需要?????? 實現以下功能:
一、信號控制
在系統的硬件中,已完成的發射電路、接收電路、檢測電路、顯示電路等設計。在系統軟件里,要完成出增益控制信號與門控信號、發射脈沖信號與峰值采集信號及遠近控制信號的時序及輸出。
二、數據存儲
為得到發射信號和接收回波兩者之間時間差,須讀出此刻計數器里的計數值,接著存儲在 RAM 中,并且每次的發射周期的開始,必須對計數器進行清零操作,以備后續的處理。
三、信號處理
RAM 里存儲的計數值不能作為距離值的直接地顯示輸出,計數值和實際距離值之間轉換
公式為:距離=高電平時間*聲速(340M/S)/2????????????????????? (5-1)
四、數據傳輸與顯示
通過軟件的處理得到距離送顯示輸出,用三位 LED 顯示。因為采用單片機STC89C51并且考慮了系統的控制流程,所以整一個系統軟件都是 STC89C51系列單片機的匯編語言實現。由于距離值的得出和顯示是在中斷子程序里完成的,因此在初始化的發射程序后進入到中斷響應的等待過程。繼中斷響應后,原始數據經過計數值和距離值換算子程序與二進制和十進制轉換子程序之后顯示輸出。整一個系統軟件的功能實現可以分為主程序、中斷服務程序等主要的部分。
本次課程設計在分析了汽車業現狀的基礎上,提出了汽車防撞報警設計及其重要性。設計中對車載防撞報警系統的設計可應用在汽車倒車等多種場合,用于告知駕駛者在倒車的時候能準確的避開可能對倒車過程中有著的危害和障礙物與行人,有一定較強實用性,提高駕駛員的安全性。
附 錄一?? 系統原理圖
?
附 錄二?? Proteus軟件仿真圖
附 錄三?? C語言代碼
#include <reg52.H>//器件配置文件
#include
#include "eeprom52.h"
//傳感器接口
sbit RX?= P2^3;
sbit TX?= P2^2;
//按鍵聲明
sbit S1?= P1^4;
sbit S2?= P1^5;
sbit S3?= P1^6;
sbit S4=P1^1;
sbit S5=P1^2;
sbit S6=P1^3;
bit msflag=0;
sbit light=P3^6;
sbit ms=P3^7;
sbit jg=P3^0;
sbit yg=P3^1;
sbit DIAN=P0^5;
//蜂鳴器
sbit Feng= P2^0;
//變量聲明
unsigned int? time=0;
unsigned int? timer=0;
unsigned char posit=0;
unsigned long S=0;
unsigned long BJS;//報警距離
char num=0;
//模式 0正常模式 1調整
char Mode=0;
bit?flag=0,flag_BJ;
unsigned char const discode[] ={0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x47,0xDF,0xD7,0x80};???? //數碼管顯示碼0123456789-和不顯示
unsigned char disbuff[4]?????? ??={0,0,0,0};???????????? //數組用于存放距離信息
unsigned char disbuff_BJ[4]? ={0,0,0,0};//報警信息
sbit W0=P2^4;
sbit W1=P2^5;
sbit W2=P2^6;
sbit W3=P2^7;
/******************把數據保存到單片機內部eeprom中******************/
void write_eeprom()
{
?????? SectorErase(0x2000);
?????? byte_write(0x2000,BJS%255);
?????? byte_write(0x2001,BJS/255);
?????? byte_write(0x2060,a_a);?????
}
/******************把數據從單片機內部eeprom中讀出來*****************/
void read_eeprom()
{
?????? BJS?? = (byte_read(0x2001)*255)+byte_read(0x2000);
?????? a_a????? = byte_read(0x2060);
}
/**************開機自檢eeprom初始化*****************/
void init_eeprom()
{
?????? read_eeprom();???????????? //先讀
?????? if(a_a!= 1)??????????? //新的單片機初始單片機內問eeprom
?????? {
????????????? BJS?? = 50;
????????????? a_a= 1;
????????????? write_eeprom();???? ?? //保存數據
?????? }????
}
//延時100ms(不精確)
void delay(void)
{
???unsigned char a,b,c;
???for(c=10;c>0;c--)
???????for(b=38;b>0;b--)
???????????for(a=130;a>0;a--);
}
//按鍵掃描
void Key_()
{
?????? ms=~msflag;
?????? if(S4==0){
????????????? delay();?? ?? //延時去抖
???????????????????? if(S4==0){
???????msflag=~msflag;
??????????????????????????? while(!S4);
????????????? }
?????? }
?????? if(msflag==0){
????????????? if(S5==0){
???????????????????? delay();?? ?? //延時去抖
??????????????????????????? if(S5==0){
?????????????????????????????????? if(jg==1&&yg==1){
???????????????????????????????????????????????? jg=0;
?????????????????????????????????? }elseif(jg==0 && yg==1){
???????????????????????????????????????????????? jg=1;yg=0;
?????????????????????????????????? }elseif(yg==0 && jg==1){
???????????????????????????????????????????????? jg=0;yg=1;
?????????????????????????????????? }
?????????????????????????????????? while(!S5);
???????????????????? }
????????????? }
???????????????????? if(S6==0){
??????????????????????????? delay();?? ?? //延時去抖
?????????????????????????????????? if(S6==0){
????????????????????????????????????????? jg=1;yg=1;
????????????????????????????????????????? while(!S6);
??????????????????????????? }
???????????????????? }
?????? }else{
????????????? if(light==0){
???????????????????? //距離小于報警距
???????????????????? if(S<=BJS)?????????????????? //距離小于報警值
???????????????????? {
??????????????????????????? ?jg=0;yg=1;
???????????????????? }
???????????????????? else?????????????????????? //距離大于報警值
???????????????????? {
??????????????????????????? yg=0;jg=1;
???????????????????? }
????????????? }else{
???????????????????? jg=1;yg=1;
????????????? }
?????? }
?????? //+
?????? if(S1==0)
?????? {
????????????? delay();?? ?? //延時去抖
????????????? delay();?? ?? //延時去抖
????????????? while(S1==0)
????????????? {
???????????????????? P1=P1|0x0f;
????????????? }
???????????????????? BJS++;?? //報警值加
????????????? if(BJS>500)//最大500
????????????? {
???????????????????? BJS=1;
????????????? }
????????????? write_eeprom();?????????????????? ?? //保存數據
?????? }
?????? //-
?????? elseif(S2==0)
?????? {
????????????? delay();
????????????? delay();?? ?? //延時去抖
????????????? while(S2==0)
????????????? {
???????????????????? P1=P1|0x0f;
????????????? }
???????????????????? BJS--;???? //報警值減
????????????? if(BJS<1)?????? //最小1
????????????? {
???????????????????? BJS=500;
????????????? }
????????????? write_eeprom();?????????????????? ?? //保存數據
?????? }
?????? //功能
?????? elseif(S3==0)??????? //設置鍵
?????? {
????????????? delay();
????????????? delay();?? ?? //延時去抖
????????????? while(S3==0)
????????????? {
???????????????????? P1=P1|0x0f;
????????????? }
???????????????????? Mode++;??????? //模式加
???????????????????? num=0;
????????????? if(Mode>=2)????????? //加到2時清零
????????????? {
???????????????????? Mode=0;
????????????? }????
?????? }
}
/**********************************************************************************************************/
//掃描數碼管
void Display(void)?????????????????????
{
?????? //正常顯示
?????? if(Mode==0)
?????? {
????????????? num++;
????????????? if(num==1)
????????????? {
???????????????????? W3=1;
???????????????????? W0=1;
???????????????????? P0=~discode[disbuff[0]];
???????????????????? DIAN=0;
???????????????????? W1=0;???
????????????? }
????????????? elseif(num==2)
????????????? {
???????????????????? W1=1;
???????????????????? P0=~discode[disbuff[1]];
???????????????????? W2=0;
????????????? }
????????????? elseif(num>=3)
????????????? {
???????????????????? W2=1;
???????????????????? P0=~discode[disbuff[2]];
???????????????????? W3=0;
???????????????????? num=0;
????????????? }
?????? }
?????? //報警顯示
?????? else
?????? {
????????????? num++;
????????????? if(num==1)
????????????? {
???????????????????? W3=1;
???????????????????? P0=~0xCE;?????????? ?//11001110
???????????????????? W0=0;
????????????? }
????????????? elseif(num==2)
????????????? {
???????????????????? W0=1;
???????????????????? P0=~discode[disbuff_BJ[0]];
???????????????????? DIAN=0;
???????????????????? W1=0;???
????????????? }
????????????? elseif(num==3)
????????????? {
???????????????????? W1=1;
???????????????????? P0=~discode[disbuff_BJ[1]];
???????????????????? W2=0;
????????????? }
????????????? elseif(num>=4)
????????????? {
???????????????????? W2=1;
???????????????????? P0=~discode[disbuff_BJ[2]];
???????????????????? W3=0;
???????????????????? num=0;
????????????? }
?????? }
}
/**********************************************************************************************************/
//計算
void Conut(void)
{
?????? time=TH0*256+TL0;???? ? //讀出T0的計時數值
?????? TH0=0;
?????? TL0=0;???????????????????????? ? //清空計時器
?????? S=(time*1.7)/100;???? //算出來是CM
?????? if(Mode==0)???????????????? ? //非設置狀態時
?????? {
????????????? if((S>=700)||flag==1)//超出測量范圍顯示“-”
????????????? {????
???????????????????? flag=0;
???????????????????? disbuff[0]=10;?????? ??//“-”
???????????????????? disbuff[1]=10;?????? ??//“-”
???????????????????? disbuff[2]=10;?????? ??//“-”
????????????? }
????????????? else
????????????? {
???????????????????? //距離小于報警距
???????????????????? if(S<=BJS)?????????????????? //距離小于報警值
???????????????????? {
??????????????????????????? ?flag_BJ=1;?????????? //報警變量置一,定時器開始報警
???????????????????? }
???????????????????? else?????????????????????? //距離大于報警值
???????????????????? {
??????????????????????????? flag_BJ=0;??????????? //關閉報警
??????????????????????????? Feng=1;??????????????? //蜂鳴器關閉
???????????????????? }
???????????????????? disbuff[0]=S%1000/100;????????????? //將距離數據拆成單個位賦值
???????????????????? disbuff[1]=S%100/10;
???????????????????? disbuff[2]=S%10;
????????????? }
?????? }
?????? else
?????? {
???????????????????? Feng=1;
???????????????????? flag_BJ=0;??????????????????????????????????????? ?? //報警關閉
???????????????????? disbuff_BJ[0]=BJS%1000/100;
???????????????????? disbuff_BJ[1]=BJS%100/10;
???????????????????? disbuff_BJ[2]=BJS%10;
?????? }
}
/**********************************************************************************************************/
//定時器0
void zd0() interrupt 1????????? ?//T0中斷用來計數器溢出,超過測距范圍
{
?????? flag=1;??? ?????????????????????????????????? //中斷溢出標志
}
/**********************************************************************************************************/
//定時器1
void zd3() interrupt 3????????? ?//T1中斷用來掃描數碼管和計800MS啟動模塊
{
?????? TH1=0xf8;
?????? TL1=0x30;????????????????????????? //定時2ms
?????? Key_();?????????????????????????????? //掃描按鍵
?????? Display();??????????????????????????? //掃描顯示
?????? timer++;?????????????????????? //變量加
?????? if(flag_BJ==1)??????????????????????????? ? //報警開
?????? {
????????????? Feng=0;
?????? }
?????? if(timer>=400)???????????????????? //400次就是800ms
?????? {
????????????? timer=0;
????????????? TX=1;?????????????????? ????????? //800MS? 啟動一次模塊
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? _nop_();
????????????? TX=0;
?????? }
}
/**********************************************************************************************************/
//主函數
void main(void)
{?
?????? TMOD=0x11;??????? ??//設T0為方式1,GATE=1;
?????? TH0=0;
?????? TL0=0;?????????
?????? TH1=0xf8;??????????? ??//2MS定時
?????? TL1=0x30;
?????? ET0=1;??????????????????????? //允許T0中斷
?????? ET1=1;???????????????? ?? //允許T1中斷
?????? TR1=1;???????????????? ?? //開啟定時器
?????? EA=1;???????????????????????????????? //開啟總中斷
?????? init_eeprom();? //開始初始化保存的數據?
?????? while(1)
?????? {
????????????? while(!RX);?????????? //當RX為零時等待
????????????? TR0=1;???????????????? //開啟計數
????????????? while(RX);??????????? //當RX為1計數并等待
????????????? TR0=0;???????????????? //關閉計數
????????????? Conut();??????????????? //計算
?????? }
}
pan sQ?Rn?9