超声波测距仿真

这篇具有很好参考价值的文章主要介绍了超声波测距仿真。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

超声波测距仿真


萌新第一次写博客,有格式不正确的地方还请大家见谅。

设计总体要求

  1. 用HCSR04超声波传感器测量距离,测量范围0~170cm,精确到小数点后一位。
  2. 用LCD1602或者数码管显示测量到的距离。
  3. 当距离大于120cm时,绿色LED灯亮;
    (1)当距离在50-120cm之间,蜂鸣器间断发声“滴 滴 滴 ”提示,黄色LED灯亮。
    (2)当距离低于50cm时,蜂鸣器持续报警,红色LED灯亮,显示报警信号(如warning)并闪烁。
  4. 临界值默认50和120cm,可以用按键调节临界值,需满足下限值<上限值。

系统的整体设计方案

  本设计的构建是基于89C51单片机外围芯片的超声信号检测的。超声波发生模块送出片刻的40KHz的矩形波信号,遇物体反射后,被超声波接收模块接收并作为本设计的Input,单片机对此信号进行判断加工处理后,把计算出的距离结果传到LCD显示屏上,当检测距离小于预设值时报警模块工作。
  本设计的硬件部分主要由AT89C51单片机控制模块、超声波发出和接收模块、预警模块以及LCD显示模块等几部分组成。系统的总体结构设计框图在第二部分展示。
  设计的硬件部分主要包括时钟信号子模块,复位电路子模块,参数修改子模块,信号灯子模块,AT89C51单片机,LCD1602液晶显示模块,超声波测距模块以及蜂鸣器模块。系统软件部分主要51主程序处理模块、delay子程序块、超声波发生与感应子程序模块等。

整体设计方案仿真图

超声波测距仿真,单片机,嵌入式硬件
  注意,使用protuse8.0以后的版本才能在元件库中找到SRF04超声波测距模块,老版本里面是不含这个模块的,要自己做。并且系统自带的模块只能设置整数的距离值(单位cm)。为了解决精确到小数点后一位的问题,额,需要使用一点小技巧

原件表单

2N4403,AT89C52,BUTTON,BUZZER,CAP,CRYSTAL,LED-GREEN,LED-RED,LED-YELLOW,LM016L,MZPY4V3RL,POT-HG,RES,RES10SIPB,RESPACK-8,SRF04

程序设计部分

  程序实现主要有LCD控制函数LCD1602显示函数超声波控制模块程序部分上限值和下限值的参数修改函数LCD显示距离函数检测距离计算并显示函数距离显示函数外部中断函数主函数延时函数

接口定义及变量定义部分

#include <reg51.h>
#include <intrins.h>
#include "delay.h"
#define LCD1602_shuru P0
//接口定义
sbit LCD1602_E=P2^2;
sbit LCD1602_RW=P2^1;
sbit LCD1602_RS=P2^0;
sbit RED=P2^7;
sbit GREEN=P2^5;
sbit YELLOW=P2^6;
sbit BUZZER=P3^7;  
sbit TR=P1^0;
sbit ECHO=P1^1;
//参数调整按键接入芯片管脚端
sbit L_plus=P1^2;  
sbit L_minus=P1^3;  
sbit replacement=P1^4;  
sbit H_plus=P1^5;  
sbit H_minus=P1^6;  

int flag=0,i;
int time,distance;
float distance1;
int High=120,Low=50;//测量范围
int bai,shi,ge,xiao;//数码管显示
unsigned long S=0;

LCD控制函数部分

此部分包含LCDwritecom函数LCDwritedata函数LCDwritedata函数三个函数,以实现对LCD1602的写入以及初始化的功能。

