找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8098|回復(fù): 10
打印 上一主題 下一主題
收起左側(cè)

[討論]超聲波測距

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:15556 發(fā)表于 2009-12-9 21:54 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
請教有關(guān)超聲波測距的問題,有經(jīng)驗(yàn)的可以交流下
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:21971 發(fā)表于 2010-3-6 15:30 | 只看該作者

目前,現(xiàn)有的超聲波發(fā)生器有40KHz,48KHz,58KHz等頻率。根據(jù)聲波在空氣中(25攝氏度時(shí))的速度340米每秒,來計(jì)算距離。其中一關(guān)鍵數(shù)據(jù)是超聲波從發(fā)射到返回之間的時(shí)間(除以2),以此來計(jì)算時(shí)間;從而得到距離,之后再進(jìn)行距離方面的提示工作,現(xiàn)有的倒車?yán)走_(dá)便是如此。以上請知悉......

回復(fù)

使用道具 舉報(bào)

板凳
ID:22031 發(fā)表于 2010-3-20 19:53 | 只看該作者
正在等程序,新手,誰搞過的共享一下程序啊- -
回復(fù)

使用道具 舉報(bào)

地板
ID:26649 發(fā)表于 2010-11-2 20:32 | 只看該作者
我也等。。。
回復(fù)

使用道具 舉報(bào)

5#
ID:60076 發(fā)表于 2014-4-5 04:10 | 只看該作者
這個(gè)程序在分的很細(xì),可以看超聲部分或溫濕檢測部分程序。
程序如下:
#include <reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define Data  P1   //LCD1602的數(shù)據(jù)口
#define NOP() {_nop_();_nop_();_nop_();_nop_();} //用于延時(shí)

//LCD1602控制引腳定義
//sbit RS = P2^6;
//sbit RW = P2^5;
//sbit E = P2^7;
sbit RS = P2^0; //復(fù)位端
sbit RW = P2^1; //寫數(shù)據(jù)端
sbit E = P2^2; //使能端
//溫濕DHT11的數(shù)據(jù)引腳定義
sbit DHT=P2^3;
//這些數(shù)組用于數(shù)據(jù)的緩存
uchar wendu_char[]=" temperature";//12  用于提示的字符
uchar shidu_char[]="  humidity";//10   用于提示的字符
uchar  wendu[] ="wen:00.00 d";//11  數(shù)據(jù)格式,當(dāng)讀取的數(shù)據(jù)會(huì)保存到數(shù)組的相應(yīng)的位上
uchar  shidu[]="shi:00.00 RH";//12  //同上一句
uchar table[]={" make ^!^ in  "};//14   //用于提示
uchar table1[]={" 2013-12-20 "};//12   //用于提示
//uchar qingxu1[]={"   ^!^    "};//11
//uchar qingxu2[]={"good weather"};//12
//uchar qingxu3[]={"   -_-!    "};//12
//uchar qingxu4[]={"bad weather!"};//12
unsigned char shiZ,shiX,wenZ,wenX,check;  //用于存讀出傳感器的數(shù)據(jù),因?yàn)樽x出的是整型數(shù)據(jù),之后用于轉(zhuǎn)換成字符存于上面的數(shù)組中
unsigned char shiH,shiL,wenH,wenL;  //
unsigned char flag;  //定義一個(gè)標(biāo)志位
unsigned int n=20,m;   //定義一些會(huì)在下面用到的全局變量
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void delay(uint a); //超聲波模塊和溫濕模塊的公用延時(shí)函數(shù)
void delay_10us() ;
void delay_1ms(unsigned int i) ;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//超聲波部分的函數(shù)
/////////////////////////////////////////////////////
sbit Tx=P3^3;    //超聲波模塊發(fā)射脈沖的引腳定義
sbit Rx=P3^2;    //超聲波模塊接收回波的引腳定義
uchar code table2[]={"Distance Test:"}; //14   //用于提示
uchar temp_dis[]= {"000.0 cm"};// 8       //用于顯示數(shù)據(jù)的緩沖數(shù)組
long int t;//讀出的數(shù)據(jù)現(xiàn)存于這些變量,再轉(zhuǎn)換成字符賦給上面的數(shù)組
double distance;
uchar cache[4]={0,0,0,0};  //用于裝入分離的數(shù)據(jù)的各個(gè)位
//外部中斷0用于計(jì)算超聲波模塊接收到回波的時(shí)間,用于計(jì)算距離
void init0() //外部中斷0在接收到Rx腳的高電平觸發(fā)定時(shí)器計(jì)時(shí),當(dāng)高電平回波結(jié)束時(shí)是下降沿
{//定時(shí)器0的初始化
TMOD=0x01;  
TH0=0;
TL0=0;

//外部中0的初始化
EX0=1; //外部中斷的
IT0=1;      //設(shè)置為低電平觸發(fā),下降沿有效

//打開總中斷
//EA=1;
}

