久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 9705|回復(fù): 5
收起左側(cè)

語音播報超聲波測距程序

[復(fù)制鏈接]
ID:75263 發(fā)表于 2015-4-19 23:04 | 顯示全部樓層 |閱讀模式
        本程序來源于網(wǎng)絡(luò),由51hei收集整理,測距原理:單片機IO口接超聲波模塊TX引腳,由IO口產(chǎn)生40KHz頻率方波發(fā)送給TX用以超聲波模塊發(fā)送超聲波,同時打開單片機計時器,超聲波遇到障礙后返回,模塊接收頭接收到超聲波后產(chǎn)生信號由電路濾波整形放大后在RX引腳輸出高電平,RX接單片機的P3^2(51內(nèi)核單片機的外部中斷),在中斷服務(wù)程序中停止計數(shù)器,對所計數(shù)值進行處理得到超聲波往返所用時間再乘以風速即得測量距離。由于超聲波屬于聲波范圍,其速度與溫度有關(guān),不同溫度下超聲波在空氣中傳播速度隨溫度變化關(guān)系:V=331.4+0.61T。所以要是測量結(jié)果更加精確需另加溫度補償模塊(本實驗中采用開發(fā)板上的DS18B20溫度傳感器完成溫度補償)。外圍可添加LCD顯示(本實驗采用開發(fā)板1602LCD)和語音播報模塊(本實驗采用ISD4004語音模塊)。



AT89S52單片機引腳圖



1602lcd引腳圖

源程序
// *********************單片機實驗室******************************/
// *文件名稱 :csbspk.c
// *功能     : 實現(xiàn)超聲波測距并語音播報 (測量范圍:4~80cm)
// *引腳連接 : ISD4004 SS接P1.2  MOSI接P1.0  MISO接P1.1  SCLK接P1.3
// *           超聲波模塊 TX接P3.1  RX接P3.2   J7接上插冒
// *當前版本 :1.0
// *作者     : 劉松
// *完成日期 :2010.11.11
// ****************************************************************/
#include<reg52.h>
#include <intrins.h>
#include"lcd.h"   // 液晶顯示
#include"ds18b20.h"  //溫度傳感器

sbit P3_1=P3^1;
sbit key1=P2^1;   //定義按鍵
sbit SS=P1^2;     //以下四行定義ISD4004引腳      
sbit MOSI=P1^0;
sbit MISO=P1^1;
sbit SCLK=P1^3;

uchar addr; //語音地址全局變量
uchar s;    //語音所對應(yīng)數(shù)字
int VD;     //擴大十倍的聲速
int D;      //測量的距離
int temp;   //超聲波反射時間

void timer() //初始化計數(shù)器
{
  TMOD=0x10;
  TH1=0;
  TL1=0;
  EA=1;
  EX0=1;
}


void delay25us_40KHz(unsigned char us) //產(chǎn)生方波用于超聲波發(fā)射
{
   
TR1=1;
    while(us--)
{
   P3_1= 0;
   _nop_();_nop_();
   _nop_();_nop_();
   _nop_();_nop_();
   _nop_();_nop_();
   _nop_();_nop_();
   _nop_();
   P3_1= 1;
   _nop_();_nop_();
   _nop_();_nop_();
}
P3_1= 1;
}


rec() interrupt 0 //計算超聲波反射時間
{
  TR1=0;
  EA=0;
  temp=TH1*256+TL1;
}


void delayms(uchar ms)  // 延時子程序用于語音播放上電等待
{      
uchar j;
while(ms--)
{
  for(j = 0; j < 120; j++);
}
}


void delay2(int m) //長延時用于語音播放
{
  int l,j;
  for(l=0;l<30001;l++)
  for(j=0;j<m;j++);
}


