单片机交流
直播中

陈燕

7年用户 1099经验值
私信 关注
[问答]

如何使用超声波模块实现测距功能?

超声波测距原理是什么?

如何使用超声波模块实现测距功能?

回帖(1)

张海宝

2021-10-27 10:54:08
使用超声波模块实现测距功能,测量结果显示在LCD1602上、并通过串口发送给电脑,测量距离大于或小于5~400cm,LCD1602显示“Waring!”同时蜂鸣器报警、串口发送“Waring”。
超声波测距原理

超声波测距的方法有很多种,最常用的是脉冲回波法。原理框图如图,





超声波传感器发射超声波,在空气中传播至被测目标,经反射后由超声波传感器接收反射脉冲,测量出超声波脉冲从发射到接收的时间,经过计算 S=1/2vt 可以得到距离。h较小时,S≈d ,所以通过测量超声波往返时间,就可以计算出距离长短。
HC-SR04模块

工作原理:采用IO触发测距,给trig至少10us的高电平信号;
模块自动发送8个40khz的方波,自动检测是否有信号返回;有信号返回,通过IO输出一高电平,高电平持续的时间就是超声波从发射到返回的时间。
时序图如下图所示:





具体实现,控制口发一个10us以上的高电平,就可以在接收口等待高电平输出。一有输出就可以开定时器计时,当接收口变为低电平时就可以读定时器的值,此时就为此次测距的时间,从而算出距离。如此不断地周期测量,就可以达到移动测量的值。
代码


#include       
#include
***it trig=P1^1;                                //控制端口定义
***it echo=P1^0;                                //接收端口定义
***it RS=P3^5;                            //lcd1602数据/命令端
***it EN=P3^4;                             //使能端
***it U1=P2^6;                       //数码管段选
***it U2=P2^7;                       //数码管位选
***it bi=P2^3;                       //buzz


unsigned char str[]={"Distance:"};      //lcd显示字符串
unsigned char juli[]={"0000cm"};        //lcd距离显示字符串
unsigned char change[]={"rn"};        //串口打印换行符
unsigned char jg[]={"Waring"};          //串口打印
unsigned int time;                            //时间
unsigned long s;                            //距离
bit flag=0;                             //标志位(定时器)
bit flag1=0;                            //标志位(串口打印)


void delayms(unsigned int xms);         //延时
void buzz();                            //蜂鸣器
void wcmd(unsigned char cmd)            //写命令
{
    RS = 0;                     
    P0 = cmd;
        delayms(5);
    EN = 1;
        delayms(5);
    EN = 0;   
}
void wdat(unsigned char dat)            //写数据
{
        RS = 1;
        P0 = dat;
        delayms(5);
        EN = 1;
        delayms(5);
        EN = 0;
}  
void Init()                             //1602初始化
{        U1=0;                           
    U2=0;
    EN=0;
    wcmd(0x38);                         //功能设置:8位,2行,5*7
    wcmd(0x0c);                         //显示控制:显示,有光标,闪烁
    wcmd(0x06);                         //输入模式:光标右移,屏不移位
    wcmd(0x01);                         //清屏   
}


void wstr(unsigned char addr,unsigned char *p)  
{
    wcmd(addr);     
    while(*p!='')  
    {   wdat(*p);   
        p++;        
    }   
}
void start()                            //超声波发送模块
{   
    trig=1;                                            
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    trig=0;                                     
}
void count()                            //距离计算
{   time=TH0*256+TL0;                               
    s=time*1.7/100;                                    
    if((s>400)||(s<5)||(flag==1) )
    {   wstr(0xC0,"Waring!");
        buzz();
        flag1=1;
    }
    else                                                               
    {
        juli[3] = s%10+0x30;                               
        juli[2] = s/10%10+0x30;                       
        juli[1] = s/100%10+0x30;                    
        juli[0] = s/1000+0x30;                               
        wstr(0xC0,"       ");
        wstr(0xC0,juli);
        flag1=0;
    }
    TH0=0x00;                                               
    TL0=0x00;                                               
    flag=0;                                                       
}
void uart()                             //串口
{   
    TMOD |= 0x20;                       //定时器模式1  
    TH1 = 0xFD;                         //波特率9600   
    TL1 = 0xFD;
    TR1 = 1;                            //打开定时器
    REN = 1;                            //允许串行接收
    SM0 = 0;                            //串行口工作方式1
    SM1 = 1;                           
    ES = 1;                             //允许串行中断
}
void main()
{   
    unsigned char i,j;
    Init();                                            //LCD初始化
    wstr(0x80,str);          
    TMOD=0x01;                          
    TH0=0x00;                          
    TL0=0x00;                          
    EA=1;                               
    ET0=1;       
    uart();                             //串口初始化
    while(1)
    {
        start();                                   
        while(echo==0);                 //接收到才打开定时器
        TR0=1;                          
        while(echo==1);                 //接收不到后就关闭定时器
        TR0=0;                          
        count();                          
        delayms(1000);
        for(i=0;i<=5;i++)
        {   
            if(flag1==0)
            {   SBUF=juli;
                while(TI==0);           //发完后TI会被置为1
                TI = 0;                 //TI置为0,为了下一次传输
            }
            else
            {   
                SBUF=jg;
                while(TI==0);
                TI = 0;
               
            }
        }
        for(j=0;j<=3;j++)
        {
            SBUF=change[j];
            while(TI==0);
            TI = 0;
        }
    }
}
void buzz()
{
    bi=0;
    delayms(200);
    bi=1;
}
void delayms(unsigned int xms)     
{
    unsigned int i,j;
    for(i=xms;i>0;i--)
        for(j=110;j>0;j--);
}
void InterruptTimer0() interrupt 1                          
{
    flag=1;                                       
}
开发板效果图












举报

更多回帖

×
20
完善资料,
赚取积分