摘要STC89C52是STC系列單片機里應用比較廣泛的一款,在自動控制領域里享有很高的價值,以其易用性和多功能性受到了廣大電子設計愛好者的好評。本次設計主要是利用STC89C52單片機、超聲波傳感器完成測距報警系統的制作,以STC89C52為主控芯片,利用超聲波對距離的檢測,將前方物體的距離探測出來,然后單片機處理運算,與設定的報警距離值進行比較判斷,當測得距離小于設定值時,STC89C52發出指令控制蜂鳴器報警。
1 緒論
1.1 項目研究背景及意義
由于超聲測距是一種非接觸檢測技術,不受光線、被測對象顏色等的影響,較其它儀器更衛生,更耐潮濕、粉塵、高溫、腐蝕氣體等惡劣環境,具有少維護、不污染、高可靠、長壽命等特點。因此可廣泛應用于紙業、礦業、電廠、化工業、水處理廠、污水處理廠、農業用水、環保檢測、食品(酒業、飲料業、添加劑、食用油、奶制品)、防汛、水文、明渠、空間定位、公路限高等行業中。可在不同環境中進行距離準確度在線標定,可直接用于水、酒、糖、飲料等液位控制,可進行差值設定,直接顯示各種液位罐的液位、料位高度。因此,超聲在空氣中測距在特殊環境下有較廣泛的應用。利用超聲波檢測往往比較迅速、方便、計算簡單、易于實現實時控制,并且在測量精度方面能達到工業實用的指標要求,因此為了使移動機器人能夠自動躲避障礙物行走,就必須裝備測距系統,以使其及時獲取距障礙物的位置信息(距離和方向)。因此超聲波測距在移動機器人的研究上得到了廣泛的應用。同時由于超聲波測距系統具有以上的這些優點,因此在汽車倒車雷達的研制方面也得到了廣泛的應用。
2 總體設計方案及論證
2.1 總體方案設計 本設計包括硬件和軟件設計兩個部分。模塊劃分為數據采集、按鍵控制、四位數碼管顯示、報警等子模塊。電路結構可劃分為:超聲波傳感器、蜂鳴器、單片機控制電路。就此設計的核心模塊來說,單片機就是設計的中心單元,所以此系統也是單片機應用系統的一種應用。單片機應用系統也是有硬件和軟件組成。硬件包括單片機、輸入/輸出設備、以及外圍應用電路等組成的系統,軟件是各種工作程序的總稱。單片機應用系統的研制過程包括總體設計、硬件設計、軟件設計等幾個階段。系統采用STC89C52單片機作為核心控制單元,當測得的距離小于設定距離時,主控芯片將測得的數值與設定值進行比較處理。然后控制蜂鳴器報警。系統總體的設計方框圖如圖1所示。
圖1 系統方框圖(見附件)
3 硬件實現及單元電路設計
3.1 主控制模塊
主控制最小系統電路如圖2所示。

圖2 最小系統
硬件電路總設計見圖3,從以上的分析可知在本設計中要用到如下器件: STC89C52、超聲波傳感器、按鍵、四位數碼管、蜂鳴器等一些單片機外圍應用電路。其中D1為電源工作指示燈。電路中用到3個按鍵,一個是設定鍵, 一個加鍵,一個減鍵。

圖3 總設計電路圖
3.2 電源設計
電源部分的設計采用3節5號干電池4.5V供電。
3.3 超聲波測試模塊 超聲波模塊采用現成的HC-SR04超聲波模塊,該模塊可提供 2cm-400cm 的非接觸式距離感測功能,測距精度可達高到 3mm。模塊包括超聲波發射器、接收器與控制電路。基本工作原理:采用 IO 口 TRIG 觸發測距,給至少 10us 的高電平信號;模塊自動發送 8 個 40khz的方波,自動檢測是否有信號返回;有信號返回,通過 IO 口 ECHO 輸出一個高電平,高電平持續的時間就是超聲波從發射到返回的時間。測試距離=(高電平時間*聲速(340M/S))/2。實物如下圖4。其中VCC 供5V 電源,GND 為地線,TRIG 觸發控制信號輸入,ECHO 回響信號輸出等四支線。

