找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 1619|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

超聲波測試儀的設(shè)計(jì)仿真

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主


#include <reg51.h>                                //預(yù)處理命令,定義SFR的頭
#include <math.h>
#include <intrins.h>                           //內(nèi)部函數(shù)庫文件
#define uchar unsigned char            //定義縮寫字符uchar
#define uint unsigned int                //定義縮寫字符uint
#define lcd_data P0            //定義LCD1602接口 P0
sbit DQ =P1^7;                             //將18B20DQ位定義為P1.7引腳
sbit lcd_RS=P2^0;                           //將18B20RS位定義為P2.0引腳
sbit lcd_RW=P2^1;                           //將18B20RW位定義為P2.1引腳
sbit lcd_EN=P2^2;                           //將18B20EN位定義為P2.2引腳       
sbit BEEP=P3^0;              //測量超出指定范圍,報(bào)警  
sbit Trig=P2^5;                  //HC-SR04觸發(fā)信號輸入
sbit Echo=P2^6;                  //HC-SR04回響信號輸出
uint Distance;              //測量的距離值
uint SPEEDSOUND;            //聲速
uint t[2];              //將距離轉(zhuǎn)換成十進(jìn)制數(shù)時(shí),中間變量
uchar Buffer1[12]={0x20,0x20,0x20,0x20,0x63,0x6d,'\0'};         //距離顯示cm
uchar tab[16]={0x20,0x20,0x20,0x20,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,'\0'};  //顯示"Distance"       
/**********lcd顯示子程序************/
void delay20us(void)        //20us延時(shí)
{   
  unsigned char a;   
  for(a=100;a>0;a--);
  }       

void delay_20ms(void)          /*延時(shí)20ms函數(shù)*/
{
   uchar i,temp;               //聲明變量i,temp
   for(i = 20;i > 0;i--)       //循環(huán)
   {
    temp = 248;                //給temp賦值248
    while(--temp);             //temp減1是否等于0,否則繼續(xù)執(zhí)行該行
    temp = 248;                //給temp賦值248
    while(--temp);             //temp減1是否等于0,否則繼續(xù)執(zhí)行該行
    }
}
void delay_38us(void)          /*延時(shí)38us函數(shù)*/
{   uchar temp;                //聲明變量temp
    temp = 18;                 //給temp賦值
    while(--temp);             //temp減1是否等于0,否則繼續(xù)執(zhí)行該行
}
void delay_1520us(void)         /*延時(shí)1520us函數(shù)*/
{  uchar i,temp;                //聲明變量i,temp
   for(i = 3;i > 0;i--)         //循環(huán)
   {
    temp = 252;                 //給temp賦值
    while(--temp);              //temp減1是否等于0,否則繼續(xù)執(zhí)行該行
    }
}
uchar lcd_rd_status( )          /*讀取lcd1602的狀態(tài),主要用于判斷忙*/
{
uchar tmp_sts;                 //聲明變量tmp_sts
lcd_data = 0xff;               //初始化P3口
lcd_RW = 1;                    //RW =1  讀      
lcd_RS = 0;                    //RS =0  命令,合起來表示讀命令(狀態(tài))
lcd_EN = 1;                    //EN=1,打開EN,LCD1602開始輸出命令數(shù)據(jù),100nS之后命令數(shù)據(jù)有效
tmp_sts = lcd_data;            //讀取命令到tmp_sts
lcd_EN = 0;                    //關(guān)掉LCD1602
lcd_RW = 0;                    //把LCD1602設(shè)置成寫
return tmp_sts;                //函數(shù)返回值tmp_sts
}
void lcd_wr_com(uchar command )  /*寫一個(gè)命令到LCD1602*/
{
  while(0x80&lcd_rd_status()); //寫之前先判斷LCD1602是否忙,看讀出的命令的最高位是否為1,為1表示忙,繼續(xù)讀,直到不忙
  lcd_RW = 0;
  lcd_RS = 0;                  //RW=0,RS=0 寫命令
  lcd_data = command;          //把需要寫的命令寫到數(shù)據(jù)線上
  lcd_EN = 1;  
  lcd_EN = 0;                  //EN輸出高電平脈沖,命令寫入
}
void lcd_wr_data(uchar sjdata )  /*寫一個(gè)顯示數(shù)據(jù)到lcd1602*/
{
while(0x80&lcd_rd_status());  //寫之前先判斷l(xiāng)cd1602是否忙,看讀出的命令的最高位是否為1,為1表示忙,繼續(xù)讀,直到不忙
lcd_RW = 0;
lcd_RS = 1;                   //RW=0,RS=1 寫顯示數(shù)據(jù)
lcd_data = sjdata ;            //把需要寫的顯示數(shù)據(jù)寫到數(shù)據(jù)線上
lcd_EN = 1;
lcd_EN = 0;                   //EN輸出高電平脈沖,命令寫入
lcd_RS = 0;                 
}
void Init_lcd(void)            /*初始化lcd1602*/
{
  delay_20ms();                //調(diào)用延時(shí)
  lcd_wr_com(0x38);            //設(shè)置16*2格式,5*8點(diǎn)陣,8位數(shù)據(jù)接口
  delay_38us();                //調(diào)用延時(shí)
  lcd_wr_com(0x0c);            //開顯示,不顯示光標(biāo)
  delay_38us();                //調(diào)用延時(shí)
  lcd_wr_com(0x01);            //清屏
  delay_1520us();              //調(diào)用延時(shí)
  lcd_wr_com(0x06);            //顯示一個(gè)數(shù)據(jù)后光標(biāo)自動+1
}       
void GotoXY(uchar x, uchar y)  //設(shè)定位置,x為行,y為列
{
        if(y==0)                        //如果y=0,則顯示位置為第一行
                lcd_wr_com(0x80|x);
        if(y==1)
                lcd_wr_com(0xc0|x);           //如果y=1,則顯示位置為第二行
}