//超聲波模塊初始化
void HC05_Init()
{ //依據(jù)模塊的資料,把發(fā)射腳拉高大于10us,再把發(fā)射腳拉低,模塊就會(huì)自動(dòng)發(fā)送探測的脈沖
  EA=1;
  Tx=1;  
  NOP();NOP();NOP();NOP(); //用于延時(shí),保持大于8us的要求
  Tx=0;  //發(fā)射腳拉低
  while(!Rx);  //當(dāng)RX為零時(shí)等待
  TR0=1;       //開啟計(jì)數(shù)
  while(Rx);   //當(dāng)RX為1計(jì)數(shù)并等待
  TR0=0;    //關(guān)閉計(jì)數(shù)
  //TR0=1; //打開定時(shí)器0,以便從發(fā)送脈沖開始計(jì)時(shí),到接收到外部中斷0后關(guān)閉
  distance=0.17*t;  //計(jì)算距離的公式
// distance=(340*t)/2;
}

//數(shù)值轉(zhuǎn)換
void distance_convert(long int dat)
{  
  //把得到的數(shù)據(jù)分離出個(gè),十,百等位,裝入數(shù)組中
//0.17*t知道測量的值有兩個(gè)小數(shù)點(diǎn),且該超聲波模塊可以測量到幾百厘米,所以,得到的數(shù)據(jù)格式位000.00cm,
//我們要保留1為小數(shù),又因?yàn)閈,%的運(yùn)算為整數(shù),則先把數(shù)據(jù)乘以10,再求出各個(gè)對應(yīng)的位放到對應(yīng)的數(shù)組
  //dat=dat*10;
  cache[0]=dat/1000; //實(shí)際對應(yīng)原數(shù)據(jù)的百位,因?yàn)榘褦?shù)據(jù)*10處理了,向高位移了一位
  cache[1]=dat/100;
  cache[2]=dat/10;
  cache[3]=dat; //
  //裝入數(shù)組,加'0'是將整型的數(shù)據(jù)轉(zhuǎn)換成字符數(shù)據(jù)
  temp_dis[0]=cache[0]+'0'; //數(shù)組的格式位uchar temp_dis[]= {"000.0 cm"};
  temp_dis[1]=cache[1]+'0';
  temp_dis[2]=cache[2]+'0';
  temp_dis[4]=cache[3]+'0';
}

//溫度度部分的函數(shù)(DHT11)
////////////////////////////////////

//延時(shí)函數(shù)1ms
void delay_1ms(unsigned int i)
{
  unsigned int j=88;
  for(;i>0;i--)
  {
  while(j>0)j--;
  }
}
//延時(shí)函數(shù)10us
void delay_10us()
{
  unsigned char i;
  i--;
  i--;
  i--;
  i--;
  i--;
  i--;
}
//延時(shí)函數(shù)可調(diào)
void delay(uint a)
{
uint y;
for(;a>0;a--)
  for(y=100;y>0;y--);
}


//讀取DHT11的數(shù)據(jù),其為單總線通訊,只用一條線,已經(jīng)定義為DHT,區(qū)別于I2C通訊
char read_data()
{
  unsigned char i,num,temp;
  num=0;
  for(i=0;i<8;i++)
  {
  flag=2;
  while((!DHT)&&flag++); //判斷從機(jī)是否發(fā)出80us的低電平相應(yīng)信號是否結(jié)束
  delay_10us();
  delay_10us();
  delay_10us();
   if(DHT==1)
   {
    temp=1;
    flag=2;
    while(DHT&&flag++);   
   } //超時(shí)則跳出
  else
   temp=0;
   num<<=1; //一位一位的讀出存入變量num中
   num|=temp;
  }
  return(num); //讀8個(gè)位的數(shù)據(jù),為一個(gè)字節(jié)
}