超聲波探測模塊HC-SR04的使用方法如下:IO口觸發,給Trig口至少10us的高電平,啟動測量;模塊自動發送8個40Khz的方波,自動檢測是否有信號返回;有信號返回,通過IO口Echo輸出一個高電平,高電平持續的時間就是超聲波從發射到返回的時間,測試距離=(高電平時間*340)/ 2,單位為m。程序中測試功能主要由兩個函數完成。
實現中采用定時器0進行定時測量,8分頻,TCNTT0預設值0XCE,當timer0溢出中斷發生2500次時為125ms,計算公式為(單位:ms):
T = (定時器0溢出次數 * (0XFF - 0XCE))/ 1000
其中定時器0初值計算依據分頻不同而有差異。
3.3.1 超聲波的特性聲音是與人類生活緊密相關的一種自然現象。當聲的頻率高到超過人耳聽覺的頻率極限(根據大量實驗數據統計,取整數為20000赫茲)時,人們就會覺察不出周圍聲的存在,因而稱這種高頻率的聲為“超”聲。人的聽覺范圍如圖5所示。

圖5 人的聽覺范圍
超聲波的特性有:
(1)束射特性
由于超聲波的波長短,超聲波射線可以和光線一樣,能夠反射、折射,也能聚焦,而且遵守幾何光學上的所有定律。即超聲波射線從一種物質表面反射時,入射角等于反射角,當射線透過一種物質進入另一種密度不同的物質時就會產生折射現象,也就是要改變它的傳播方向,兩種物質的密度差別愈大,則折射率也愈大。
(2)吸收特性
聲波在各種介質中傳播時,隨著傳播距離的增加,其強度會逐漸減弱,這是因為介質要吸收掉它的部分能量。對于同一介質,聲波的頻率越高,介質吸收就越強。對于一個頻率一定的聲波,在氣體中傳播時吸收尤為歷害,在液體中傳播時吸收就比較弱,在固體中傳播時吸收是最小的。
(3)超聲波的能量傳遞特性
超聲波之所以能在各個工業部門中得到廣泛的應用,主要原因還在于比聲波具有強大得多的功率。為什么有這么強大的功率呢?因為當聲波進入某一介質中時,由于聲波的作用使物質中的分子也隨之振動,振動的頻率和聲波頻率—樣,分子振動的頻率決定了分子振動的速度。頻率愈高速度愈大。物資分子由于振動所獲得的能量除了與分子本身的質量有關外,主要是由分子的振動速度的平方決定的,所以如果聲波的頻率愈高,也就是物質分子愈能得到更高的能量。超聲波的頻率比普通聲波要高出很多,所以它可以使物質分子獲得很大的能量;換句話來說,超聲波本身就可以供給物質分子足夠大的功率。
(4)超聲波的聲壓特性
當聲波進入某物體時,由于聲波振動使物質分子相互之間產生壓縮和稀疏的作用,將使物質所受的壓力產生變化。由于聲波振動引起附加壓力現象叫聲壓作用。
3.3.2 超聲波換能器完成產生超聲波和接收超聲波這種功能的裝置就是超聲波傳感器,習慣上稱為超聲換能器,或者超聲波探頭。超聲波探頭主要由壓電晶片組成,既可以發射超聲波,也可以接收超聲波。小功率超聲探頭多用作探測方面。它有許多不同的結構,可分直探頭(縱波)、斜探頭(橫波)、表面波探頭(表面波)、蘭姆波探頭(蘭姆波)、雙探頭(一個探頭反射、一個探頭接收)等。
超聲探頭的核心是其塑料外套或者金屬外套中的一塊壓電晶片。構成晶片的材料可以有許多種。由于晶片的大小,如直徑和厚度也各不相同,因此每個探頭的性能都是不同的,我們使用前必須預先了解清楚該探頭的性能參數。
超聲波傳感器的主要性能指標包括:
(1)工作頻率。工作頻率就是壓電晶片的共振頻率。當加到它兩端的交流電壓的頻率和晶片的共振頻率相等時,輸出的能量最大,靈敏度也最高。
(2)工作溫度。由于壓電材料的居里點一般比較高,特別時診斷用超聲波探頭使用功率較小,所以工作溫度比較低,可以長時間地工作而不失效。醫療用的超聲探頭的溫度比較高,需要單獨的制冷設備。
(3)靈敏度。主要取決于制造晶片本身。機電耦合系數大,靈敏度高。
人類能聽到的聲音頻率范圍為:20Hz~20kHz,即為可聽聲波,超出此頻率范圍的聲音,即20Hz以下頻率的聲音稱為低頻聲波,20kHz以上頻率的聲音稱為超聲波。超聲波為直線傳播方式,頻率越高,繞射能力越弱,但反射能力越強。為此,利用超聲波的這種性能就可制成超聲波傳感器。另外,超聲波在空氣中的傳播速度較慢,為340m/s,這就使得超聲波傳感器使用變得非常簡便。我們選用壓電式超聲波傳感器。它的探頭常用材料是壓電晶體和壓電陶瓷,是利用壓電材料的壓電效應來進行工作的。逆壓電效應將高頻電振動轉換成高頻機械振動,從而產生超聲波,可作為發射探頭;而利用正壓電效應,將超聲振動波轉換成電信號,可作為接收探頭。
為了研究和利用超聲波,人們已經設計和制成了許多種超聲波發生器。總體上講,超聲波發生器大體可以分為兩大類:一類是用電氣方式產生超聲波,一類是用機械方式產生超聲波。電氣方式包括壓電型、磁致伸縮型和電動型等;機械方式有加爾統笛、液哨和氣流旋笛等。它們所產生的超聲波的頻率、功率和聲波特性各不相同,因而用途也各不相同。目前較為常用的是壓電式超聲波發生器。
圖6 超聲波傳感器結構
壓電式超聲波發生器實際上是利用壓電晶體的諧振來工作的。超聲波發生器內部結構如圖所示,它有兩個壓電晶片和一個共振板。當它的兩極外加脈沖信號,其頻率等于壓電晶片的固有振蕩頻率時,壓電晶片將會發生共振,并帶動共振板振動,便產生超聲波。反之,如果兩電極間未外加電壓,當共振板接收到超聲波時,將壓迫壓電晶片作振動,將機械能轉換為電信號,這時它就成為超聲波接收器了。如圖6所示。
3.4 超聲波傳感器原理
市面上常見的超聲波傳感器多為開放型,其內部結構如圖7所示,一個復合式振動器被靈活地固定在底座上。該復合式振動器是由諧振器以及一個金屬片和一個壓電陶瓷片組成的雙壓電晶片元件振動器。諧振器呈喇叭形,目的是能有效地輻射由于振動而產生的超聲波,并且可以有效地使超聲波聚集在振動器的中央部位。
當電壓作用于壓電陶瓷時,就會隨電壓和頻率的變化產生機械變形。另一方面,當振動壓電陶瓷時,則會產生一個電荷。利用這一原理,當給由兩片壓電陶瓷或一片壓電陶瓷和一個金屬片構成的振動器,所謂叫雙壓電晶片元件,施加一個電信號時,就會因彎曲振動發射出超聲波。相反,當向雙壓電晶片元件施加超聲振動時,就會產生一個電信號。基于以上作用,便可以將壓電陶瓷用作超聲波傳感器。
圖7 超聲波內部結構
超聲波是一種在彈性介質中的機械振蕩,其頻率超過20KHz,分橫向振蕩和縱向振蕩兩種,超聲波可以在氣體、液體及固體中傳播,其傳播速度不同。它有折射和反射現象,且在傳播過程中有衰減。
超聲波的基本特性如下所述:
波的傳播速度是用頻率乘以波長來表示。電磁波的傳播速度是3×108m/s,而聲波在空氣中的傳播速度很慢,約為344m/s (20℃時)。在這種比較低的傳播速度下,波長很短,這就意味著可以獲得較高的距離和方向分辨率。正是由于這種較高的分辨率特性,才使我們有可能在進行測量時獲得很高的精確度。
要探測某個物體是否存在,超聲波就能夠在該物體上得到反射。由于金屬、木材、混凝土、玻璃、橡膠和紙等可以反射近乎100%的超聲波,因此我們可以很容易地發現這些物體。由于布、棉花、絨毛等可以吸收超聲波,因此很難利用超聲波探測到它們。同時,由于不規則反射,通常可能很難探測到凹凸表面以及斜坡表面的物體,這些因素決定了超聲波的理想測試環境是在空曠的場所,并且測試物體必須反射超聲波。
聲波傳播的速度“c”可以用下列公式表示。c=331.5+0.607t (m/s) 式中,t=溫度 (℃)也就是說,聲音傳播速度隨周圍溫度的變化而有所不同。因此,要精確的測量與某個物體之間的距離時,始終檢查周圍溫度是十分必要的,尤其冬季室內外溫差較大,對超聲波測距的精度影響很大,此時可用18B20作溫度補償來減小溫度變化所帶來的測量誤差,考慮到本設計的測試環境是在室內,而且超聲波主要是用于測距功能,對測量精度要求不高,所以關于溫度效應對系統的影響問題在這里不做深入的探討。
4. 衰減
傳播到空氣中的超聲波強度隨距離的變化成比例地減弱,這是因為衍射現象所導致的在球形表面上的擴散損失,也是因為介質吸收能量產生的吸收損失。如圖8所示,超聲波的頻率越高,衰減率就越高,超聲波的傳播距離也就越短,由此可見超聲波的衰減特性直接影響了超聲波傳感器有效距離。
圖8 聲壓在不同距離下的衰減特性
5.聲壓特性
聲壓級 (S.P.L.) 是表示音量的單位,利用下列公式予以表示。
S.P.L.= 20logP/Pre (dB)式中,“P”為有效聲壓 (μbar),“Pre”為參考聲壓 (2×10-4μbar)如圖6所示為幾種常用超聲波傳感器的聲壓圖。
圖9 超聲波傳感器的聲壓圖
6.靈敏度特性
靈敏度是表示聲音接收級的單位,使用下列公式予以表示。
靈敏度= 20log E/P (dB)式中,“E”為所產生的電壓 (Vrms),“P”為輸入聲壓(μbar)。超聲波傳感器的靈敏度直接影響著系統測距范圍,如圖7所示為幾種中常見超聲波傳感器的靈敏度圖,從圖中可以發現40KHz時傳感器的聲壓級最高,也就是說40KHz時所對應的靈敏度最高。
圖10 超聲波傳感器靈敏度示意圖
7.輻射特性
把超聲波傳感器安裝在臺面上。然后,測量角度與聲壓 (靈敏度) 之間的關系。為了準確地表達輻射,與前部相對比,聲壓 (靈敏度) 級衰減6dB的角度被稱為半衰減角度,用θ1/2表示。超聲波設備的外表面尺寸較小易于獲得精確的輻射角度。如圖11所示為幾種常見超聲波傳感器的輻射特性示意圖。
圖11 超聲波傳感器輻射特性示意圖
分析以上研究結果不難看出超聲波傳感器工作在40KHz范圍內具有最大的聲壓級和最高的靈敏度。
3.5 測距分析
超聲波發射器向某一方向發射超聲波,在發射時刻的同時開始計時,超聲波在空氣中傳播,途中碰到障礙物就立即返回來,超聲波接收器收到反射波就立即停止計時。超聲波在空氣中的傳播速度為340m/s,根據計時器記錄的時間t,就可以計算出發射點距障礙物的距離(s),即:s=340t/2
最常用的超聲測距的方法是回聲探測法,超聲波發射器向某一方向發射超聲波,在發射時刻的同時計數器開始計時,超聲波在空氣中傳播,途中碰到障礙物面阻擋就立即反射回來,超聲波接收器收到反射回的超聲波就立即停止計時。超聲波在空氣中的傳播速度為340m/s,根據計時器記錄的時間t,就可以計算出發射點距障礙物面的距離s,即:s=340t/2。
由于超聲波也是一種聲波,其聲速V與溫度有關。在使用時,如果傳播介質溫度變化不大,則可近似認為超聲波速度在傳播的過程中是基本不變的。如果對測距精度要求很高,則應通過溫度補償的方法對測量結果加以數值校正。聲速確定后,
只要測得超聲波往返的時間,即可求得距離。這就是超聲波測距儀的基本原理。如圖12所示:(見附件)
圖12 超聲波的測距原理
(3-1)
(3-2)
式中:L---兩探頭之間中心距離的一半.
又知道超聲波傳播的距離為:

