基于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();
    }
}

 

 

 

 

 

 

 

 

 

posted on 2020-11-16 00:04  chaina_家长  阅读(2434)  评论(0编辑  收藏  举报