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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3243|回復: 4
打印 上一主題 下一主題
收起左側

基于51單片機帶溫度補償的超聲波測距(超聲波模塊+18B20+1602液晶)

[復制鏈接]
跳轉到指定樓層
樓主
ID:846211 發表于 2021-1-11 19:03 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
超聲波測距(超聲波模塊+18B20+1602液晶)  
#include"reg52.h"
#include"math.h"
#define uchar unsigned char
#define uint unsigned int
#define LcdData P0                   //1602數據端口
sbit LCD_RS=P3^5;      //1602 RS端口
sbit LCD_RW=P2^5;      //1602 RW端口
sbit LCD_EN=P3^4;      //1602 EN端口
sbit Echo=P1^6;        //HC-SR04 接收端口
sbit Trig=P1^7;        //HC-SR04 發射端口
sbit Resets_Key=P3^3;  //復位清零按鍵
sbit Single_Key=P3^2;  //單次測量按鍵    誤差較大
sbit Contin_Key=P1^3;  //連續測量按鍵    誤差小
sbit Averag_Key=P1^2;  //連續(平均測量)按鍵   誤差較小
sbit DQ=P2^2;          //DS18B20單總線接口
bit Temp_Flag;         //正負溫度標志:溫度為正Temp_Flag=0,否則為1
uint temp=25;          //溫度值
bit flag_flow=0,flag_one=0,flag_clear=0,flag_con1=0,flag_con2=0,flag_temp=0;
uchar i=0,m,j,k;
uint time=0,S=0,S1=0,totle=0;
float V=346.0;
uint Sav[11];                                                          //連續測量時10次平均值數組
uchar Line1[16]={"T:   C  V:346m/s"};          //1602第一行初始字符顯示數組
uchar Line2[16]={"S=     m        "};          //1602第二行初始字符顯示數組
void Delayms(uchar xms);                        //延時xms函數
void WriteLcd(uchar Dat,bit x);        //1602寫函數
void InitLcd(void);                                //1602初始化函數
void DisplayLcd();                                //1602顯示函數
void init();                                        //初始化函數
void keyscan();                                        //鍵掃描函數
void StartModule();                            //啟動模塊函數
void Conut(void);                                 //測量計算函數
void Delayus(uchar xus);        //us級延時函數
bit Init_DS18B20(void);         //初始化DS18B20函數
uchar Read_DS18B20(void);       //讀DS18B20函數
void Write_DS18B20(uchar Dat);  //寫DS18B20函數
void GetTemp();                 //取溫度函數
void CalcTestTemp();            //溫度處理函數
void main(void)    //主函數
{
        init();
        InitLcd();
        while(1)
        {
                keyscan();                         //鍵掃描函數
            DisplayLcd();
            if(flag_temp==0)
            {
                    GetTemp();
                    CalcTestTemp();
            }
            if(flag_one==1||flag_con1==1||flag_con2==1)
            {
                    StartModule();         //開始發射超聲波
                while(!Echo);                 //當RX為零時等待
            TR0=1;                         //開啟計數
            while(Echo);             //當RX為1計數并等待
                TR0=0;                         //關閉計數
            Conut();                 //計算
            Delayus(200);
                flag_one=0;
            }
        }
}
void Delayms(uchar xms)   //延時ms函數
{
    uchar i,j;
    for(i=xms;i>0;i--)
            for(j=110;j>0;j--);
}
void WriteLcd(uchar Dat,bit x)  //1602寫函數(寫指令時x=0,寫數據時x=1)
{
        LCD_EN=0;
        LcdData=Dat;
        LCD_RS=x;
        LCD_RW=0;
        LCD_EN=1;
        Delayms(1);
        LCD_EN=0;
}
void InitLcd(void)           //1602初始化函數
{
        WriteLcd(0x38,0);  //功能設定(38H),8位數據,2行顯示,5*7點陣
        WriteLcd(0x0C,0);  //顯示開、關設定(0CH),開顯示,不顯示光標,光標不閃爍
        WriteLcd(0x06,0);  //輸入模式設定(06H),讀寫一個字符后,地址指針加1,且光標加1
        WriteLcd(0x01,0);  //清除顯示(01H),清除數據RAM中的數據
}
void DisplayLcd()                                  //液晶屏顯示函數
{
    uchar y;
    V=(331.4+temp*0.607);
    Line1[2]=temp/10+0x30;
    Line1[3]=temp%10+0x30;
    Line1[4]=0xDF;                  //顯示℃中C前面的小圓
    Line1[10]=(uint)V/100+0x30;
    Line1[11]=(uint)V%100/10+0x30;
    Line1[12]=(uint)V%10+0x30;
    if(flag_clear==1)
    S1=0;
    if((S1>=7000)||flag_flow==1)    //超出測量范圍顯示“-”
        {         
            flag_flow=0;
            Line2[2]='-';
            Line2[3]='.';
            Line2[4]='-';
            Line2[5]='-';
            Line2[6]='-';
        }
    else
        {
                        Line2[2]=S1/10;
            Line2[2]=S1/1000+0x30;
            Line2[3]='.';
            Line2[4]=S1%1000/100+0x30;
            Line2[5]=S1%100/10+0x30;
            Line2[6]=S1%10+0x30;
        }
    WriteLcd(0x80,0);               //設定第一行地址
    for(y=0; y<16; y++)
        WriteLcd(Line1[y],1);
    WriteLcd(0xc0,0);               //設定第二行地址
    for(y=0; y<16; y++)
        WriteLcd(Line2[y],1);
}
void init()        //初始化函數
{
    TMOD=0x01;        //設T0為方式1,GATE=1;
    TH0=0;
    TL0=0;         
    ET0=1; //允許T0中斷
    EA=1;  //開啟總中斷
}
void keyscan()                         //鍵掃描函數
{
    if(Resets_Key==0)                         //復位清零鍵
    {
        Delayms(5);
        if(Resets_Key==0)
        {
                while(Resets_Key==0);
            flag_clear=1;
            }
    }
    if(Single_Key==0)                         //單次測量鍵
    {
        Delayms(5);
        if(Single_Key==0)
        {
                while(Single_Key==0);
                flag_one=1;
            flag_con1=0;
                flag_con2=0;
                flag_clear=0;
            }
    }
    if(Contin_Key==0)                         //連續瞬時測量鍵
    {
        Delayms(5);
        if(Contin_Key==0)
        {
                while(Contin_Key==0);
                flag_con1=~flag_con1;
                if(flag_con1==1)
                {
                    flag_one=0;
                    flag_con2=0;
                    flag_clear=0;
                }
            }
    }
    if(Averag_Key==0)                        //連續平均測量鍵
    {
        Delayms(5);
        if(Averag_Key==0)
        {
                while(Averag_Key==0);
                flag_con2=~flag_con2;
                if(flag_con2==1)
                {
                    flag_one=0;
                    flag_con1=0;
                    flag_clear=0;
                }
            }
    }
}
void StartModule()                        //啟動模塊函數(觸發一次,提供大于10us的高電平)
{
    Trig=1;                                       //啟動一次模塊
    Delayus(15);                                    //延時2i+5=35us
    Trig=0;
}
void Conut(void)                           //測量計算函數
{
    time=TH0*256+TL0;
    TH0=0;
    TL0=0;
    V=(331.4+temp*0.607);        //由溫度計算速度值,單位是m/s
    S=(uint)(time*V/2000);       //算出來是mm
    if(flag_con2==1)                           //如果是連續測量,則取10次的平均值
    {
        if(k<=10)
            k++;
            if(k>=11)
        k=1;
            Sav[k]=S;
            j++;
            if(j<10)
            S1=S;
            if(j>=10)
            {
                j=10;
                for(m=1;m<=10;m++)
            totle=totle+Sav[m];
            S1=(uint)(totle/10);              //取10次的平均值
                totle=0;
        }
    }
    if(flag_one==1||flag_con1==1)          //如果是單次測量或連續瞬時測量,則取1次的值
    {
        S1=S;
    }
}
void Delayus(uchar xus) //晶振為12MHz,延時時間為2i+5 us
{
    while(--xus);
}
bit Init_DS18B20(void)
{
        bit x;
        DQ=1;
        DQ=0;
        Delayus(250);
        DQ=1;
        Delayus(20);
        if(!DQ) x=0;
        else x=1;
        Delayus(250);
        DQ=1;
        return x;
}
//讀DS18B20函數
uchar Read_DS18B20(void)
{
        uchar i=0,Dat=0;
        for(i=0;i<8;i++)
        {
                DQ=1;
                DQ=0;
                Dat>>=1;
                DQ=1;
                if(DQ) Dat |= 0x80;
                DQ=1;
                Delayus(30);
        }
        return Dat;
}
//寫DS18B20函數
void Write_DS18B20(uchar Dat)
{
        uchar i=0;
        for(i=0;i<8;i++)//循環8次,寫入一個字節
        {
                DQ=1;//未發送前的狀態
                Dat >>= 1;//將要傳送的最低位放入CY
                DQ=0;//將總線拉低,產生寫時序
                DQ=CY;//將要傳送的位狀態送到總線上
                Delayus(30);//延時50us,即保持總線狀態,待DS18B20采樣
                DQ=1;//恢復期,總線置1
        }
}
void GetTemp(void)       //獲取溫度函數
{
        uchar a=0,b=0;
        Init_DS18B20();
        Write_DS18B20(0xcc); //跳過ROM
        Write_DS18B20(0x44); //開啟溫度轉換
        Init_DS18B20();
        Write_DS18B20(0xcc); //跳過ROM
        Write_DS18B20(0xbe); //讀暫存器
        a=Read_DS18B20();    //讀取高速暫存字節0,溫度低8位
        b=Read_DS18B20();    //讀取高速暫存字節1,溫度高8位
        temp=b;
        temp<<=8;
        temp=temp|a;         //將高、低位溫度編碼合在一起
        if(b>=8)             //判斷溫度值是否為負,如果溫度高字節大于等于8說明溫度值為負
        {
            temp=~temp+1;      //將補碼轉換成原碼
            Temp_Flag=1;       //溫度標志為1,表示溫度為負
        }
        else
        {
            Temp_Flag=0;       //溫度標志為0,表示溫度為正
        }
        temp=temp*0.0625+0.5;//將溫度編碼轉換成溫度值,加0.5是為了四舍五入
}
void CalcTestTemp()                              //溫度處理函數
{
        if(temp<100) Line1[2]=' ';        //如果溫度值小于10,十位顯示空白(不顯示0)
        else Line1[2]=temp%100/10+0x30;   //取溫度十位并轉換成ASCII碼
        Line1[3]=temp%10+0x30;            //取溫度個位并轉換成ASCII碼        
}
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:866047 發表于 2021-3-2 14:17 | 只看該作者
有沒有對應的電路圖啊
回復

