51單片機課程設計:基於51單片機的超聲波測距(測距原理介紹)
本程序利用超聲波模塊來進行距離的測量,並顯示在數碼管上,其他朋友可以在本程序的基礎上,修改部分代碼,應用到智能小車上或者其他測距設備上。
超聲波測距的原理是:首先給模塊Trig端一個高電平,然後單片機開始計時,同時模塊會發射超聲波信號,當單片機檢測到Echo端爲高電平時(也就是說模塊收到反射的信號),計時停止。通過以上操作,我們就可以得到一個時間變量,然後調用對應的公式就可以將時間變量轉換爲距離。
相關工程文件以及資料在文章下方,感興趣的朋友可以下載。
關於粘貼複製亂碼的問題:如果程序複製到Keil編譯器上出現註釋亂碼,可以先建一個.c文件,也就是說不在keil裏面編輯,然後用記事本打開.c文件,將源碼複製進去,再在keil中添加文件即可。
/**************************************************************** 基於51單片機的超聲波測距例程 如果需要在其他開發板上運行並顯示,只需要修改數碼管顯示模塊即可 DisplayData[8]用於存放轉換後的距離數據,也就是說你只需要將其中 的數據在其他顯示模塊顯示出來。 引腳3.1 接模塊Trig 引腳3.2 接模塊Echo 晶振頻率一般都是12MHZ 2016-12-30---------------------SWorld ****************************************************************/ #include<reg52.h> #define uchar unsigned char //宏定義無符號字符型 #define uint unsigned int //宏定義無符號整型 #define GPIO_DIG P0//位選以及段選數據輸出端口定義 unsigned char code DIG_CODE[10]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //顯示段碼 數碼管字跟 unsigned char DisplayData[8];//用來存放要顯示的8位數的值 sbit DUC=P2^2;// DUC段選信號 sbit WEC=P2^3;//WEC 位選信號 sbit Trig=P3^1; sbit Echo=P3^2; uchar succeed_flag=0; uint timeH,timeL,distance=0,time=0,ss; //float ; //延時子程序 延時1ms void delay_ms(uint c) { uchar a, b; for(;c>0;c--) { for (b=38;b>0;b--) { for (a=13;a>0;a--); } } } //延時子程序 延時1us void delay_us(uint c) { uchar a ; for(;c>0;c--) for(a=0;a<5;a++); } //數碼管顯示 void DigDisplay() { unsigned char i; unsigned int j; for(i=0;i<8;i++) { WEC=1;DUC=0; switch(i) //位選,選擇點亮的數碼管, { case(0): GPIO_DIG=0x7F; break;//顯示第0位 case(1): GPIO_DIG=0xBF; break;//顯示第1位 case(2): GPIO_DIG=0xDF; break;//顯示第2位 case(3): GPIO_DIG=0xEF; break;//顯示第3位 case(4): GPIO_DIG=0xF7; break;//顯示第4位 case(5): GPIO_DIG=0xFB; break;//顯示第5位 case(6): GPIO_DIG=0xFD; break;//顯示第6位 case(7): GPIO_DIG=0xFE; break;//顯示第7位 } WEC=0;DUC=1; GPIO_DIG=DisplayData[i];//發送段碼 j=15; //掃描間隔時間設定 while(j--); GPIO_DIG=0x00;//消隱 } } //主函數模塊 void main(void) { Trig=0; EA=1; TMOD=0x11;//定時器1,16位工作方式 定時器0 16位工作方式 while(1) { EA=0; //關總中斷 Trig=1; delay_us(20); //延時20us Trig=0; //20us脈衝 while(Echo==0); //等待Echo回波引腳變高電平 succeed_flag=0; EA=1; //開外部中斷 EX0=1; //打開外部中斷0 TH1=0; //定時器1缺清零 TL1=0; //計數溢出標誌 TF1=0; TR1=1; //啓動定時器1 delay_ms(20); TR1=0; //關閉定時器1 EX0=0; //關外部中斷 if(succeed_flag==1) { time=timeH*256+timeL; distance=time*0.172; } if(succeed_flag==0) { distance=0; } DisplayData[5]=DIG_CODE[distance/100]; DisplayData[4]=DIG_CODE[(distance%100)/10]; DisplayData[3]=DIG_CODE[distance%10]; for(ss=0;ss<200;ss++) DigDisplay(); } } //外部中斷0 用於判斷回波電路 void exter() interrupt 0 { timeH =TH1; //取出定時器值H timeL =TL1; //取出定時器值L succeed_flag=1;//成功測量標誌 EX0=0; //關外部中斷 } //定時器1中斷 用作超聲波測距計時 void timer1() interrupt 3 { TH1=0; TL1=0; }