【Proteus】超声波测距

本文详细介绍了在Proteus8.6版本中使用超声波模块进行测距的原理和方法,包括驱动程序的编写、定时器的配置以及1602液晶屏的显示。在驱动程序中,通过拉高Trig引脚10us触发超声波发射,然后通过Echo引脚检测返回时间并计算距离。在遇到Echo引脚逻辑争用问题时,作者给出了解决方案,并提供了完整的C语言代码实现。

前言:

在proteus8.6版本已经有了超声波模块,之前的proteus7版本中是没有这个的,只能够通过信号模拟超声波,或者就是自己制作超声波模块的模型,不过意思都差不多,现在既然proteus已经有了这个模块,就可以拉出来玩一下,看看实际的效果如何。压缩包链接放在最后。

超声波的驱动:

有关这种超声波模块的驱动程序,应该还是比较好写的,没有像IIC协议等引脚时序那样略微复杂,而且驱动程序又比较通用,关于这个超声波模块的驱动原理,在淘宝上随便搜一下,下面都有比较详细的介绍,这里我就随便找了一家:

这个写得清楚明白,简单易懂,就是先将Trig脚拉低,然后给到Trig引脚一个至少10us的高电平信号,然后再拉低。之后模块就会自动向外发送超声波,我们只需要等待Echo管脚变为高电平就可以了。这个Echo管脚高电平的时间就带有距离信息。具体的距离计算公式也给出了:

测试距离 = (高电平时间 * 声速)/ 2;

那么,我们编程的思路就有了,先将Trig管脚置低,然后给Trig引脚一个至少10us延时的高电平信号,然后再拉低,然后等待Echo管脚的高电平信号,当Echo接收到高电平信号时,就打开定时器,在定时器中断中使用一个变量来计时,记录Echo管脚的高电平时间,当Echo变为低或者时间过长时,跳出循环,进行距离计算。因为可能前方没有障碍物,导致高电平时间很长,程序就在这里一直等待,而且此时的长距离信号也没有什么意义了,因此加上了时间过长时也会跳出循环。这个可以根据自己的实际情况来进行超时时间的调整。这样子,我们的大概的驱动函数就有了:

//超声波测量距离
void measure()
{
   float ult = 0.0f;
   Trig = 1;
   delay_20us();
   Trig = 0;
   while(Echo == 0);  //等待高电平
   TR0 = 1;  //打开定时器0
   time = 0;	//计时清零
   while((Echo == 1)&&(time <= 2000)); //等待Echo变为低电平或超出时间限制	2000us 
   
   //距离计算
   ult = (float)time;    
   distance = (int) (34.0f * (ult / 100.0f)); //单位cm  34 * time/100 
   if(distance > 1000)
   {
   	distance = 1000;
   }
   TR0 = 0;  //关闭定时器
   time=0;
   ult=0;
}

关于定时器的问题,应该已经有很多关于51单片机的定时器的内容,这里就不在一个个寄存器来解释了。可以查阅相关的资料。在上面的驱动函数中,我们使用了time这个变量来计时。我们的定时器初始化配置如下:

/**********************************
初始化函数
***********************************/
void init()	  
{
   TMOD = 0x01;	//设置定时器工作方式,第二位为定时器0
   TH0 = (65536 - 10)/256; //定时器0高8位  10us
   TL0 = (65536 - 10)%256; //定时器0低8位
   TR0 = 1;	   //打开定时器
   ET0 = 1;	   //开定时器中断
   EA = 1;     //开总中断
}

定时器中断如下:

void T0_time() interrupt 1
{
    TH0 = (65536 - 10)/256; //定时器0高8位  10us
    TL0 = (65536 - 10)%256; //定时器0低8位
    time ++;
}

可以看到,time每计数一次,代表10us的时间,即0.00001秒,那么距离公式就是:

距离 = (time * 0.00001 * 340 / 2)单位:米

我们可以将单位换算为厘米,这样显示起来更加方便,而且proteus8中的超声波模块,也是按照厘米来发送电平的,因此转换为厘米就是:

距离 = time * 0.001 * 340 / 2 = time * 0.01 * 34 / 2 单位:cm

可以看到,这里正常应该是有一个除以2的,但我在实际测试中发现,proteus中的超声波模块显示的距离,发回给我的信号并没有除以2,因此我就没有除,也可能是我部分步骤有问题,欢迎指正,也可以根据自己情况进行修改。

之后是proteus原理图的绘制,正如文章开头的图片:

使用一个1602来显示距离,具体1602的驱动程序的文章,可以查看我之前的文章:【Proteus】单片机配合矩阵键盘LCD1602制作简易计算器 - 知乎

之后便是使用proteus来调试。

小技巧:我们可以在proteus的Message窗口查看proteus的仿真过程