void Print(uchar *str)                   //顯示字符串函數(shù)
{
        while(*str!='\0')                   //判斷字符串是否顯示完
        {
                lcd_wr_data(*str);           //寫數(shù)據(jù)
                str++;                                  
        }
}
void LCD_Print(uchar x, uchar y, uchar *str)//x為行值,y為列值,str是要顯示的字符串   
{
  GotoXY(x,y);                                   //設(shè)定顯示位置
  Print(str);                                   //顯示字符串
}
                                                  
/****溫度轉(zhuǎn)換函數(shù),2字節(jié)轉(zhuǎn)換為1字節(jié) *****************/

void convert1()                       //溫度轉(zhuǎn)化程序,存放在x
{
   uchar x=0x00;                           //變量初始化
   if(t[1]>0x07)               //判斷溫度為負(fù)值
   {
    x=14;
   }
   else                    //溫度為正值
    t[1]<<=4;                           //將高字節(jié)左移4位
    t[1]=t[1]&0x70;                       //取出高字節(jié)的3個(gè)有效數(shù)字位
    x=t[0];                                   //將t[0]暫存到X,因?yàn)槿⌒?shù)部分還要用到它
    x>>=4;                                           //右移4位
    x=x&0x0f;                                   //和前面兩句就是取出t[0]的高四位       
    t[1]=t[1]|x;                           //將高低字節(jié)的有效值的整數(shù)部分拼成一個(gè)字節(jié)
    x=t[1];                                                                 
  }

/*******************DS18B20初始化函數(shù)**********************/