//讀取DHT11的40位數(shù)據(jù)函數(shù)//////////////////////////////////////////////////////////////////////////////
void read_init()
{
  DHT=0;   //主機(jī)拉低21ms
  delay_1ms(21);
  DHT=1;    //總線由上拉電阻拉高40us
  delay_10us();
  delay_10us();
  delay_10us();
  delay_10us();
  DHT=1; //主機(jī)設(shè)為輸入 判斷從機(jī)相應(yīng)信號
  if(!DHT)  //判斷從機(jī)是否把總線拉低
  {
   flag=2;
   while((!DHT)&&flag++); //等待從機(jī)把總線拉低
   flag=2;
   while(DHT&&flag++); //判斷從機(jī)是否拉低總線,即響應(yīng)
    //接收數(shù)據(jù)
   shiH=read_data();//因?yàn)閞ead_data()只讀出一個(gè)字節(jié),而DHT讀出的是連續(xù)的5個(gè)字節(jié),所以不用for()
   shiL=read_data();
   wenH=read_data();
   wenL=read_data();
   check=read_data();
   DHT=1;
  }      
}

//DH11數(shù)據(jù)處理
void DHT11dada()
{
unsigned char temp;
read_init();
  temp=shiH+shiL+wenH+wenL; //檢驗(yàn)也為8位的二進(jìn)制,等于前面的數(shù)據(jù)之和
  if(check==temp)
  {  //檢驗(yàn)數(shù)據(jù)對了就賦給另外幾個(gè)變量來轉(zhuǎn)換
    shiZ=shiH;
    shiX=shiL;
    wenZ=wenH;
    wenX=wenL;
  }
  wendu[4]='0'+wenZ/10; //分離出各個(gè)位,并轉(zhuǎn)換成字符數(shù)據(jù),依據(jù)上面的數(shù)組定義wendu[] ="wen:00.00 d";的數(shù)據(jù)格式,把對應(yīng)的數(shù)據(jù)寫到對應(yīng)的位
  wendu[5]='0'+wenZ;  //分理出的是溫度的個(gè)位,在數(shù)組中的第六個(gè)位置,所以寫入該位更新,以便顯示
  wendu[8]='0'+wenX/10;  //第七位為 .
  wendu[9]='0'+wenX;
  shidu[4]='0'+shiZ/10; //同理,濕度的格式為shidu[]="shi:00.00 RH";
  shidu[5]='0'+shiZ;
  shidu[8]='0'+shiX/10;
  shidu[9]='0'+shiX;
}


//LCD1602部分函數(shù)     各個(gè)函數(shù)依據(jù)LCD1602的時(shí)序編寫
////////////////////////////////////////////////////////

//LCD1602寫指令函數(shù)
void lcd_write_com(uchar c)   
{
  delay_1ms(5);
  E=0;
  RS=0;
  RW=0;
  _nop_();
  E=1;
  Data=c;
  E=0;
}

//LCD1602寫數(shù)據(jù)函數(shù)
void lcd_write_dat(uchar c)  
{
  delay_1ms(5);
  E=0;
  RS=1;
  RW=0;
  _nop_();
  E=1;
  Data=c;
  E=0;
  RS=0;
}

//LCD1602初始化
void lcd_init()   
{
  delay_1ms(5);
  lcd_write_com(0x38);
  lcd_write_com(0x38);
  lcd_write_com(0x38);
  lcd_write_com(0x06);
  lcd_write_com(0x0c);
  lcd_write_com(0x01);
}
//LCD1602清屏函數(shù)
void qingping()
{
lcd_write_com(0x01);
delay(5);
}

//顯示開始標(biāo)題
void disp(void)    //顯示子函數(shù)
{ uchar i,j;
lcd_write_com(0x80);//往第一行寫入字符串,寫完一個(gè)字符會(huì)自動(dòng)調(diào)到第二個(gè)地址寫入數(shù)據(jù)
  for(i=0;i<13;i++)
  {
   lcd_write_dat(table[ i]);
  }
lcd_write_com(0x80+40);//往第二行寫入日期
for(j=0;j<11;j++)
  {
   lcd_write_dat( table1[j]);
  }
  delay(3000);//顯示的時(shí)間長短
  qingping();//清屏
}

