基于51單片機(jī)的超聲波測(cè)距儀設(shè)計(jì)方案


基于51單片機(jī)的超聲波測(cè)距儀設(shè)計(jì)方案
一、 引言
超聲波測(cè)距技術(shù)作為一種非接觸式測(cè)量方法,因其高精度、高可靠性、對(duì)環(huán)境適應(yīng)性強(qiáng)等優(yōu)點(diǎn),在工業(yè)自動(dòng)化、機(jī)器人導(dǎo)航、物聯(lián)網(wǎng)設(shè)備、智能家居以及安防領(lǐng)域有著廣泛的應(yīng)用前景。超聲波測(cè)距儀通過發(fā)射超聲波脈沖并接收其回波,利用聲波在介質(zhì)中傳播的速度恒定性,通過測(cè)量超聲波從發(fā)射到接收的總時(shí)間來精確計(jì)算出被測(cè)物體與傳感器之間的距離。本設(shè)計(jì)方案將深入探討基于經(jīng)典的51系列單片機(jī)實(shí)現(xiàn)超聲波測(cè)距儀的詳細(xì)過程,涵蓋其系統(tǒng)構(gòu)成、硬件選型、軟件設(shè)計(jì)以及可能遇到的問題與解決方案,旨在為讀者提供一個(gè)全面且實(shí)用的設(shè)計(jì)指南,使其能夠成功構(gòu)建并優(yōu)化自己的超聲波測(cè)距系統(tǒng)。51單片機(jī)憑借其成熟的生態(tài)系統(tǒng)、豐富的資料、易學(xué)易用等特點(diǎn),成為初學(xué)者和工程師進(jìn)行嵌入式系統(tǒng)設(shè)計(jì)的理想選擇,尤其適用于對(duì)成本和功耗有一定要求的中小型項(xiàng)目。本文將著重分析每個(gè)關(guān)鍵元器件的選擇理由及其在整個(gè)系統(tǒng)中的功能,確保讀者對(duì)設(shè)計(jì)的每一個(gè)環(huán)節(jié)都有清晰的認(rèn)識(shí)。
二、 超聲波測(cè)距原理
超聲波測(cè)距的基本原理是利用超聲波在空氣中傳播的時(shí)間與距離之間的關(guān)系。當(dāng)超聲波發(fā)射器發(fā)出超聲波脈沖后,該脈沖在空氣中傳播,遇到障礙物后會(huì)被反射回來,并被超聲波接收器接收。我們知道聲波在介質(zhì)中傳播的速度是一個(gè)相對(duì)穩(wěn)定的常數(shù)(在標(biāo)準(zhǔn)大氣壓和20℃時(shí),聲速約為343米/秒)。通過精確測(cè)量從超聲波發(fā)射到接收到回波的總時(shí)間t,就可以利用簡(jiǎn)單的物理公式計(jì)算出距離D。由于超聲波是從發(fā)射器發(fā)出,傳播到障礙物后再反射回接收器,因此這個(gè)時(shí)間t實(shí)際上是超聲波往返的總時(shí)間。所以,單程距離D的計(jì)算公式為:D=2v×t其中,v是超聲波在當(dāng)前介質(zhì)(通常是空氣)中的傳播速度。需要注意的是,聲速會(huì)受到環(huán)境溫度、濕度、氣壓等因素的影響。在實(shí)際應(yīng)用中,為了提高測(cè)距精度,通常需要對(duì)聲速進(jìn)行溫度補(bǔ)償。然而,對(duì)于大多數(shù)非高精度要求的應(yīng)用場(chǎng)景,可以采用一個(gè)固定的經(jīng)驗(yàn)值。51單片機(jī)在接收到回波信號(hào)后,會(huì)啟動(dòng)定時(shí)器計(jì)時(shí),直至接收到回波停止,從而得到超聲波的往返時(shí)間,再通過上述公式換算為距離。這一過程的精度高度依賴于單片機(jī)的定時(shí)器精度和對(duì)外界干擾的濾除能力。
三、 系統(tǒng)整體構(gòu)成
基于51單片機(jī)的超聲波測(cè)距儀主要由以下幾個(gè)核心模塊組成:主控模塊、超聲波收發(fā)模塊、顯示模塊、電源模塊和按鍵模塊(可選)。每個(gè)模塊協(xié)同工作,共同完成超聲波的發(fā)射、接收、時(shí)間測(cè)量、距離計(jì)算以及最終的顯示功能。主控模塊作為整個(gè)系統(tǒng)的大腦,負(fù)責(zé)協(xié)調(diào)各個(gè)模塊的工作,處理數(shù)據(jù)并進(jìn)行邏輯控制。超聲波收發(fā)模塊是實(shí)現(xiàn)測(cè)距功能的關(guān)鍵,包括超聲波發(fā)射電路和超聲波接收電路。顯示模塊則用于直觀地展示測(cè)量結(jié)果。電源模塊為整個(gè)系統(tǒng)提供穩(wěn)定的工作電壓。按鍵模塊(如果需要)可以用于模式切換、參數(shù)設(shè)置或校準(zhǔn)等功能,增加了系統(tǒng)的交互性。這種模塊化的設(shè)計(jì)思路使得系統(tǒng)的開發(fā)、調(diào)試和維護(hù)變得更加便捷高效,同時(shí)也為后續(xù)功能的擴(kuò)展預(yù)留了空間。
四、 主要元器件選型及作用分析
本部分將詳細(xì)介紹構(gòu)建超聲波測(cè)距儀所需的關(guān)鍵元器件,并深入分析其選擇原因、功能及在系統(tǒng)中的作用。
4.1 主控芯片:STC89C52RC/AT89C52
選擇理由: STC89C52RC和AT89C52是廣泛應(yīng)用于教學(xué)和工業(yè)控制領(lǐng)域的經(jīng)典51系列單片機(jī)。它們具有成熟的架構(gòu)、豐富的IO口資源、內(nèi)置定時(shí)器/計(jì)數(shù)器、串口通信能力以及片內(nèi)Flash存儲(chǔ)器。STC系列的單片機(jī)相比傳統(tǒng)的AT系列,通常具有更快的運(yùn)行速度、更寬的工作電壓范圍、更低的功耗和更為便捷的ISP(在系統(tǒng)編程)功能,無需專用編程器即可下載程序,極大地簡(jiǎn)化了開發(fā)流程。對(duì)于超聲波測(cè)距這種需要精確時(shí)間測(cè)量和實(shí)時(shí)數(shù)據(jù)處理的應(yīng)用,51單片機(jī)的定時(shí)器/計(jì)數(shù)器資源完全能夠滿足需求,其性價(jià)比極高,資料豐富,便于學(xué)習(xí)和開發(fā)。
功能:
控制超聲波模塊: 通過控制超聲波模塊的Trigger(觸發(fā))引腳發(fā)射超聲波,并通過Echo(回響)引腳接收回波信號(hào)。
時(shí)間測(cè)量: 利用其內(nèi)部的定時(shí)器/計(jì)數(shù)器功能,精確測(cè)量超聲波從發(fā)射到接收回波之間的時(shí)間間隔。例如,可以使用定時(shí)器T0或T1,設(shè)置為計(jì)數(shù)模式,通過捕捉Echo引腳的高電平持續(xù)時(shí)間來獲取時(shí)間。
數(shù)據(jù)處理: 根據(jù)測(cè)量到的時(shí)間,結(jié)合聲速計(jì)算出實(shí)際距離。
顯示控制: 控制LCD1602或數(shù)碼管顯示模塊,將計(jì)算出的距離值顯示出來。
系統(tǒng)協(xié)調(diào): 負(fù)責(zé)整個(gè)系統(tǒng)的工作流程調(diào)度,包括初始化、數(shù)據(jù)采集、計(jì)算、顯示刷新等。
具體型號(hào)分析: STC89C52RC具有8KB的Flash程序存儲(chǔ)器、512B的RAM、32個(gè)可編程I/O口、3個(gè)16位定時(shí)器/計(jì)數(shù)器、一個(gè)全雙工UART串口以及看門狗定時(shí)器。這些資源對(duì)于超聲波測(cè)距儀的設(shè)計(jì)綽綽有余。其工作頻率可達(dá)35MHz,足以提供足夠的指令執(zhí)行速度來處理實(shí)時(shí)測(cè)距任務(wù)。
4.2 超聲波測(cè)距模塊:HC-SR04
選擇理由: HC-SR04是一款集成度高、使用方便且性價(jià)比極高的超聲波測(cè)距模塊。它包含了超聲波發(fā)射器和接收器,以及相應(yīng)的控制電路,僅通過兩個(gè)引腳(Trig和Echo)即可完成測(cè)距功能,極大地簡(jiǎn)化了外部電路設(shè)計(jì)。其測(cè)量范圍通常在2cm至400cm之間,精度可達(dá)0.3cm,足以滿足大多數(shù)通用測(cè)距需求。模塊內(nèi)部已經(jīng)集成了超聲波發(fā)射和接收的壓電陶瓷片以及驅(qū)動(dòng)電路和信號(hào)處理電路,用戶無需關(guān)心超聲波信號(hào)的具體產(chǎn)生和接收細(xì)節(jié),只需關(guān)注Trig和Echo引腳的時(shí)序控制。
功能:
Trig(觸發(fā))引腳: 通過向該引腳輸入一個(gè)10微秒(us)以上的高電平脈沖,模塊會(huì)內(nèi)部自動(dòng)發(fā)射8個(gè)40KHz的超聲波脈沖。
Echo(回響)引腳: 當(dāng)超聲波模塊發(fā)射超聲波后,Echo引腳會(huì)變?yōu)楦唠娖健.?dāng)接收到回波信號(hào)時(shí),Echo引腳會(huì)變?yōu)榈碗娖健R虼耍珽cho引腳高電平的持續(xù)時(shí)間就代表了超聲波從發(fā)射到接收的總時(shí)間。
工作原理概覽: 51單片機(jī)首先給HC-SR04的Trig引腳一個(gè)短促的高電平脈沖,HC-SR04隨即發(fā)射超聲波。單片機(jī)同時(shí)啟動(dòng)定時(shí)器開始計(jì)時(shí)。超聲波遇到障礙物反射回來后,HC-SR04的Echo引腳會(huì)從低電平變?yōu)楦唠娖剑⒊掷m(xù)到接收到回波為止。單片機(jī)檢測(cè)到Echo引腳變?yōu)楦唠娖胶螅_始捕捉高電平的持續(xù)時(shí)間,當(dāng)Echo引腳再次變?yōu)榈碗娖綍r(shí),停止計(jì)時(shí)。根據(jù)計(jì)時(shí)器的時(shí)間差,即可計(jì)算出距離。這種簡(jiǎn)單而高效的接口設(shè)計(jì)是選擇HC-SR04的關(guān)鍵原因。
4.3 顯示模塊:LCD1602液晶顯示屏
選擇理由: LCD1602是一種經(jīng)典的字符型液晶顯示模塊,可以顯示兩行,每行16個(gè)字符。它結(jié)構(gòu)簡(jiǎn)單、價(jià)格便宜、接口友好,非常適合用于顯示簡(jiǎn)單的數(shù)字和文字信息,如距離值、單位等。與數(shù)碼管相比,LCD1602能夠顯示更多的信息,并且功耗較低,顯示效果更清晰。其內(nèi)部集成了LCD控制器,與單片機(jī)連接方便,通常通過并行或I2C(如果帶有轉(zhuǎn)換模塊)接口進(jìn)行通信。
功能: 接收來自51單片機(jī)的數(shù)據(jù)和控制命令,并將其轉(zhuǎn)換為可視的字符或數(shù)字顯示出來。在本設(shè)計(jì)中,它主要用于顯示測(cè)量到的距離值,例如“Distance: XX.XX cm”。
接口說明: LCD1602通常有16個(gè)引腳,包括數(shù)據(jù)線(D0-D7)、控制線(RS、RW、EN)和電源線。RS(Register Select)用于選擇命令寄存器或數(shù)據(jù)寄存器;RW(Read/Write)用于選擇讀寫模式;EN(Enable)用于使能操作。通過對(duì)這些引腳的電平組合和時(shí)序控制,單片機(jī)可以向LCD1602發(fā)送命令(如清屏、設(shè)置光標(biāo)位置)和顯示數(shù)據(jù)。
4.4 電源模塊:AMS1117-3.3/5.0V穩(wěn)壓模塊
選擇理由: 超聲波測(cè)距儀需要穩(wěn)定可靠的電源供應(yīng)。51單片機(jī)通常工作在5V,而HC-SR04模塊也推薦5V供電,但有些版本的LCD1602可能需要3.3V或5V。為了確保整個(gè)系統(tǒng)的穩(wěn)定運(yùn)行,通常會(huì)采用一個(gè)穩(wěn)壓模塊將外部電源(如9V電池或12V適配器)轉(zhuǎn)換為單片機(jī)和各模塊所需的穩(wěn)定電壓。AMS1117系列穩(wěn)壓芯片是常見的低壓差線性穩(wěn)壓器,具有輸出電壓穩(wěn)定、紋波小、功耗低、成本低廉等優(yōu)點(diǎn)。選擇帶有AMS1117芯片的模塊可以方便地將較高輸入電壓轉(zhuǎn)換為所需的5V或3.3V輸出。
功能: 將外部輸入的非穩(wěn)壓直流電源(例如直流9V或12V)轉(zhuǎn)換為系統(tǒng)所需的穩(wěn)定5V或3.3V直流電源,為單片機(jī)、超聲波模塊和顯示模塊提供可靠的工作電壓,避免因電壓波動(dòng)引起的系統(tǒng)不穩(wěn)定或誤動(dòng)作。
選擇原因: 盡管可以直接使用三端穩(wěn)壓芯片7805,但AMS1117系列具有更低的壓差,這意味著在輸入電壓與輸出電壓差較小的情況下也能保持穩(wěn)定輸出,且其封裝和集成度更適合模塊化設(shè)計(jì)。
4.5 其他輔助元器件
晶振: 通常為11.0592MHz或12MHz。
選擇理由: 晶振是單片機(jī)的心臟,為單片機(jī)提供穩(wěn)定的時(shí)鐘信號(hào)。11.0592MHz是一個(gè)常用值,因?yàn)樗墚a(chǎn)生標(biāo)準(zhǔn)的波特率,方便串口通信(如果需要)。12MHz則是一個(gè)常用的整數(shù)頻率,便于計(jì)算定時(shí)器和延時(shí)。
功能: 提供單片機(jī)系統(tǒng)時(shí)鐘,決定了單片機(jī)指令執(zhí)行速度和定時(shí)器/計(jì)數(shù)器的計(jì)時(shí)精度。
復(fù)位電路: 通常由一個(gè)10kΩ電阻和10μF電容組成。
選擇理由: 復(fù)位電路是單片機(jī)正常啟動(dòng)的必要條件。RC復(fù)位電路是最簡(jiǎn)單、最常用的復(fù)位方式,在系統(tǒng)上電時(shí)為單片機(jī)提供一個(gè)短暫的低電平復(fù)位信號(hào),確保單片機(jī)從已知狀態(tài)開始運(yùn)行。
功能: 在上電瞬間或按下復(fù)位按鈕時(shí),強(qiáng)制單片機(jī)回到初始狀態(tài),重新開始執(zhí)行程序,防止因上電不穩(wěn)定等因素導(dǎo)致程序運(yùn)行異常。
濾波電容: 0.1μF陶瓷電容(并聯(lián)在電源引腳附近)和10μF/100μF電解電容(并聯(lián)在穩(wěn)壓輸出端)。
選擇理由: 電源濾波是確保系統(tǒng)穩(wěn)定運(yùn)行的關(guān)鍵。陶瓷電容用于濾除高頻噪聲,電解電容用于濾除低頻噪聲,提供穩(wěn)定的直流電源。
功能: 降低電源紋波和噪聲,保證各芯片工作電壓的穩(wěn)定性,防止干擾信號(hào)通過電源線進(jìn)入芯片,提高系統(tǒng)抗干擾能力和工作穩(wěn)定性。
五、 硬件電路設(shè)計(jì)
硬件電路設(shè)計(jì)是實(shí)現(xiàn)測(cè)距儀功能的物理基礎(chǔ),需要將上述選定的元器件按照正確的連接方式組合起來。
5.1 主控芯片最小系統(tǒng)
STC89C52RC/AT89C52單片機(jī)需要構(gòu)建一個(gè)最小系統(tǒng)才能正常工作。這包括:
電源連接: VCC接5V,GND接地。
晶振電路: 將11.0592MHz或12MHz的晶振連接到單片機(jī)的XTAL1和XTAL2引腳,并分別并聯(lián)兩個(gè)22pF或33pF的瓷片電容到地。這兩個(gè)電容是晶振的負(fù)載電容,用于提供穩(wěn)定的諧振頻率。
復(fù)位電路: 將單片機(jī)的RST引腳通過一個(gè)10kΩ電阻連接到VCC,同時(shí)并聯(lián)一個(gè)10μF電解電容到GND。此外,可以并聯(lián)一個(gè)按鍵開關(guān),一端接RST,另一端接地,用于手動(dòng)復(fù)位。
5.2 超聲波模塊連接
HC-SR04模塊與51單片機(jī)的連接非常簡(jiǎn)單:
VCC: 連接到51單片機(jī)的5V電源。
GND: 連接到51單片機(jī)的GND。
Trig(觸發(fā)): 連接到51單片機(jī)的一個(gè)普通I/O口,例如P1.0。用于單片機(jī)向HC-SR04發(fā)送觸發(fā)脈沖。
Echo(回響): 連接到51單片機(jī)的另一個(gè)普通I/O口,例如P1.1。最好選擇可以作為外部中斷或定時(shí)器輸入捕捉的引腳,但對(duì)于測(cè)量高電平持續(xù)時(shí)間,普通I/O口結(jié)合定時(shí)器查詢也可行。
5.3 LCD1602顯示模塊連接
LCD1602通常采用4位或8位并行模式與單片機(jī)連接。為了節(jié)省I/O口資源,通常選擇4位模式。
VCC和GND: 連接到51單片機(jī)的5V電源和GND。
VDD和VSS: VDD接5V,VSS接地。
VO: 對(duì)比度調(diào)節(jié)引腳,通常連接一個(gè)10kΩ的滑動(dòng)變阻器,一端接VCC,另一端接地,中間滑動(dòng)端接VO,用于調(diào)節(jié)顯示對(duì)比度。
RS、RW、EN: 控制線,分別連接到51單片機(jī)的三個(gè)I/O口,例如P0.0、P0.1、P0.2。
RS (Register Select):P0.0
RW (Read/Write):P0.1 (通常接地,只進(jìn)行寫操作)
EN (Enable):P0.2
DB4-DB7: 數(shù)據(jù)線(高4位),連接到51單片機(jī)的另外四個(gè)I/O口,例如P0.4-P0.7。
A和K: 背光引腳,A(Anode)接VCC(通常串聯(lián)一個(gè)限流電阻),K(Cathode)接地。
如果使用帶I2C接口的LCD1602模塊,連接會(huì)更簡(jiǎn)單,只需要SCL和SDA兩根線連接到單片機(jī)的I2C接口引腳即可。
六、 軟件程序設(shè)計(jì)
軟件程序設(shè)計(jì)是實(shí)現(xiàn)超聲波測(cè)距儀功能的靈魂,它負(fù)責(zé)控制硬件、處理數(shù)據(jù)并實(shí)現(xiàn)邏輯功能。程序主要包括初始化、超聲波發(fā)射、時(shí)間測(cè)量、距離計(jì)算和顯示等模塊。
6.1 主程序結(jié)構(gòu)
主程序通常包含初始化函數(shù)、無限循環(huán)以及必要的延時(shí)或任務(wù)調(diào)度。
#include <reg52.h> // 引入51單片機(jī)頭文件
#include <intrins.h> // 包含_nop_()函數(shù)用于微秒級(jí)延時(shí)
sbit Trig = P1^0; // 定義Trig引腳
sbit Echo = P1^1; // 定義Echo引腳
// LCD1602接口定義
sbit LCD_RS = P0^0;
sbit LCD_RW = P0^1; // 實(shí)際應(yīng)用中常直接接地,只進(jìn)行寫操作
sbit LCD_EN = P0^2;
#define LCD_DATA P0 // 將P0口定義為數(shù)據(jù)端口
unsigned int time_count; // 存儲(chǔ)定時(shí)器計(jì)數(shù)值
float distance; // 存儲(chǔ)計(jì)算出的距離
// 函數(shù)聲明
void delay_us(unsigned int us);
void delay_ms(unsigned int ms);
void HCSR04_Init();
void HCSR04_Start();
unsigned int HCSR04_GetDistance();
void LCD_WriteCommand(unsigned char cmd);
void LCD_WriteData(unsigned char dat);
void LCD_Init();
void LCD_ShowChar(unsigned char row, unsigned char col, unsigned char dat);
void LCD_ShowString(unsigned char row, unsigned char col, unsigned char *str);
void LCD_ShowNum(unsigned char row, unsigned char col, float num, unsigned char len);
void main()
{
HCSR04_Init(); // 初始化超聲波模塊
LCD_Init(); // 初始化LCD1602
LCD_ShowString(0, 0, "Distance:"); // 第一行顯示固定文本
while(1)
{
time_count = HCSR04_GetDistance(); // 獲取超聲波往返時(shí)間
// 根據(jù)時(shí)間計(jì)算距離
// 聲速v = 343 m/s = 0.0343 cm/us
// 距離D = (v * t) / 2
// 如果定時(shí)器是1us計(jì)數(shù)一次,那么time_count就是us數(shù)
// 實(shí)際計(jì)算時(shí),需要考慮單片機(jī)晶振和定時(shí)器分頻。
// 例如:12MHz晶振,定時(shí)器工作在模式1,1us計(jì)數(shù)一次
(12/12 = 1個(gè)機(jī)器周期,1個(gè)機(jī)器周期1us)
// D = time_count * 0.0343 / 2;
// D = time_count * 0.01715; // 簡(jiǎn)化計(jì)算
// 考慮更精確的聲速計(jì)算:在20℃空氣中聲速約為343.2m/s,即34320cm/s = 0.03432 cm/us
// distance = (float)time_count * 0.03432 / 2.0; // 往返時(shí)間除以2得到單程時(shí)間
// 更準(zhǔn)確的計(jì)算方法是:12MHz晶振,一個(gè)機(jī)器周期為1us,如果定時(shí)器是1us加1,
那么time_count的單位就是us
// 距離 = (時(shí)間(us) * 0.034cm/us) / 2
distance = (float)time_count / 58.0; // 經(jīng)驗(yàn)公式,將us轉(zhuǎn)換為cm的便捷方法
(1/0.03432)*2 ≈ 58
// 或者 distance = (float)time_count * 0.01716;
if(distance > 400 || distance < 2) // 超出測(cè)量范圍或無效值
{
LCD_ShowString(1, 0, "Out of Range "); // 清除舊顯示,顯示超范圍
}
else
{
LCD_ShowNum(1, 0, distance, 4); // 在LCD第二行顯示距離,保留2位小數(shù)
LCD_ShowString(1, 6, " cm "); // 顯示單位
}
delay_ms(100); // 延時(shí)100ms,等待下一次測(cè)量,避免測(cè)量過于頻繁
}
}
6.2 延時(shí)函數(shù)
延時(shí)函數(shù)是嵌入式編程中常用的基本功能,用于產(chǎn)生精確的時(shí)間延遲。
// 微秒級(jí)延時(shí)函數(shù)
void delay_us(unsigned int us)
{
while(us--)
{
_nop_(); // 執(zhí)行一個(gè)空指令,一個(gè)機(jī)器周期,通常為1us(12MHz晶振)
}
}
// 毫秒級(jí)延時(shí)函數(shù)
void delay_ms(unsigned int ms)
{
unsigned int i, j;
for(i=ms; i>0; i--)
{
for(j=110; j>0; j--); // 經(jīng)過校準(zhǔn)的循環(huán),使延時(shí)接近1ms (對(duì)于12MHz晶振)
}
}
6.3 HC-SR04模塊操作函數(shù)
這是超聲波測(cè)距的核心部分,負(fù)責(zé)觸發(fā)超聲波并測(cè)量回波時(shí)間。
// HC-SR04初始化 (在此示例中無需特殊初始化,主要是引腳配置)
void HCSR04_Init()
{
// 配置Trig和Echo引腳為輸出/輸入,對(duì)于51單片機(jī),默認(rèn)是準(zhǔn)雙向口,直接操作即可
// P1M0 = 0x00; P1M1 = 0x00; // 配置P1口為準(zhǔn)雙向口(默認(rèn))
}
// 啟動(dòng)超聲波測(cè)距并獲取時(shí)間
unsigned int HCSR04_GetDistance()
{
unsigned int timer_value = 0;
Trig = 0; // 清除Trig
Trig = 1; // 產(chǎn)生一個(gè)10us以上的高電平脈沖
delay_us(12); // 延時(shí)12us,確保脈沖寬度
Trig = 0; // 脈沖結(jié)束
// 等待Echo引腳變?yōu)楦唠娖剑ń邮盏匠暡òl(fā)射)
while(!Echo);
// 啟動(dòng)定時(shí)器開始計(jì)時(shí)
// 這里使用定時(shí)器0,設(shè)置為模式1(16位定時(shí)器)
TMOD &= 0xF0; // 清除TMOD的低四位,不影響T1
TMOD |= 0x01; // 設(shè)置T0為模式1 (16位定時(shí)器/計(jì)數(shù)器)
TH0 = 0x00; // 定時(shí)器高8位清零
TL0 = 0x00; // 定時(shí)器低8位清零
TR0 = 1; // 啟動(dòng)定時(shí)器0
// 等待Echo引腳變?yōu)榈碗娖剑ń邮盏交夭ǎ?br/> while(Echo && !TF0); // Echo為高電平且定時(shí)器未溢出
TR0 = 0; // 停止定時(shí)器0
if(TF0) // 如果定時(shí)器溢出,說明超出了測(cè)量范圍或沒有收到回波
{
TF0 = 0; // 清除溢出標(biāo)志
return 0xFFFF; // 返回一個(gè)無效值
}
else
{
timer_value = TH0 * 256 + TL0; // 讀取定時(shí)器計(jì)數(shù)值
return timer_value;
}
}
關(guān)于定時(shí)器的說明:上述代碼中,定時(shí)器T0被設(shè)置為模式1(16位定時(shí)器),最大計(jì)數(shù)值為65535。如果使用12MHz晶振,一個(gè)機(jī)器周期是1μs。那么定時(shí)器每計(jì)數(shù)1次就是1μs。
因此,timer_value
的單位就是μs。HC-SR04的有效測(cè)量范圍是2cm-400cm,對(duì)應(yīng)的往返時(shí)間大約是116μs到23200μs。65535μs對(duì)應(yīng)的距離約為11.2米,遠(yuǎn)超HC-SR04的測(cè)量上限,所以定時(shí)器溢出的情況很少發(fā)生,除非長(zhǎng)時(shí)間沒有回波。TF0
是定時(shí)器溢出標(biāo)志位,用于判斷是否溢出。
6.4 LCD1602顯示函數(shù)
這部分代碼用于控制LCD1602顯示測(cè)量結(jié)果。
// LCD1602發(fā)送命令
void LCD_WriteCommand(unsigned char cmd)
{
LCD_RS = 0; // RS=0,表示寫命令
LCD_RW = 0; // RW=0,表示寫操作
// 發(fā)送高4位
LCD_DATA = (cmd & 0xF0);
LCD_EN = 1; // EN高電平
delay_us(5); // 延時(shí)片刻
LCD_EN = 0; // EN低電平
delay_us(5); // 延時(shí)片刻
// 發(fā)送低4位
LCD_DATA = ((cmd << 4) & 0xF0); // 將低四位左移到高四位
LCD_EN = 1;
delay_us(5);
LCD_EN = 0;
delay_us(5);
delay_ms(2); // 命令執(zhí)行延時(shí)
}
// LCD1602發(fā)送數(shù)據(jù)
void LCD_WriteData(unsigned char dat)
{
LCD_RS = 1; // RS=1,表示寫數(shù)據(jù)
LCD_RW = 0; // RW=0,表示寫操作
// 發(fā)送高4位
LCD_DATA = (dat & 0xF0);
LCD_EN = 1;
delay_us(5);
LCD_EN = 0;
delay_us(5);
// 發(fā)送低4位
LCD_DATA = ((dat << 4) & 0xF0);
LCD_EN = 1;
delay_us(5);
LCD_EN = 0;
delay_us(5);
delay_ms(1); // 數(shù)據(jù)寫入延時(shí)
}
// LCD1602初始化
void LCD_Init()
{
delay_ms(15); // 上電延時(shí)
LCD_WriteCommand(0x30); // 功能設(shè)置:8位數(shù)據(jù)接口
delay_ms(5);
LCD_WriteCommand(0x30);
delay_us(100);
LCD_WriteCommand(0x30);
LCD_WriteCommand(0x20); // 功能設(shè)置:4位數(shù)據(jù)接口
LCD_WriteCommand(0x28); // 功能設(shè)置:4位數(shù)據(jù),2行顯示,5x7點(diǎn)陣
LCD_WriteCommand(0x0C); // 顯示開,光標(biāo)關(guān),不閃爍
LCD_WriteCommand(0x06); // 地址自動(dòng)加1,顯示不移動(dòng)
LCD_WriteCommand(0x01); // 清屏
delay_ms(2);
}
// 在指定位置顯示字符
void LCD_ShowChar(unsigned char row, unsigned char col, unsigned char dat)
{
unsigned char address;
if(row == 0) // 第一行
{
address = 0x80 + col;
}
else // 第二行
{
address = 0xC0 + col;
}
LCD_WriteCommand(address); // 設(shè)置DDRAM地址
LCD_WriteData(dat); // 寫入數(shù)據(jù)
}
// 在指定位置顯示字符串
void LCD_ShowString(unsigned char row, unsigned char col, unsigned char *str)
{
unsigned char address;
if(row == 0) // 第一行
{
address = 0x80 + col;
}
else // 第二行
{
address = 0xC0 + col;
}
LCD_WriteCommand(address); // 設(shè)置DDRAM地址
while(*str != '