void delay_18B20(uint i)                        //延時(shí)程序
{
        while(i--);
}
void Init_DS18B20(void)                          //ds18b20初始化函數(shù)
{
         uchar x=0;
         DQ = 1;                                          //DQ復(fù)位
         delay_18B20(8);                                  //稍做延時(shí)
         DQ = 0;                                          //單片機(jī)將DQ拉低
         delay_18B20(80);                                 //精確延時(shí)大于480us
         DQ = 1;                                          //拉高總線
         delay_18B20(14);
         x=DQ;                                            //稍做延時(shí)后 如果x=0則初始化成功 x=1則初始化失敗
         delay_18B20(20);
}
uchar ReadOneChar(void)                                 //ds18b20讀一個(gè)字節(jié)函數(shù)
{
        unsigned char i=0;
        unsigned char dat0 = 0;
        for (i=8;i>0;i--)
         {
                  DQ = 0;                    //讀前總線保持為低
                  dat0>>=1;
                  DQ = 1;                    //開始讀總線釋放
                  if(DQ)                                         //從DS18B20總線讀得一位
                  dat0|=0x80;
                  delay_18B20(4);                         //延時(shí)一段時(shí)間
         }
        return(dat0);                                     //返回?cái)?shù)據(jù)
}
void WriteOneChar(uchar dat1)                 //ds18b20寫一個(gè)字節(jié)函數(shù)
{
        uchar i=0;
        for (i=8; i>0; i--)
        {
                  DQ = 0;                                                 //開始寫入DS18B20總線要處于復(fù)位(低)狀態(tài)
                DQ = dat1&0x01;                                 //寫入下一位
            delay_18B20(5);
                DQ = 1;                                                 //重新釋放總線
            dat1>>=1;                                         //把一個(gè)字節(jié)分成8個(gè)BIT環(huán)移給DQ
}
}
void ReadTemperature()                            //讀取ds18b20當(dāng)前溫度
{       
        delay_18B20(80);                //延時(shí)一段時(shí)間
        Init_DS18B20();       
        WriteOneChar(0xCC);                // 跳過讀序號列號的操作
        WriteOneChar(0x44);           // 啟動溫度轉(zhuǎn)換
        delay_18B20(80);              // 延時(shí)一段時(shí)間
        Init_DS18B20();                                //DS18B20初始化
        WriteOneChar(0xCC);                 //跳過讀序號列號的操作
        WriteOneChar(0xBE);                 //讀取溫度寄存器等(共可讀9個(gè)寄存器) 前兩個(gè)就是溫度
        delay_18B20(80);                            //延時(shí)一段時(shí)間
    t[0]=ReadOneChar();                //讀取溫度值低位
    t[1]=ReadOneChar();               //讀取溫度值高位
}

void HCSR04_Initialize()     //HCSR04初始化
{  
  SPEEDSOUND=334.1+25*0.61;   //溫度25度時(shí)聲速的值
  Trig=0;   
  Echo=0;  
  TMOD=0x01;                         //T0定時(shí)方式1
}  

float MeasuringDistance()                 //測量距離
{  
TH0=0;  TL0=0;                           //最大定時(shí)時(shí)間約65ms
  Trig=1;                                      //生成20us脈沖寬度的觸發(fā)信號
  delay20us();           //20us脈沖
  Trig=0;
  while(!Echo);                           //等待回響信號變高電平
TR0=1;                                          //啟動定時(shí)器0
  while(Echo);                            //等待回響信號變低電平
TR0=0;                  //關(guān)閉定時(shí)器0
return (SPEEDSOUND*(TH0*256+TL0))/2000; }  //返回距離值mm

void DisplayDistance()         //顯示距離
{
Distance= MeasuringDistance();
if(Distance<20)
{
BEEP=0;
}   
        t[1]=Distance/10;
    Buffer1[1]=t[1]/100+0x30;    //加0x30 為變 0~9 ASCII碼
    Buffer1[2]=(t[1]%100)/10+0x30;     //分離出十位
    Buffer1[3]=(t[1]%100)%10+0x30;     //分離出個(gè)位       
    LCD_Print(4,1,Buffer1);             //顯示距離
}                    

/*************************main主程序*********************/
void main(void)
{
    uchar x;
        BEEP=1;                          //關(guān)閉報(bào)警   
        delay_20ms();           //系統(tǒng)延時(shí)20ms啟動
           Init_lcd();                        //調(diào)用LCD初始化函數(shù)
        delay_20ms();                                           //延時(shí)一段時(shí)間
        LCD_Print(0,0,tab);
    HCSR04_Initialize();                           //HC-SR04初始化
    while(1)
        {
        ReadTemperature();            //測溫度,存放在t[1]t[0]
    delay_18B20(100);
    convert1();               //溫度轉(zhuǎn)換,存放在x
        if(x<14)                       //溫度界限判斷
     x=14;
    else if(x>26)  
         x=26;
    SPEEDSOUND=334.1+x*0.61;    //聲速修正M/S
        DisplayDistance();                //顯示距離值
    }
   }


搜狗截圖18年12月05日1038_2.png (35.21 KB, 下載次數(shù): 45)

搜狗截圖18年12月05日1038_2.png

8超聲測距.rar

86.89 KB, 下載次數(shù): 6, 下載積分: 黑幣 -5

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

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

本版積分規(guī)則

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

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

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