当然,我这里是已经成功的截图,最开始仿真我也是不成功的,这里有一个小插曲:

如上图,我最开始的main中初始化时,是将Echo引脚置0的,之后仿真时,Echo引脚的电平就不会变化了,一直等不到想要的高电平,此时Message窗口的提示信息如下:

Message窗口提示Echo引脚发生了逻辑争用,之后我就一直等不到高电平信号了,解决办法就是在初始化时不要管这个Echo,可能只有Proteus仿真需要这样,如果是真实的超声波模块,应该不会有这种问题,最后的main如下:

void main()
{
   lcd_init();  
   Trig=0;
 //  Echo=0;  
   init(); //定时器初始化 
   display();  //显示函数      
   while(1)
   {
	 measure();	 //测量距离
     display();  //显示函数
	 delay_ms(100);
   }
}

main.c中所有代码如下:

#include <reg52.h>
#include <stdio.h>
#include "1602.h"
#define uchar unsigned char
#define uint unsigned int
uchar direction;
int distance = 0;
int time = 0;	    //超声波计时
sbit Trig = P1^0;
sbit Echo = P1^1;


//延时20us 使能超声波
void delay_20us()
{  
	uint bt ;
	for(bt = 0;bt < 100;bt ++);
}
 //延时10us 超声波使用
void delay_10us()
{  
	uint bt ;
	for(bt = 0;bt < 30;bt ++);
}

/**********************************
初始化函数
***********************************/
void init()	  
{
   TMOD = 0x01;	//设置定时器工作方式,第二位为定时器0
   TH0 = (65536 - 10)/256; //定时器0高8位  10us
   TL0 = (65536 - 10)%256; //定时器0低8位
   TR0 = 1;	   //打开定时器
   ET0 = 1;	   //开定时器中断
   EA = 1;     //开总中断
}

//超声波测量距离
void measure()
{
   float ult = 0.0f;
   Trig = 1;
   delay_20us();
   Trig = 0;
   while(Echo == 0);  //等待高电平
   TR0 = 1;  //打开定时器0
   time = 0;	//计时清零
   while((Echo == 1)&&(time <= 2000)); //等待Echo变为低电平或超出时间限制	2000us 
   
   //距离计算
   ult = (float)time;    
   distance = (int) (34.0f * (ult / 100.0f)); //单位cm  34 * time/100 
   if(distance > 1000)
   {
   	   distance = 1000;
   }
   TR0 = 0;  //关闭定时器
   time=0;
   ult=0;
}

//显示函数
void display()
{
   char *string = "distance :";
   char *string2 = "cm";
   char Z[16];
   //显示距离
   sprintf((char*)Z,"%s%d%s",string,distance,string2);						   
   print_string(Z,1);
 //  write_com(0x8a);
}					

void main()
{
   lcd_init();  
   Trig=0;
 //  Echo=0;  
   init(); //定时器初始化 
   display();  //显示函数      
   while(1)
   {
	 measure();	 //测量距离
         display();  //显示函数
	 delay_ms(100);
   }
}

void T0_time() interrupt 1
{
	TH0 = (65536 - 10)/256; //定时器0高8位  10us
    TL0 = (65536 - 10)%256; //定时器0低8位
	time ++;

}

工程链接:通过网盘分享的文件:超声波测距
链接: https://pan.baidu.com/s/1mbsQwYxBNk83EfTRcvhIow 提取码: h35t

电子乐屋Proteus是一款集成电路设计与仿真软件,可以帮助电子工程师进行电路设计和虚拟仿真。其中,Proteus超声波测距仿真模块是该软件中一个重要的功能模块。 超声波测距技术利用超声波在空气中传播速度较快的特性,通过发送超声波信号并接收回波的方式,计算出目标物体与传感器之间的距离。这种技术在许多领域被广泛应用,如自动停车系统、无人机避障等。 Proteus超声波测距仿真模块能够帮助工程师在虚拟环境中进行超声波测距系统的设计和仿真。首先,用户可以在Proteus中选择合适的超声波传感器模型,并设置其工作参数,如发送信号频率和接收灵敏度等。然后,用户可以将该模型与其他电路组件进行连接,构建完整的测距系统。 一旦完成了超声波测距系统的建模,用户就可以通过Proteus的仿真功能来验证其性能。Proteus提供了详细的波形图分析和测距算法仿真工具,可以帮助用户评估系统的准确性和稳定性。此外,Proteus还支持用户设计并调试其他相关电路功能模块,如信号处理电路和显示电路等。 总体而言,Proteus超声波测距仿真模块为电子工程师提供了一个方便而强大的工具,帮助他们设计、模拟和优化超声波测距系统。通过该模块,工程师可以在虚拟环境中迅速验证设计的正确性,提高工作效率,并最终实现更优秀的导航和测距功能。
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙猫略略略

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值