超聲波模塊工作原理:
(1)采用IO觸發測距,給至少10us的高電平信號;
(2)模塊自動發送8個40khz的方波,自動檢測是否有信號返回;
(3)有信號返回,通過IO輸出一高電平,高電平持續的時間就是
超聲波從發射到返回的時間.測試距離=(高電平時間*聲速(340M/S))/2;
定時器初始化:
考慮到原理(3)有信號返回時輸出一個高電平,所以TMOD設置為0x09,GATE=1(需要TR0和中斷0(INT0)口都=0,中斷才會啟動),然后用杜邦線將中斷0的引腳和超聲波模塊的I0口(echo口)連接,這樣當超神波返回時,echo=1,INT0=1,中斷啟動。
我試過將初始設置為10us和100us兩種,10us時,s=vt,100us時,s=vt/2,按照公式s=vt/2才是正確的,但是我10us時,值相差也不大,不知道什么原因,但是這個不對,所以下面代碼中,用的是100us這個。
------------------------------------------------分割線----------------------------------------------------------------
#include "reg52.h" typedef unsigned char uchar; typedef unsigned int uint; sbit trig=P2^0; sbit echo=P2^1; sbit beep=P1^5; sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; uint num=0; //計時 float distance; //距離 float cm_per_num=3.40; //按照我的定時器初始化設定,1個num是100us uchar DisplayData[6]; uchar code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f};//顯示0~9的值 void delay1ms(uchar xms) { uchar a,b,c; for(c=xms;c>0;c--) for(b=142;b>0;b--) for(a=2;a>0;a--); } /* 設置工作方式為方式1,GATE=1,當中斷0口輸入1且TR0=1 時定時器工作 因為超聲波模塊的工作原理就是在接收回波時,從開始到結束,ech0=1 所以在單片機上用杜邦線將ech0的P21口和 中斷0口 P32口鏈接 使得在回波期間,定時器工作,計算回波的時間,進而s=vt算出距離 */ void TimerInit() //初始化,定時10us { TMOD = 0x09; TH0 = 0xFF; TL0 = 0x9C; EA = 1; ET0 = 1; TR0 = 1; } void Timer0() interrupt 1 //中斷 每過100us,num+1 { TH0 = 0xFF; TL0 = 0x9C; num++; } void value_distance() { trig=0; echo=0; delay1ms(1); trig=1; delay1ms(11); //給trig一個10us以上的高電平信號 trig=0; if(echo==1) //如果有反射回的超聲波,echo腳會在這期間持續輸入高電平 { delay1ms(300); //接收超聲波期間不做任何動作。 } distance=num*cm_per_num/2; //計算距離,單位CM num=0; } void datapros() //對取得的距離進行處理 { float a= distance*100; DisplayData[0]=smgduan[(int)a%10]; DisplayData[1]=smgduan[(int)a%100/10]; DisplayData[2]=smgduan[(int)a%1000/100]+0x80; //數字+小數點 DisplayData[3]=smgduan[(int)a%10000/1000]; DisplayData[4]=smgduan[(int)a/10000]; } void DigDisplay() //數碼管顯示 { uchar i; for(i=0;i<6;i++) { switch(i) //位選,選擇點亮的數碼管, { case(0): LSA=0;LSB=0;LSC=0; break;//顯示第0位 case(1): LSA=1;LSB=0;LSC=0; break;//顯示第1位 case(2): LSA=0;LSB=1;LSC=0; break;//顯示第2位 case(3): LSA=1;LSB=1;LSC=0; break;//顯示第3位 case(4): LSA=0;LSB=0;LSC=1; break;//顯示第4位 case(5): LSA=1;LSB=0;LSC=1; break;//顯示第5位 } P0=DisplayData[i];//發送段碼 delay1ms(1); //間隔一段時間掃描 P0=0x00;//消隱 } } void main() { while(1) { TimerInit(); value_distance(); datapros(); DigDisplay(); } }