超声波测距仿真
萌新第一次写博客,有格式不正确的地方还请大家见谅。
设计总体要求
- 用HCSR04超声波传感器测量距离,测量范围0~170cm,精确到小数点后一位。
- 用LCD1602或者数码管显示测量到的距离。
- 当距离大于120cm时,绿色LED灯亮;
(1)当距离在50-120cm之间,蜂鸣器间断发声“滴 滴 滴 ”提示,黄色LED灯亮。
(2)当距离低于50cm时,蜂鸣器持续报警,红色LED灯亮,显示报警信号(如warning)并闪烁。 - 临界值默认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.h
和Delay.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初值计算依据分频不同而有差异。
文章来源:https://www.toymoban.com/news/detail-753841.html
最终效果说明
首先LCD1602初始化和实现便捷显示,传感器启动并开始测距,输出信号由单片机接收并处理转换为测量距离数值,然后先查询上下限值修改按键是否按下,如果被按下,则相应修改上下限值,反之则保持上下限值,再是测量距离数值与上下限值以及测量范围的比较,如果在测量范围内,大于上限值,则控制绿灯亮,黄红两灯不亮,LCD1602显示当前测量距离和上下限值以及normal(正常提示),开关三极管断开,蜂鸣器不工作,无声音;
大于下限值小于上限值,则控制黄灯亮,绿红两灯不亮,LCD1602显示当前测量距离和上下限值以及cautions(小心警示),开关三极管间断打开,蜂鸣器间断工作,从而实现发出滴 滴 滴~的声音;小于下限值,则控制红灯亮,黄绿两灯不亮,LCD1602显示当前测量距离和上下限值,同时warning显示又消显实现闪烁警报,开关三极管一直打开,蜂鸣器持续工作,一直发声警报。反之若超出测量范围,LCD1602显示距离位置显示out of rang(超出范围),提示显示位置显示error(错误)。文章来源地址https://www.toymoban.com/news/detail-753841.html
到了这里,关于超声波测距仿真的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!