////////////////////////////液晶顯示子函數(shù)//////////////////////////////////
void display()
{
    float V;//聲速
V=331.4+0.61*T; VD=V*10;
D=temp*V/2000-29;
displaystring(0,0,"Dis=");
displaychar(4,0,(D/100)+0x30);
displaychar(5,0,(D0/10)+0x30);
displaychar(6,0,'.');
displaychar(7,0,(D)+0x30);
displaystring(8,0,"cm");
displaystring(0,1,"T=");
displaychar(5,1,(TD)+0x30);
displaychar(4,1,'.');
displaychar(3,1,(TD0/10)+0x30);
displaychar(2,1,(TD/100)+0x30);
displaychar(6,1,0xdf);
displaychar(7,1,'C');
displaystring(9,1,"V=");
displaychar(11,1,(VD/1000)+0X30);
displaychar(12,1,(VD00/100)+0X30);
displaychar(13,1,(VD0/10)+0X30);
displaychar(14,1,'.');
displaychar(15,1,(VD)+0X30);

}
///////////////////////////////////////////////////////////////



////////////////放音部分子程序,放音地址由ADDR決定////
void play(addr)
{  
    uchar y;
SS=0;
MOSI=0;//發(fā)送開始
SCLK=0;
for(y=0;y<8;y++)
{
  SCLK=0;
  if((0x20>>y)&0x01)MOSI=1;  //上電命令
  else MOSI=0;
  _nop_();
  _nop_();
  _nop_();
  SCLK=1;
  _nop_();
  _nop_();
  _nop_();
}//發(fā)送結(jié)束
SS=1;//上電結(jié)束
delayms(50);
SS=0;
MOSI=0;//發(fā)送地址
SCLK=0;
for(y=0;y<16;y++)
{
  SCLK=0;
  if((addr>>y)&0x01)MOSI=1;
  else MOSI=0;
  _nop_();
  _nop_();
  _nop_();
  SCLK=1;
  _nop_();
  _nop_();
  _nop_();
}//發(fā)送地址結(jié)束
MOSI=0;//放音
SCLK=0;
for(y=0;y<8;y++)
{
  SCLK=0;
  if((0xe0>>y)&0x01)MOSI=1;  //指定地址放音命令
  else MOSI=0;
  _nop_();
  _nop_();
  _nop_();
  SCLK=1;
  _nop_();
  _nop_();
  _nop_();
}
SS=1;
SS=0;
MOSI=0;
SCLK=0;
for(y=0;y<8;y++)
{
  SCLK=0;
  if((0xf0>>y)&0x01)MOSI=1; //忽略地址放音命令(連貫播放后續(xù)空間)
  else MOSI=0;
  _nop_();
  _nop_();
  _nop_();
  SCLK=1;
  _nop_();
  _nop_();
  _nop_();
}
SS=1;  
}
///////////////////////////////////////////////////////////////


///////////////////讀數(shù)字子函數(shù)///////////////////////////////
void speaknum()  
{
  if(s==1) play(0x01);
  if(s==2) play(0x0a);
  if(s==3) play(0x14);
  if(s==4) play(0x1e);
  if(s==5) play(0x28);
  if(s==6) play(0x32);
  if(s==7) play(0x3c);
  if(s==8) play(0x46);
  if(s==9) play(0x50);
  if(s==0) play(0x6e);
}
////////////////////////////////////////////////////////////////