使用道具 舉報

板凳
ID:965040 發表于 2023-10-26 15:43 | 只看該作者
實測可用,感謝分享
回復

使用道具 舉報

地板
ID:965040 發表于 2023-10-26 15:53 | 只看該作者
實際測試,可以使用,感謝分享
回復

使用道具 舉報

5#
ID:965040 發表于 2023-10-26 16:04 | 只看該作者
實測功能正常,感謝分享
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲天堂av一区 | xxx国产精品视频 | 国产精品久久久久久久久久久久 | 亚洲人成人一区二区在线观看 | 国产成人区 | 成人做爰999 | 成人高清在线 | 91精品久久久久久久久中文字幕 | 中文字幕蜜臀 | 91av视频在线观看 | 久久久久久999 | 午夜丰满少妇一级毛片 | 亚洲国产区 | 国产99久久久国产精品 | 精品一区二区三区在线观看国产 | 在线欧美一区 | 欧美一区二区三区精品 | 亚洲一区 中文字幕 | 亚洲午夜视频在线观看 | 色婷婷一区二区三区四区 | 免费视频一区二区三区在线观看 | 青青草综合网 | 精品视频在线观看 | 西西裸体做爰视频 | 韩三级在线观看 | 亚洲精品一区二区三区四区高清 | 毛片免费看的 | 免费网站国产 | 91精品在线看 | 麻豆av网| 在线看片国产精品 | 国产网站在线播放 | 日韩欧美高清 | 一区二区三区电影在线观看 | 欧美一区二区大片 | 欧美一区二区 | 美女逼网站| 成人av播放| 日韩精品一区在线 | 国产高清精品在线 | 成人99 |