( 3-3)
式中:v—超聲波在介質中的傳播速度;
t—超聲波從發射到接收所需要的時間.
將(3—2)、(3—3)代入(3-1)中得:

( 3-4)
其中,超聲波的傳播速度v在一定的溫度下是一個常數(例如在溫度T=30度時,V=349m/s);當需要測量的距離H遠遠大于L時,則(3—4)變為:

( 3-5)
所以,只要需要測量出超聲波傳播的時間t,就可以得出測量的距離H.
3.6 時鐘電路的設計
XTAL1和XTAL2分別為反向放大器的輸入和輸出。該反向放大器可以配置為片內振蕩器。石晶振蕩和陶瓷振蕩均可采用。如采用外部時鐘源驅動器件,XTAL2應不接。
因為一個機器周期含有6個狀態周期,而每個狀態周期為2個振蕩周期,所以一個機器周期共有12個振蕩周期,如果外接石英晶體振蕩器的振蕩頻率為12MHZ,一個振蕩周期為1/12us,故而一個機器周期為1us。如圖13所示為時鐘電路。
圖13 時鐘電路圖
3.7 復位電路的設計
復位方法一般有上電自動復位和外部按鍵手動復位,單片機在時鐘電路工作以后, 在RESET端持續給出2個機器周期的高電平時就可以完成復位操作。例如使用晶振頻率為12MHz時,則復位信號持續時間應不小于2us。本設計采用的是自動復位電路。如圖14示為復位電路。
圖14 復位電路圖
3.8 聲音報警電路的設計
如下圖所示,用一個Speaker和三極管、電阻接到單片機的P13引腳上,構成聲音報警電路,如圖15示為聲音報警電路。
圖15 聲音報警電路圖
3.9 顯示模塊
顯示模塊采用數碼管顯示接口電路如圖16
圖16 數碼管電路
4 軟件設計 4.1 主程序工作流程圖
按上述工作原理和硬件結構分析可知系統主程序工作流程圖如下圖17所示;
圖17 主程序工作流程圖
超聲波探測程序流程圖:
5 總結
本設計研究了一種基于單片機技術的超聲波智能測距報警系統。該系統通過以STC89C52單片機為工作處理器核心,超聲波傳感器,它是一種新穎的被動式超聲波探測器件,能夠以非接觸測出前方物體距離,并將其轉化為相應的電信號輸出.該報警器的最大特點就是使用戶能夠操作簡單、易懂、靈活;且安裝方便、智能性高、誤報率低。隨著現代人們安全意識的增強以及科學技術的快速發展,相信報警器必將在更廣闊的領域得到更深層次的應用。
6 參考文獻
[1] 吳政江. 單片機控制紅外線防盜報警器[J]. 錦州師范學院學報, 2001.
[2] 宋文緒. 傳感器與檢測技術[M]. 北京: 高等教育出版社, 2004.
[3] 余錫存. 單片機原理及接口技術[M]. 西安: 西安電子科技大學出版社, 2000.
[4] 唐桃波, 陳玉林. 基于AT89C51的智能無線安防報警器 [J]. 電子設計應用, 2003, 5(6): 49~51.
[5] 李全利. 單片機原理及接口技術[M]. 北京: 北京航空航天大學出版社, 2004.
[6] 薛均義, 張彥斌. MCS-51系列單片微型計算機及其應用[M]. 西安: 西安交通大學出版社, 2005.
[7] 徐愛鈞, 彭秀華. 單片機高級語言C51應用程序設計[M]. 北京: 北京航空航天大學出版社, 2006.
[8] 康華光. 電子技術基礎(模擬部分)[M]. 北京: 高等教育出版社, 2004.
附 錄附件1:原理圖