void LCDwritecom(char a)   //LCD1602的写入命令
{
  LCD1602_E=0;     //使能清零
  LCD1602_RS=0;    //选择发送命令
  LCD1602_RW=0;    //选择写入
  LCD1602_shuru=a;     //放入命令
  delay(1);     //等待数据稳定
  LCD1602_E=1;     //写入时序
  delay(5);   //保持时间
  LCD1602_E=0;
}
void LCDwritedata(char b)   //LCD1602写入数据
{
  LCD1602_E=0; //使能清零
  LCD1602_RS=1; //选择输入数据
  LCD1602_RW=0; //选择写入
  LCD1602_shuru=b; //写入数据
  delay(1);
  LCD1602_E=1;   //写入时序
  delay(5);   //保持时间
  LCD1602_E=0;
}
    
void LCDwritedata()        //LCD初始化程序
{
  LCDwritecom(0x38);  //开显示
  LCDwritecom(0x0c);  //开显示不显示光标
  LCDwritecom(0x06);  //写一个指针加1
  LCDwritecom(0x01);  //清屏
  LCDwritecom(0x80);  //设置数据指针起点
}

LCD1602显示函数部分

LCD1602类似于多位数码管的位选择显示,第Y+1行的第X+1个显示位置显示Data的具体内容

void display(char X,char Y,char Data)   //LCD1602的便捷显示程序
{
  Y&=0x1;  //限制X不能大于15,Y不能大于1(LCD1602一共有两行,每行16个显示位置)
  X&=0xF; 
  if(Y) 
   X|=0x40; //当要显示第二行时地址码+0x40;
   X|=0x80; // 算出指令码
  LCDwritecom(X); //这里不检测信号,发送地址码
  LCDwritedata(Data);
}

超声波控制模块程序部分

控制超声波模块发射超声波

void  startSRF04()            //超声波传感器SRF04的启动模块
{
   TR=0;                      //起始应该是低电平
   TR=1;                      //启动一次模块
   for(i=0;i<=20;i++)         //停止10us左右
        _nop_();
   TR=0;
}

上限值和下限值的参数修改函数

void modification()   
{
 if (replacement==0)
	 {
    High=120,Low=50;
   }
}

LCD显示距离函数

LCD显示,范围为0—170,为了不显示不必要的0,需要对每种情况进行判断

 void display_parameter() 
 {
 //下限处理
 if(Low>=100&&Low<=170)
 {
  display(8,1,(char)(Low/100+'0')); 
  display(9,1,(char)(Low/10%10+'0')); 
  display(10,1,(char)(Low%10+'0')); 
 }
 else if(Low>=10&&Low<=170)
     {
     display(8,1,' ');
     display(9,1,(char)(Low/10%10+'0')); 
        display(10,1,(char)(Low%10+'0'));    
    }
 else if(Low<=170)
 {
  display(8,1,' ');
  display(9,1,' ');
  display(10,1,(char)(Low%10+'0'));   
 }
 //上限处理
 if (High>=100 && High<=170)
 {  
  display(12,1,(char)(High/100+'0')); 
  display(13,1,(char)(High/10%10+'0')); 
  display(14,1,(char)(High%10+'0'));    
 }
 else if(High>=10&&High<=170)
     {
         display(12,1,' ');
         display(13,1,(char)(High/10%10+'0'));
         display(14,1,(char)(High%10+'0'));   
     }
 else if(High<=170)
 {
  display(12,1,' ');
  display(13,1,' ');
  display(14,1,(char)(High%10+'0'));   
 }
 
 display(11,1,'-');
}

检测距离计算并显示函数

void Ranging_algorithm()   
{
  startSRF04();
  while(!ECHO);  //当RX为0时,等待
  TR0=1;       //开启计数
  while(ECHO);   //当RX为1时,计数并等待
  TR0=0;    //关闭计数
  time=TH0*256+TL0;
  TH0=0;
  TL0=0;
  distance =(time*1.705)/100;  //算出来是cm
	distance1 =(time*1.705)/100;
  distance1=distance1+0.05;     //四舍五入

}

距离显示函数

void distance_display()
{	
	xiao=((int)(distance1*10))%10; //distance强制类型转换后出现了bad operand type
  bai=distance/100;
  shi=distance/10%10;
  ge=distance%10;
	//误差修正
	if(distance>95&&distance<160) xiao=xiao-5;
		
  if(distance>=100&&distance<=170)  //距离显示(不显示不必要的零)
  {
    display(7,0,(char)(bai+'0')); 
    display(8,0,(char)(shi+'0'));
    display(9,0,(char)(ge+'0'));   
    display(10,0,'.'); 
    display(11,0,(char)(xiao+'0'));  
  }
  else  if(distance>=10&&distance<=170)
   {
      display(7,0,' ');
      display(8,0,(char)(shi+'0')); 
      display(9,0,(char)(ge+'0'));
      display(11,0,(char)(xiao+'0'));  					
   }
  else if(distance<=170)
  {
   display(7,0,' ');
   display(8,0,' ');
   display(9,0,(char)(ge+'0'));
   display(11,0,(char)(xiao+'0')); 		
  }
  if (distance<=170)
  {
   display(5,0,' ');
	 display(6,0,' ');
   display(10,0,'.');  
   display(13,0,'c');
   display(14,0,'m');
   display(15,0,' ');
  }
  //距离判断
  if(distance<=Low)  
  { 
   display(0,1,'w');  //警告并闪烁
   display(1,1,'a');
   display(2,1,'r');
   display(3,1,'n');
   display(4,1,'i');
   display(5,1,'n');
   display(6,1,'g');
   display(7,1,' ');
   display(8,1,' ');
   display(0,1,' ');  
   display(1,1,' ');
   display(2,1,' ');
   display(3,1,' ');
   display(4,1,' ');
   display(5,1,' ');
   display(6,1,' ');
   display(7,1,' ');
   display(8,1,' ');
   GREEN= 1;
   YELLOW=1;
   RED=0;     //红灯亮  
   BUZZER=0;       //蜂鸣器持续响
  }
  else if(distance>Low && distance<=High)
       {
         YELLOW=0;      //黄灯亮
         GREEN=1;
         RED=1;
         BUZZER=1;
         delay(30);
         BUZZER=0;     //蜂鸣器 嘀~嘀~嘀
         delay(60);
         BUZZER=1; 
         delay(30);

       }     
  else if(distance>High && distance<=170)
       {
         GREEN=0;  //绿灯亮
         YELLOW=1;
         RED=1;
         BUZZER=1;  //蜂鸣器不响
       }
  else if((distance>170)||flag==1)  //超出显示范围或者定时器时间溢出
       {  
         flag=0;
         display(5,0,'o'); 
         display(6,0,'u'); 
         display(7,0,'t'); 
         display(8,0,' '); 
         display(9,0,'o'); 
         display(10,0,'f'); 
         display(11,0,' '); 
         display(12,0,'r'); 
         display(13,0,'a'); 
         display(14,0,'n'); 
         display(15,0,'g'); 
				 GREEN=1;
       }
}

外部中断函数

经过仿真发现当不使用外部中断时,加减是在是太慢了,内部中断又被用去了一个,不够四个中断源,只能从硬件电路上进行扩展

void zhongduan1() interrupt 1    //T0中断用来检测计数器溢出,表示超过测距范围,使用掉了内部定时器1
{
    flag=1;        //中断溢出标志
}
void Init1()   //中断初始化
{
	//内部定时器0
  TMOD=0x01;     //采用16位计数器模式
  TH0=0;         //高位
  TL0=0;         //低位
  ET0=1;         //中断允许
	//外部中断0
	IT0=0;         //外部中断低电平触发
	EX0=1;         //外部中断有效,分开关开
  EA=1;     
}
void Int0()	interrupt 0
{
   if(L_plus==0)
	{
		while(L_plus==0);
		if(Low<High){
	    Low++;
	 }
	}
	if(L_minus==0)
	{
		while(L_minus==0);
		if(Low>0) Low--;
	}
	if(H_plus==0)
	{
		while(H_plus==0);
		if(High<170) High++;
	}
	if(H_minus==0)
	{
		while(H_minus==0);
		if(High>Low)
			{
       High--;
	 }
	}
}

主函数

void main()
{
 BUZZER=1;  //初始设置蜂鸣器不响
 Init1();
 LcdInit();
 display(0,0,'D'); 
 display(1,0,'I'); 
 display(2,0,'S'); 
 display(3,0,'T'); 
 display(4,0,':');
 display(0,1,'P');
 display(1,1,'a');
 display(2,1,'r');
 display(3,1,'a');
 display(4,1,'m');
 display(5,1,':');
 
 while(1)
 {
  modification();
  display_parameter();
  Ranging_algorithm();
  distance_display();
 }
}

延时函数

为了增强函数的可复用性,对延时函数单独进行封装,下面分别是Delay.hDelay.c

#ifndef __DELAY_H__
#define __DELAY_H__
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void delay(unsigned int xms);  //延时函数

#endif

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
  while(xms--){
	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
	
	}
}


超声波测距原理解释

  超声波模块采用现成的HC-SRF04超声波模块,该模块可提供2cm-400cm 的非接触式距离感测功能,测距精度可达高到3mm。模块包括超声波发射器、接收器与控制电路。基本工作原理:采用IO口TRIG 触发测距,给至少10us的高电平信号;模块自动发送8个 40khz 的方波,自动检测是否有信号返回;有信号返回,通过 IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(3.40cm/us))/2。在第二部分的原理图中,VCC供5V电源,GND 为地线,TRIG 触发控制信号输入,ECHO 回响信号输出等四支线。

  超声波探测模块HC-SR04的使用方法如下:IO口触发,给Trig口至少10us的高电平,启动测量;模块自动发送8个40Khz的方波,自动检测是否有信号返回;有信号返回,通过IO口Echo输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间,测试距离=(高电平时间*340)/ 2,单位为m。程序中测试功能主要由两个函数完成。

  实现中采用定时器0进行定时测量,8分频,TCNTT0预设值0XCE,当timer_0溢出中断发生2500次时为125ms,计算公式为(单位:ms):T =(定时器0溢出次数 * (0XFF - 0XCE))/ 1000 ,其中定时器0初值计算依据分频不同而有差异。

最终效果说明

  首先LCD1602初始化和实现便捷显示,传感器启动并开始测距,输出信号由单片机接收并处理转换为测量距离数值,然后先查询上下限值修改按键是否按下,如果被按下,则相应修改上下限值,反之则保持上下限值,再是测量距离数值与上下限值以及测量范围的比较,如果在测量范围内,大于上限值,则控制绿灯亮,黄红两灯不亮,LCD1602显示当前测量距离和上下限值以及normal(正常提示),开关三极管断开,蜂鸣器不工作,无声音;
  大于下限值小于上限值,则控制黄灯亮,绿红两灯不亮,LCD1602显示当前测量距离和上下限值以及cautions(小心警示),开关三极管间断打开,蜂鸣器间断工作,从而实现发出滴 滴 滴~的声音;小于下限值,则控制红灯亮,黄绿两灯不亮,LCD1602显示当前测量距离和上下限值,同时warning显示又消显实现闪烁警报,开关三极管一直打开,蜂鸣器持续工作,一直发声警报。反之若超出测量范围,LCD1602显示距离位置显示out of rang(超出范围),提示显示位置显示error(错误)。文章来源地址https://www.toymoban.com/news/detail-753841.html

到了这里,关于超声波测距仿真的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Arduino单片机超声波测距仪设计

    文章目录 摘  要 1.课程设计任务 1.1课程设计题目 1.2设计的要求 2.设计总体方案 2.1初步设计方案 2.2各个单元电路的设计要求 2.3主要性能指标 2.4总体方案 3.单元模块设计 3.1显示模块 3.2超声波测距模块 3.3蜂鸣器模块 3.4电机模块 3.5 LED二极管模块 4.软件流程图 5.设计代码 5.1核

    2024年02月11日
    浏览(49)
  • 基于51单片机的超声波测距及温度显示

    (仿真+程序+PCB+原理图+设计报告) 功能介绍 具体功能: 1.超声波测距传感器HC-SR04、温度传感器DS18B20将检测的数据传给51单片机; 2.LCD1602实时显示测得的距离和温度; 3.按键可以设置距离的上下限; 4.距离超过设定范围,蜂鸣器+LED产生声光报警; ​演示视频: 基于5

    2024年04月24日
    浏览(51)
  • 基于c51单片机超声波测距仪

            整个系统由AT89C51,超声波电路,显示电路和报警电路,按键控制组成,系统复位后,首先对各模块进行初始化,初始化后根据超声波模块返回的回波进行数据计算,把数据显示到LMO16L液晶显示器上,并与设定的报警值相比较,小于报警值则蜂鸣器响起、指示灯亮

    2024年02月04日
    浏览(55)
  • 【51单片机练习1——超声波测距+LCD12864显示】

    PS:这是人生中的第一篇博客,记录了我人生中的第一次实习工作。与其说是博客文章,这些更像是一个小白的流水账日记,可能会有很多错误和有待优化的地方,希望各位大佬可以多多提出。如有问题可以私信联系。 行文过程中,欲说尽心中无限事,感慨万千。不过各位“

    2024年02月04日
    浏览(61)
  • 超声波测距模块HC-SR04详解(基于51单片机)

    本篇文章是个人整理的包含超声波测距模块HC-SR04的基本介绍与基本工作原理以及分别通过LCD1602、数码管和串口显示距离的实例讲解与代码的笔记,部分内容来自《HC-SR04超声波测距模块说明书》,代码使用模块化编辑,部分模块来自江科大自化协的51单片机教学视频。 希望大

    2023年04月16日
    浏览(52)
  • 基于单片机的超声波探伤仪

    摘要 超声波探伤仪是目前工业制造和现代化检测的重要途径之一,广泛的应用在质量检测和产品检测中,通过使用其产品能够有效地降低产品次品的风险。尽管随着电子技术的发展, 国内出现了一些数字化的超声检测仪器,但其数据处理及扩展能力有限,缺乏足够的灵活性

    2024年04月11日
    浏览(67)
  • 基于单片机的超声波探伤仪设计

    摘要 超声波探伤仪是目前工业制造和现代化检测的重要途径之一,广泛的应用在质量检测和产品检测中,通过使用其产品能够有效地降低产品次品的风险。尽管随着电子技术的发展, 国内出现了一些数字化的超声检测仪器,但其数据处理及扩展能力有限,缺乏足够的灵活性

    2024年02月08日
    浏览(51)
  • 51单片机使用HC-S104超声波模块

      HC-S104超声波模块是一种测量距离的传感器,可以用于51单片机的测距应用。下面是使用HC-S104超声波模块的步骤: 1.将HC-S104超声波模块的VCC引脚连接到51单片机的3.3V或5V电源,GND引脚连接到51单片机的GND,TRIG引脚连接到51单片机的一个可编程输出口,ECHO引脚连接到51单片机的

    2024年02月12日
    浏览(61)
  • 超声波测距仿真

    萌新第一次写博客,有格式不正确的地方还请大家见谅。 用HCSR04超声波传感器测量距离,测量范围0~170cm,精确到小数点后一位。 用LCD1602或者数码管显示测量到的距离。 当距离大于120cm时,绿色LED灯亮; (1)当距离在50-120cm之间,蜂鸣器间断发声“滴 滴 滴 ”提示,黄色LED灯亮

    2024年02月05日
    浏览(42)
  • 基于51单片机驱动HC-SR04超声波模块(LCD1602显示)

    点击图片购买 HC- SR04+是一款宽电压工作的超声波测距模块。模块外形尺寸及软件与老版本 HC- SR04完全兼容;可以与老版本HC SR04无缝切换。低至3V的低工作电压, 使其与3.3V供电的MCU可以直接连接。 特点 探测角度: 15° 采用工业级MCU,工作温度:-20C~80C 探测距离:5V:2cm-- 450cm;3.3V: 2c

    2024年02月02日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包