资讯详情

【Proteus】超声波测距

前言:

在proteus8.6版本已经有了超声波模块,以前proteus7版本中没有这样的模型,只能通过信号模拟超声波,或者自己制作超声波模块,但意思是一样的。proteus已经有了这个模块,就可以拉出来玩一下,看看实际的效果如何。

这个超声波模块的驱动程序应该更容易写,不像IIC协议和其他引脚顺序有点复杂,驱动程序更通用,关于这个超声波模块的驱动原理,在淘宝上搜索,下面有更详细的介绍,这里我随便找到一个:

这个写得很清楚,很容易理解,就是先把Trig低脚,然后给Trig至少10个引脚us然后降低高电平信号。然后模块会自动向外发送超声波,我们只需要等待Echo管脚可以变成高电平。Echo管脚高电平时间有距离信息。还给出了具体的距离计算公式:

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

所以,我们有编程的想法,先将Trig把管脚放低,然后给Trig至少10个引脚us高电平信号延迟,然后降低,然后等待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)%6; //定时器0低8位    TR0 = 1;    ///打开定时器    ET0 = 1;    ///开定时器中断    EA = 1;     ///开总中断 }

定时器中断如下:

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

可以看到,time每次计数一次,代表10次us的时间,即0.0001秒,距离公式为:

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

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

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

可以看出,这里应该有一个除以2,但我在实际测试中发现,proteus超声波模块中显示的距离没有除以2,所以我没有除以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)%6; //定时器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() interupt 1
{
	TH0 = (65536 - 10)/256; //定时器0高8位  10us
    TL0 = (65536 - 10)%256; //定时器0低8位
	time ++;

}

标签: 11ea开关传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台