///////////////////讀出顯示結(jié)果子函數(shù)////////////////////////////
void read()
{
   play(0xdc);     //播報“測量距離”這四個字,0xdc是之前記錄下4004錄這四個字的地址
   delay2(50000);
   delay2(50000);   //延時等待播報完畢
   s=D/100;         //D是測量得到的數(shù)據(jù)值,此語句是取數(shù)據(jù)的最高位
   if(s==1)         //判斷最高位(十位)如果是“1”則不讀yi而讀shi
   {
    play(0x5a);     //shi的地址
    delay2(50000);
   }
   if(s>1)          //如果大于1則讀出相應(yīng)數(shù)字后直接在后面加讀shi
   {
    speaknum();
    delay2(50000);
    play(0x5a);
    delay2(50000);
   }
   s=D0/10;   //取次高位(個位)的值
   if(s!=0)    //次高位不為0則讀出相應(yīng)的值,為0跳過
   {
    speaknum();
    delay2(50000);
   }
   play(0x64); //讀小數(shù)點“dian”
   delay2(50000);
   s=D;     //取小數(shù)點后一位的值
   speaknum();
   delay2(50000);
   play(0xbe);  //播報“cm”limi
   delay2(50000);

    ///////////////////////////以下是播報溫度和當前計算的聲速,方法同上///////////////////
   play(0xf0);
   delay2(50000);
   delay2(50000);
   s=TD/100;
   if(s==1)
   {
    play(0x5a);
    delay2(50000);
   }
   if(s>1)
   {
    speaknum();
    delay2(50000);
    play(0x5a);
    delay2(50000);
   }
   if(s!=0)
   {
    s=TD0/10;
    speaknum();
    delay2(50000);
   }
   play(0x64);
   delay2(50000);
   s=TD;
   speaknum();
   delay2(50000);
   play(0xC8);
   delay2(50000);
   delay2(50000);
   play(0xe6);
   delay2(50000);
   delay2(50000);
   s=VD/1000;
   speaknum();
   delay2(50000);
   play(0xfa);
   delay2(50000);
   s=VD00/100;
   speaknum();
   delay2(50000);
   play(0x5a);
   delay2(50000);
   s=VD0/10;
   speaknum();
   delay2(50000);
   play(0x64);
   delay2(50000);
   s=VD;
   speaknum();
   delay2(50000);
   play(0xd2);
}
////////////////////////////////////////////////////////////



void main()
{
  initlcd() ;  //初始化LCD1602
  while(1)
{
  timer();
  readtemp();  //讀溫度
  delay25us_40KHz(15);
  display();
  if(key1==0) read();
}
}

以下是溫度傳感器頭文件ds18b20.h
sbit DQ=P2^2;
uchar tempdata[2];
uchar k=0;
int TD;
float T;
void delay1(uchar i)
{
  while(i--);
}

void initDS18B20()  //初始化DS18B20
{
DQ = 1;     //DQ復(fù)位
delay1(8);   //稍做延時
DQ = 0;     //單片機將DQ拉低
delay1(80);  //延時 大于 480us
DQ = 1;     //拉高總線
delay1(30);
}

uchar readchar()  //向DS18B20讀取一字節(jié)
{
uchar i = 0 ;
uchar dat = 0 ;
for (i = 8 ; i > 0 ; i--)
    {
      DQ = 0 ;
      dat >>= 1 ;
      DQ = 1 ;

      if(DQ)
       dat |= 0x80 ;
      delay1(4) ;
    }

      return (dat) ;
}

void writecmd(uchar cmd)  //向DS18B20寫入一字節(jié)
{
    uchar i ;
    for (i = 8 ; i > 0 ; i--)
    {
      DQ = 0 ;
      DQ = cmd&0x01 ;
      delay1(5) ;

      DQ = 1 ;
      cmd>>=1 ;
    }
}


void readtemp()
{     
initDS18B20() ;
writecmd(0xCC) ;    // 跳過讀序號列號的操作
writecmd(0x44) ;    // 啟動溫度轉(zhuǎn)換
initDS18B20() ;
writecmd(0xCC) ;    //跳過讀序號列號的操作
writecmd(0xBE) ;    //讀取溫度寄存器
tempdata[0] = readchar() ;     //溫度低8位
tempdata[1] = readchar() ;     //溫度高8位
TD=tempdata[1];
TD<<=8;
TD|=tempdata[0];
    T=TD*0.0625;         //DS18B20在出廠時以配置為12位,讀取溫度時共讀取16位,最高5位為符號位,溫度在0上,符號位為0,所以把后11位的2進制轉(zhuǎn)化為10進制后在乘以0.0625便為所測的溫度
    TD=T*10+0.5;        //將它放大10倍, 使顯示時可顯示小數(shù)點后一位, 并對小數(shù)點后第二2進行4舍5入

}

一下是液晶顯示頭文件lcd.h

sbit RS=P2^5;
sbit RW=P2^6;
sbit EN=P2^7;
#define uchar unsigned char
#define DATA P0
#define busy 0x80


