基於51單片機的超聲波模塊HC-SR04的使用


超聲波模塊工作原理:

     (1)采用IO觸發測距,給至少10us的高電平信號;

       (2)模塊自動發送8個40khz的方波,自動檢測是否有信號返回;

    (3)有信號返回,通過IO輸出一高電平,高電平持續的時間就是

          超聲波從發射到返回的時間.測試距離=(高電平時間*聲速(340M/S))/2; 

定時器初始化:

考慮到原理(3)有信號返回時輸出一個高電平,所以TMOD設置為0x09,GATE=1(需要TR0和中斷0(INT0)口都=0,中斷才會啟動),然后用杜邦線將中斷0的引腳和超聲波模塊的I0口(echo口)連接,這樣當超神波返回時,echo=1,INT0=1,中斷啟動。

我試過將初始設置為10us和100us兩種,10us時,s=vt,100us時,s=vt/2,按照公式s=vt/2才是正確的,但是我10us時,值相差也不大,不知道什么原因,但是這個不對,所以下面代碼中,用的是100us這個。

------------------------------------------------分割線----------------------------------------------------------------

 

#include "reg52.h"

typedef unsigned char uchar;
typedef unsigned int uint;

sbit trig=P2^0;
sbit echo=P2^1;
sbit beep=P1^5;

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

uint num=0;           //計時
float distance;       //距離
float cm_per_num=3.40; //按照我的定時器初始化設定,1個num是100us
uchar DisplayData[6];
uchar code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                    0x7f,0x6f};//顯示0~9的值

void delay1ms(uchar xms)   
{
    uchar a,b,c;
    for(c=xms;c>0;c--)
        for(b=142;b>0;b--)
            for(a=2;a>0;a--);
}

 /*
設置工作方式為方式1,GATE=1,當中斷0口輸入1且TR0=1 時定時器工作
因為超聲波模塊的工作原理就是在接收回波時,從開始到結束,ech0=1
所以在單片機上用杜邦線將ech0的P21口和 中斷0口 P32口鏈接
使得在回波期間,定時器工作,計算回波的時間,進而s=vt算出距離 
 */
void TimerInit()      //初始化,定時10us
{
    TMOD = 0x09;     
    TH0 = 0xFF;
    TL0 = 0x9C;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}

void Timer0() interrupt 1      //中斷 每過100us,num+1
{
    TH0 = 0xFF;
    TL0 = 0x9C;
    num++;
}

void value_distance()
{
    trig=0;
    echo=0;
    delay1ms(1);
    trig=1;
    delay1ms(11); //給trig一個10us以上的高電平信號
    trig=0;
    if(echo==1)       //如果有反射回的超聲波,echo腳會在這期間持續輸入高電平
    {
        delay1ms(300);        //接收超聲波期間不做任何動作。
    }
    distance=num*cm_per_num/2;   //計算距離,單位CM
    num=0;
        
}

void datapros()             //對取得的距離進行處理
{
    float a= distance*100;    
    DisplayData[0]=smgduan[(int)a%10];
    DisplayData[1]=smgduan[(int)a%100/10];
    DisplayData[2]=smgduan[(int)a%1000/100]+0x80;     //數字+小數點
    DisplayData[3]=smgduan[(int)a%10000/1000];
    DisplayData[4]=smgduan[(int)a/10000];    
        
}

void DigDisplay()               //數碼管顯示
{
    uchar i;
    for(i=0;i<6;i++)
    {
        switch(i)     //位選,選擇點亮的數碼管,
        {
            case(0):
                LSA=0;LSB=0;LSC=0; break;//顯示第0位
            case(1):
                LSA=1;LSB=0;LSC=0; break;//顯示第1位
            case(2):
                LSA=0;LSB=1;LSC=0; break;//顯示第2位
            case(3):
                LSA=1;LSB=1;LSC=0; break;//顯示第3位
            case(4):
                LSA=0;LSB=0;LSC=1; break;//顯示第4位
            case(5):
                LSA=1;LSB=0;LSC=1; break;//顯示第5位
        }
        P0=DisplayData[i];//發送段碼
        delay1ms(1); //間隔一段時間掃描    
        P0=0x00;//消隱
    }
}

void main()
{
    while(1)
    {
        TimerInit();
        value_distance();
        datapros();
        DigDisplay();
    }
}

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM