1.超聲波模塊型號(hào)
超聲波模塊是一種常用的測(cè)距工具,一般用在避障小車,水位監(jiān)控系統(tǒng)中,本教程使用的模塊型號(hào)為HC-SR04,外觀形狀大體如下
模塊除了兩個(gè)電源引腳外,還有TRIG,ECHO引腳,這兩個(gè)引腳分別接我們開發(fā)板的P2.0和P2.1。
工作原理就是起初先給這兩個(gè)引腳都拉低,然后讓TRIG引腳拉高10微秒以上再拉低產(chǎn)生一個(gè)脈沖起始信號(hào)(程序中我們是拉高20微秒)。起始信號(hào)一開啟,ECHO引腳就會(huì)被拉高的同時(shí),超聲波開始發(fā)射,ECHO引腳檢測(cè)到反射回來(lái)的信號(hào)時(shí)就會(huì)被拉低,因?yàn)槁曀贋?40m/s。那么測(cè)出的距離就是
(ECHO引腳高電平持續(xù)的時(shí)間*340m/s)/2。
中學(xué)學(xué)過(guò)用聲波測(cè)海底深度,時(shí)間*聲速=來(lái)回的距離,所以需要除以2才是真正的深度,超聲波模塊也一樣。
2.軟件分析
計(jì)算ECHO引腳高電平的持續(xù)時(shí)間就用定時(shí)器的計(jì)數(shù)功能完成,如果定時(shí)器計(jì)數(shù)溢出,證明測(cè)的距離太遠(yuǎn),超出模塊的測(cè)距范圍(最多4米),我們就在數(shù)碼管上顯示999表示距離太遠(yuǎn)。在測(cè)量范圍內(nèi)我們的數(shù)碼管就顯示測(cè)出的厘米數(shù)。
比如說(shuō)定時(shí)器的計(jì)數(shù)為9216,那么高電平的持續(xù)時(shí)間就是9216*(12/11059200)=0.01s
測(cè)出的距離就是0.01*340/2=1.7m
數(shù)碼管就顯示170。
不過(guò)為了簡(jiǎn)化單片機(jī)的計(jì)算過(guò)程,我們可以這樣算
“( (X*12)/11059200 )*340*100/2”就是厘米數(shù),化簡(jiǎn)約為“X/54”,X就是定時(shí)器的計(jì)數(shù)值。
本講代碼需要用到“#include<intrins.h >”的“_nop_();”,這個(gè)表示延時(shí)1微秒左右,請(qǐng)參考《手把手教你學(xué)51單片機(jī)》文檔14.2節(jié)后半段文字。
3.代碼
#include <reg52.h> #include <function.h> //詳見第六章第8講 #include <timer.h> //詳見第八章第11講 #include <intrins.h> sbit TRIG = P2^0; sbit ECHO = P2^1; u8 FLAG = 0; void delay_20us() { _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); } void main() { u16 time_data,CM_data; TRIG = 0; ECHO = 0; LED_Init(); //初始化LED硬件模塊 EA = 1; //閉合總中斷開關(guān) TIM1_Init(1000,0); //定時(shí)1ms,用來(lái)刷新數(shù)碼管顯示,定時(shí)精度要求不高可不微調(diào) TMOD &= 0xF0; TMOD |= 0x01; ET0 = 1; while(1) { TH0 = 0; TL0 = 0; FLAG = 0; //上次如果是超出測(cè)量范圍,F(xiàn)LAG被置1,這次再測(cè)就要清0 //啟動(dòng)發(fā)射聲波 TRIG = 1; delay_20us(); TRIG = 0; while(!ECHO); //聲波開始發(fā)射,等待ECHO引腳拉高退出這個(gè)循環(huán) TR0 = 1; //ECHO引腳一拉高,就打開定時(shí)器進(jìn)行計(jì)數(shù) while(ECHO==1 && FLAG==0); //收到聲波返回來(lái)的信號(hào)ECHO引腳就拉低,退出這個(gè)循環(huán);如果定時(shí)器溢出,就會(huì)進(jìn)入中斷函數(shù)執(zhí)行“FLAG=1;” //也就是測(cè)量的距離太遠(yuǎn),一直沒(méi)有收到反射回來(lái)的信號(hào),不滿足“FLAG==0”的條件只能結(jié)束這個(gè)循環(huán)語(yǔ)句 TR0 = 0; //關(guān)閉定時(shí)器結(jié)束計(jì)數(shù) time_data =TH0; time_data=(time_data<<8)|TL0; //把兩個(gè)八位的寄存器里的值組成一個(gè)16位變量的值,也就是定時(shí)器計(jì)數(shù)值 CM_data = time_data/54; //得到厘米的表達(dá)式 if(FLAG==1){ShowNumber(999); delay_ms(100);} //超出測(cè)量范圍顯示999,延時(shí)的目的:比如測(cè)得5cm到6cm之間,數(shù)碼管會(huì)頻繁在5跟6之間顯示,加入延時(shí)就會(huì)讓它們顯示的沒(méi)有那么頻繁 else {ShowNumber(CM_data); delay_ms(100);} } } void TIM0_IRQHandler() interrupt 1 { FLAG=1; } void TIM1_IRQHandler() interrupt 3 { TH1 = T1RH; //重新加載重載值 TL1 = T1RL; SEG_Scan(); }
C語(yǔ)言網(wǎng)提供由在職研發(fā)工程師或ACM藍(lán)橋杯競(jìng)賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點(diǎn)擊了解:
一點(diǎn)編程也不會(huì)寫的:零基礎(chǔ)C語(yǔ)言學(xué)練課程
解決困擾你多年的C語(yǔ)言疑難雜癥特性的C語(yǔ)言進(jìn)階課程
從零到寫出一個(gè)爬蟲的Python編程課程
只會(huì)語(yǔ)法寫不出代碼?手把手帶你寫100個(gè)編程真題的編程百練課程
信息學(xué)奧賽或C++選手的 必學(xué)C++課程
藍(lán)橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競(jìng)賽課入門課程
手把手講解近五年真題的藍(lán)橋杯輔導(dǎo)課程