單片機源程序如下:
- #include <reg52.h>
- #include <intrins.h>
- #include "eepom52.h"
- #define uchar unsigned char
- #define uint unsigned int
-
- //數碼管段選定義 0 1 2 3 4 5 6 7 8 9
- uchar code smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
- 0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff}; //斷碼
- //數碼管位選定義
- uchar code smg_we[]={0xe0,0xd0,0xb0,0x70};
- uchar dis_smg[8] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};
-
- sbit smg_we1 = P3^4; //數碼管位選定義
- sbit smg_we2 = P3^5;
- sbit smg_we3 = P3^6;
- sbit smg_we4 = P3^7;
-
- sbit c_send = P3^2; //超聲波發射
- sbit c_recive = P3^3; //超聲波接收
- uchar flag_hc_value; //超聲波中間變量
-
- sbit beep = P2^3; //蜂鳴器IO口定義
- bit flag_key_b_en,flag_key_set_en; //按鍵蜂鳴器使能
-
-
- uchar smg_i = 3; //顯示數碼管的個位數
- bit flag_300ms ;
-
- bit key_500ms ;
-
-
- long distance; //距離
- uint set_d; //距離
- bit flag_csb_juli; //超聲波超出量程
- uint flag_time0; //用來保存定時器0的時候的
-
- // 按鍵的IO變量的定義
- uchar key_can; //按鍵值的變量
- uchar zd_break_en,zd_break_value; //自動退出設置界面
- uchar menu_shudu = 10; //用來控制連加的速度
- bit flag_lj_en; //按鍵連加使能
- bit flag_lj_3_en; //按鍵連3次連加后使能 加的數就越大了
- uchar key_time,flag_value; //用做連加的中間變量
- uchar menu_1; //菜單設計的變量
- uchar a_a;
-
-
- /***********************1ms延時函數*****************************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<120;j++);
- }
-
- /***********************處理距離函數****************************/
- void smg_display()
- {
- dis_smg[0] = smg_du[distance % 10];
- dis_smg[1] = smg_du[distance / 10 % 10];
- dis_smg[2] = smg_du[distance / 100 % 10] & 0x7f;
- }
-
- /******************把數據保存到單片機內部eepom中******************/
- void write_eepom()
- {
- SectorErase(0x2000);
- byte_write(0x2000, set_d % 256);
- byte_write(0x2001, set_d / 256);
- byte_write(0x2058, a_a);
- }
-
- /******************把數據從單片機內部eepom中讀出來*****************/
- void read_eepom()
- {
- set_d = byte_read(0x2001);
- set_d <<= 8;
- set_d |= byte_read(0x2000);
- a_a = byte_read(0x2058);
- }
-
- /**************開機自檢eepom初始化*****************/
- void init_eepom()
- {
- read_eepom(); //先讀
- if(a_a != 1) //新的單片機初始單片機內問EEPOM
- {
- set_d = 100;
- a_a = 1;
- write_eepom();
- }
- }
- /****************獨立按鍵處理函數********************/
- void key()
- {
- static uchar key_new = 0,key_old = 0,key_value = 0;
- if(key_new == 0)
- { //按鍵松開的時候做松手檢測
- if((P2 & 0x07) == 0x07)
- key_value ++;
- else
- key_value = 0;
- if(key_value >= 5)
- {
- key_value = 0;
- key_new = 1;
- flag_lj_en = 0; //關閉連加使能
- flag_lj_3_en = 0; //關閉3秒后使能
- flag_value = 0; //清零
- key_time = 0;
- write_eepom();
- }
- }
- else
- {
- if((P2 & 0x07) != 0x07)
- key_value ++; //按鍵按下的時候
- else
- key_value = 0;
- if(key_value >= 5)
- {
- key_value = 0;
- key_new = 0;
- flag_lj_en = 1; //連加使能
- zd_break_en = 1; //自動退出設置界使能
- zd_break_value = 0; //自動退出設置界變量清零
- flag_key_b_en = 1; //按鍵蜂鳴器使能
- }
- }
- key_can = 20;
- if(key_500ms == 1) //連加
- {
- key_500ms = 0;
- key_new = 0;
- key_old = 1;
- zd_break_value = 0;
- }
- if((key_new == 0) && (key_old == 1))
- {
- switch(P2 & 0x07)
- {
- case 0x06: key_can = 3; break; //得到k2鍵值
- case 0x05: key_can = 2; break; //得到k3鍵值
- case 0x03: key_can = 1; break; //得到k4鍵值
- }
- // dis_smg[3] = smg_du[key_can % 10];
-
- }
- key_old = key_new;
- }
-
-
- void smg_we_switch(uchar i)
- {
- switch(i)
- {
- case 0: smg_we1 = 0; smg_we2 = 1; smg_we3 = 1; smg_we4 = 1; break;
- case 1: smg_we1 = 1; smg_we2 = 0; smg_we3 = 1; smg_we4 = 1; break;
- case 2: smg_we1 = 1; smg_we2 = 1; smg_we3 = 0; smg_we4 = 1; break;
- case 3: smg_we1 = 1; smg_we2 = 1; smg_we3 = 1; smg_we4 = 0; break;
- }
- }
-
- /***********************數碼顯示函數*****************************/
- void display()
- {
- static uchar i;
- i++;
- if(i >= smg_i)
- i = 0;
- // P1 = 0xff; //段選
- // P3 = 0xf0 | (P3 & 0x0f); //位選
- // P3 = smg_we[i] | (P3 & 0x0f); //位選
- smg_we_switch(i);
- P1 = dis_smg[i]; //段選
-
- }
-
- void delay()
- {
- _nop_(); //執行一條_nop_()指令就是1us
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
-
-
- /*********************超聲波測距程序*****************************/
- void send_wave()
- {
- c_send = 1; //10us的高電平觸發
- delay();
- c_send = 0;
- TH0 = 0; //給定時器0清零
- TL0 = 0;
- TR0 = 0; //關定時器0定時
- flag_hc_value = 0;
- while(!c_recive); //當c_recive為零時等待
- TR0=1;
- while(c_recive) //當c_recive為1計數并等待
- {
- flag_time0 = TH0 * 256 + TL0;
- if((flag_hc_value > 1) || (flag_time0 > 65000)) //當超聲波超過測量范圍時,顯示3個888
- {
- TR0 = 0;
- flag_csb_juli = 2;
- distance = 888;
- flag_hc_value = 0;
- break ;
- }
- else
- {
- flag_csb_juli = 1;
- }
- }
- if(flag_csb_juli == 1)
- {
- TR0=0; //關定時器0定時
- distance = TH0; //讀出定時器0的時間
- distance = distance * 256 + TL0;
- distance +=( flag_hc_value * 65536);//算出超聲波測距的時間 得到單位是ms
- distance *= 0.017; // 0.017 = 340M / 2 = 170M = 0.017M 算出來是米
- if(distance > 350) //距離 = 速度 * 時間
- {
- distance = 888; //如果大于3.8m就超出超聲波的量程
- }
- }
- }
-
-
- /*********************定時器0、定時器1初始化******************/
- void time_init()
- {
- EA = 1; //開總中斷
- TMOD = 0X11; //定時器0、定時器1工作方式1
- ET0 = 1; //開定時器0中斷
- TR0 = 1; //允許定時器0定時
- ET1 = 1; //開定時器1中斷
- TR1 = 1; //允許定時器1定時
- }
-
- /****************按鍵處理數碼管顯示函數***************/
- void key_with()
- {
- if(key_can == 1)
- {
- menu_1 ++;
- if(menu_1 >= 2)
- {
- menu_1 = 0;
- }
- if(menu_1 == 0)
- {
- menu_shudu = 20;
- dis_smg[0] = smg_du[distance % 10];
- dis_smg[1] = smg_du[distance / 10 % 10] ;
- dis_smg[2] = smg_du[distance / 100 % 10] & 0x7f;
- smg_i = 3;
- }
- if(menu_1 == 1)
- {
- menu_shudu = 1;
- dis_smg[0] = smg_du[set_d % 10];
- dis_smg[1] = smg_du[set_d / 10 % 10];
- dis_smg[2] = smg_du[set_d / 100 % 10] & 0x7f ;
- dis_smg[3] = 0x88;
- smg_i = 4;
- }
- }
- if(menu_1 == 1) //設置高溫報警
- {
- if(flag_lj_3_en == 0) //三次連加之后速度加快
- menu_shudu = 10 ; //500ms 加減一次
- else
- menu_shudu = 1; //250ms 加減一次
- if(key_can == 2)
- {
- set_d ++ ; //按鍵按下未松開自動加三次
- if(set_d > 350)
- set_d = 350;
- dis_smg[0] = smg_du[set_d % 10]; //取小數顯示
- dis_smg[1] = smg_du[set_d / 10 % 10] ; //取個位顯示
- dis_smg[2] = smg_du[set_d / 100 % 10] & 0x7f; //取十位顯示
- dis_smg[3] = 0x88; //a
- }
- if(key_can == 3)
- {
- set_d -- ; //按鍵按下未松開自動加三次
- if(set_d <= 1)
- set_d = 1;
- dis_smg[0] = smg_du[set_d % 10]; //取小數顯示
- dis_smg[1] = smg_du[set_d / 10 % 10] ; //取個位顯示
- dis_smg[2] = smg_du[set_d / 100 % 10] & 0x7f ; //取十位顯示
- dis_smg[3] = 0x88; //a
- }
- // write_eepom();
- }
- }
-
- /****************報警函數***************/
- void clock_h_l()
- {
- static uchar value;
- if(distance <= set_d)
- {
- value ++; //消除實際距離在設定距離左右變化時的干擾
- if(value >= 5)
- {
- beep = ~beep; //蜂鳴器報警
- }
- }
- else
- {
- value = 0;
- beep = 1; //取消報警
- }
- }
-
- /****************按鍵按下蜂鳴器響下**********************/
- void key_beep()
- {
- static uint value;
- if((flag_key_b_en == 1) && (flag_key_set_en == 1))
- {
- beep = 0; //打開蜂鳴器
- value ++;
- if(value > 800)
- {
- value = 0;
- flag_key_b_en = 0;
- beep = 1;//關閉蜂鳴器
- }
- }
- }
-
-
- void main()
- {
- send_wave(); //測距離函數
- smg_display(); //處理距離顯示函數
- time_init();
- init_eepom(); //讀eepom數據
- while(1)
- {
- if(flag_300ms == 1)
- {
- flag_300ms = 0;
- clock_h_l(); //報警函數
- send_wave(); //測距離函數
- if(menu_1 == 0)
- smg_display(); //處理距離顯示函數
- if(zd_break_en == 1) //自動退出設置界面程序
- {
- zd_break_value ++; //每300ms加一次
- if(zd_break_value > 100) //30秒后自動退出設置界面
- {
- menu_1 = 0; //
- smg_i = 3;
- zd_break_en = 0;
- zd_break_value = 0;
- }
- }
- }
- key(); //按鍵函數
- if(key_can < 10)
- {
- key_with(); //按鍵處理函數
- }
- }
- }
-
-
- /*********************定時器0中斷服務程序 用做超聲波測距的************************/
- void time0_int() interrupt 1
- {
- set_d ++; // TH0 TL0 到65536后溢出中斷
- }
-
- /*********************定時器0中斷服務程序************************/
- void time1_int() interrupt 3
- {
- static uchar value; //定時10ms中斷一次
- TH1 = 0xf8;
- TL1 = 0x30; //2ms
- display(); //數碼管顯示函數
- value++;
- if(value >= 150)
- {
- value = 0;
- flag_300ms = 1;
- }
- if(value % 25 == 0)
- {
- if(flag_lj_en == 1) //按下按鍵使能 50ms
- {
- key_time ++;
- if(key_time >= menu_shudu) //500ms
- {
- key_time = 0;
- key_500ms = 1; //500ms
- flag_value ++;
- if(flag_value >= 3)
- {
- flag_value = 10;
- flag_lj_3_en = 1; //3次后1.5秒后連加大些
- }
- }
- }
- }
- }
復制代碼
0.png (52.11 KB, 下載次數: 104)
下載附件
2018-10-24 01:36 上傳
全部資料51hei下載地址:
超聲波測距儀模塊 數碼管.rar
(11.14 MB, 下載次數: 785)
2018-10-24 01:41 上傳
點擊文件名下載附件
下載積分: 黑幣 -5