void chkbusy() //檢測狀態(tài)
{
  DATA=0xff;
  RS=0;
  RW=1;
  EN=1;
  _nop_();
  _nop_();
  while(busy&DATA);
  EN=0;
}

void WIR(uchar CMD,uchar i)   //寫命令
{
   if(i) chkbusy();
   RS=0;
   RW=0;
   EN=1;
   _nop_();
   _nop_();
   DATA=CMD;
   EN=0;
}

void WDR(char c)  //寫數(shù)據(jù)
{
   chkbusy();
   RS=1;
   RW=0;
   EN=1;
   _nop_();
   _nop_();
   DATA=c;
   EN=0;
}

void displaychar(uchar x,uchar y,char c)  //指定行列顯示字符
{
     if(y==1) x|=0x40;    //當要顯示第二行時地址碼+0x40;
     x|=0x80;
     WIR(x,0);
     WDR(c);
}

void displaystring(uchar x,uchar y,char s[])   //指定行列顯示字符串
{
uchar p=0;
while(1)
{
  displaychar(x,y,s[p]);
  p++;
  if(s[p]==0)
  break;
  x++;
  if(x>=15)       //每行最多顯示16個字符
  {
    x=0;   
    y=!y;   //如果一行顯示不完,則轉(zhuǎn)到下一行或上一行顯示
  }      
}
}

void initlcd()   //初始化lcd
{
   WIR(0x38,0);
   WIR(0x38,1);  //顯示模式設(shè)置
   WIR(0x08,1);  //關(guān)閉顯示
   WIR(0x01,1);  //清屏
   WIR(0x06,1);  //光標移位設(shè)置
   WIR(0x0c,1);  //顯示開及光標設(shè)置
}








評分

參與人數(shù) 2黑幣 +7 收起 理由
暗夜之 + 3 贊一個!
1620406085 + 4 很給力!

查看全部評分

回復(fù)

使用道具 舉報

ID:130231 發(fā)表于 2017-3-17 12:58 | 顯示全部樓層
感謝分享
回復(fù)

使用道具 舉報

ID:141123 發(fā)表于 2017-3-17 16:19 | 顯示全部樓層
挺不錯的~~~
回復(fù)

使用道具 舉報

ID:45225 發(fā)表于 2017-4-10 15:02 | 顯示全部樓層
不錯不錯,有借鑒價值!
回復(fù)

使用道具 舉報

ID:245836 發(fā)表于 2018-5-7 19:06 | 顯示全部樓層

不錯不錯,有借鑒價值!
回復(fù)

使用道具 舉報

ID:335410 發(fā)表于 2018-5-22 08:56 | 顯示全部樓層
謝謝分享,對畢業(yè)設(shè)計很有幫助
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 午夜影视在线观看 | 亚洲欧美视频一区二区 | 国产乱一区二区三区视频 | 成人黄色av网站 | caoporn免费 | 免费不卡av| 精品亚洲一区二区 | 狠狠操狠狠干 | 日韩精品极品视频在线观看免费 | 久久精品一区二区三区四区 | 在线看一区二区 | 久久亚洲天堂 | 久久精品 | 欧美国产日韩在线观看 | 精品国产一区二区三区久久影院 | 国产精品18hdxxxⅹ在线 | 毛片免费视频 | 一区二区三区日韩精品 | 国产精品美女久久久久久不卡 | 密乳av| 亚洲精品电影网在线观看 | 欧美人成在线视频 | 欧美三级在线 | 91影院 | 隔壁老王国产在线精品 | 久久婷婷麻豆国产91天堂 | 久久久久国产精品一区二区 | 久久国产精品无码网站 | 中文字幕免费中文 | 亚洲一区二区三区在线视频 | 人人干人人艹 | 欧美国产精品 | 国产成人免费一区二区60岁 | 日日日视频 | 中文字幕观看 | 国产精品二区三区 | 日韩精品一区二区三区在线观看 | 国产情侣啪啪 | 97色在线观看免费视频 | 欧美性精品 | 精品一区二区三区在线观看 |