//顯示溫濕函數(shù)
void display_DHT11()
{ uchar h,n,e,m;
//uchar x,y;
lcd_write_com(0x80);
  for(e=0;e<12;e++)  //寫入溫度數(shù)據(jù)
   {
    lcd_write_dat(wendu_char[e]);
   }
  lcd_write_com(0x80+40);
  for(n=0;n<11;n++)  //寫入溫度數(shù)據(jù)
   {
    lcd_write_dat(wendu[n]);
   }
  delay(3000);
  qingping();//清屏
  lcd_write_com(0x80);
  for(h=0;h<10;h++) //寫入濕度數(shù)據(jù)
   {
    lcd_write_dat(shidu_char[h]);
   }
  lcd_write_com(0x80+40);
  for(m=0;m<12;m++) //寫入濕度數(shù)據(jù)
   {
    lcd_write_dat(shidu[m]);
   }
  delay(3000);
  qingping();

//  //情緒表達(dá)部分   //因?yàn)?1內(nèi)存寫滿了,只能舍去這部分
//  if(shiZ>=16&&shiZ<=28)
//  {
//   lcd_write_com(0x80);
//   for(y=0;y<11;y++)
//   {
//    lcd_write_dat(qingxu1[y]);
//   }
//  lcd_write_com(0x80+0x40);
//  for(x=0;x<12;x++)
//   {
//    lcd_write_dat(qingxu2[x]);
//   }
//   delay(3000);
//   qingping();
//  }
//  if(shiZ<=16&&shiZ>=28)
//  {
//   lcd_write_com(0x80);
//   for(y=0;y<12;y++)
//   {
//    lcd_write_dat(qingxu3[y]);
//   }
//  lcd_write_com(0x80+0x40);
//  for(x=0;x<12;x++)
//   {
//    lcd_write_dat(qingxu4[x]);
//   }
//   delay(3000);
//   qingping();
//  }
}

//顯示超聲波數(shù)據(jù)
void display_HC05()
{  
  uchar k,w;
  lcd_write_com(0x80);//超聲波測距顯示部分:K,W
  for(k=0;k<14;k++)
   {
    lcd_write_dat(table2[k]);
   }
  lcd_write_com(0x80+0x40);
  for(w=0;w<8;w++)
   {
    lcd_write_dat(temp_dis[w]);
   }
  delay(3000);
  qingping();
}
////不寫在一起是為了及時(shí)將數(shù)據(jù)輸出,因?yàn)樽x完傳感器才輸出,有的傳感器的數(shù)據(jù)已經(jīng)變化了
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//主函數(shù)
void main()
{  uchar x,s;
  lcd_init();
  init0();
  Tx=0;//超聲波發(fā)送口初始化,
  while(1)
  {
  disp();//顯示開始的字符
  for(x=0;x<2;x++)
  {
   DHT11dada();//溫濕的數(shù)據(jù)
  }
  display_DHT11();//顯示溫濕的數(shù)據(jù)
  for(s=0;s<2;s++)
  {
   HC05_Init(); //需要放到while(1)中 因?yàn)橐粩嘤|發(fā)超聲波模塊的脈沖得出距離
   distance_convert(distance);
  }
  display_HC05();
}
}


//外部中斷0的中斷函數(shù),記回波的時(shí)間,即發(fā)送測量脈沖開始計(jì)時(shí),到接收到回波時(shí)產(chǎn)生外部中斷,把得到的時(shí)間賦給t
void int0() interrupt 0
{  EA=0;
  t=(TH0*256+TL0);  //讀取定時(shí)器的時(shí)間
  TH0=0; //清空定時(shí)器
  TL0=0;
}
回復(fù)

使用道具 舉報(bào)

6#
ID:61326 發(fā)表于 2014-5-2 19:50 | 只看該作者
謝謝分享
回復(fù)

使用道具 舉報(bào)

7#
ID:56795 發(fā)表于 2014-5-3 17:02 來自手機(jī) | 只看該作者
幾塊錢的超聲波測距模決是不是測距不穩(wěn)定,我做的測同一距離會(huì)測出不同的數(shù)據(jù)。誤差有幾個(gè)毫米
回復(fù)

使用道具 舉報(bào)

8#
ID:56795 發(fā)表于 2014-5-3 17:04 來自手機(jī) | 只看該作者
我不知道是程序有問題或是超聲波模塊有問題
回復(fù)

使用道具 舉報(bào)

9#
ID:28571 發(fā)表于 2015-4-18 14:12 | 只看該作者
好東西,學(xué)習(xí)一下,謝謝!
回復(fù)

使用道具 舉報(bào)

10#
ID:128255 發(fā)表于 2016-6-30 15:36 | 只看該作者
賣的模塊,普遍測量角度都在15度以內(nèi),分離模塊能達(dá)到多大的角度?
回復(fù)

使用道具 舉報(bào)

11#
ID:223039 發(fā)表于 2017-8-3 18:35 | 只看該作者
學(xué)習(xí)一下,樓主分享的很好!
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表