超声波测距仪设计实验报告
一、实验目的
1)了解超声波发生器原理以及超声波测距原理;
2)根据超声波测距原理,设计超声波测距仪硬件电路;
3)熟悉PCB板的设计与制作;
4)熟悉基于单片机或嵌入式系统的开发编程;
5)熟悉电路的综合调试。
二、实验内容
1)认真研究有关理论知识并大量查阅相关资料,确定系统的总体设计方案,设计出系统框图;
2)决定各项参数所需要的硬件设施,完成电路的理论分析和PCB板设计与制作;
3)设计制作或购买单元模块并对各单元模块进行调试与验证;
4)将单元电路及相关零散电子元件整合到PCB板上并进行整体调试;
5)完成原理图设计和硬件制作;
6)编写程序和整体调试电路;
7)完成实验报告,将设计制作成果以及报告交给老师验收。
三、实验原理
超声波是一种在弹性介质中的机械振荡,其指向性强,能量消耗缓慢,在空气中传播的距离较远,因而超声波经常用于距离的测量。超声波测距仪就是以超声波作为测量工具的一种仪器。本实验的超声波测距仪主要由超声波收发装置、单片机、测温装置、语音报警装置、LCD显示等几部分组成。系统测量距离的原理是利用单片机控制超声波收发模块发出40khz的方波串,自动检测接收端能否收到超声波在遇到障碍物后反射回来的回波,反射后的超声波经超声波换能器作为系统的输入,锁相环对此信号锁定产生锁定信号启动单片机中断程序,得到时间T。超声波在空气中的传播速度与温度有关(C=331.5+0.607*T/0C (m/s)),因而在检测是否能收到回波的同时还要通过温度传感器检测环境温度。单片机利用超声波收发装置返回的超声波传输时间和温度传感器返回的温度系数利用给定的算法(S=(C*T)/2)在单片机程序的控制下得出超声波传输的距离同时在LCD上显示距离和温度,当检测到的距离低于给定范围时单片机就会控制超限报警装置报警。
(一)压电式超声波发生器原理
压电式超声波发生器实际上是利用压电晶体的谐振来工作的。它有两个压电晶片和一个共振板。当它的两极外加脉冲信号,其频率等于压电晶片的固有振荡频率时,压电晶片将会发生共振,并带动共振板振动,利用逆压电效应产生超声波。反之,如果两电极间未外加电压,当共振板接收到超声波时,将压迫压电晶片作振动,利用正压电效应将机械能转换为电信号,这时它就成为超声波接收器了。
(二)超声波测距原理
由于超声波指向性强,能量消耗缓慢,在空气中传播的距离较远,因而超声波经常用于距离的测量。利用超声波检测往往比较迅速、方便、计算简单、易于做到实时控制,并且在测量精度方面能达到工业实用的要求。超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。超声波在空气中的传播速度为C,根据计时器记录的时间T,就可以计算出发射点距障碍物的距离S,即S=(C*T)/2.从超声波特性可知:超声波在空气中的传播速度与温度相关C=331.5+0.607t/0C (m/s),如果温度变化不大,则可认为声速是基本不变的,典型的环境温度与超声波的传播速度的关系为:
(三)AT89C51单片机
AT89C51是一种带4K字节flash存储器的低电压、高性能CMOS 8位微处理器。它与工业标准MCS-51的指令和引脚兼容,因而是一种功能强大的微控制器,它对很多嵌入式控制应用提供了一个高度灵活有效的解决方案。
AT89C51有以下特点:4K字节flash闪速存储器,128字节内部RAM,32个I/O口线,两个16定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89C51可降至0HZ的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其他所有不见工作直到下一个硬件复位。具有4.25V至5.5V的电压工作范12MHz/24MHz工作频率,同时还具有加密阵列的二级程序存储器加锁、掉电和时钟电路等。AT89C51有2个16位计时/计数器寄存器Timer0/ Timer1。作为一个定时器,每个机器周期寄存器增加1,这样寄存器即可计数机器周期。因为一个机器周期有12个振荡器周期,所以计数率是振荡器频率的1/12。作为一个计数器,该寄存器在相应的外部输入脚P3.4/T0和P3.5/T1上出现从1至0的变化时增1。由于需要二个机器周期来辨认一次1到0的变化,所以最大的计数率是振荡器频率的1/24,可以对外部的输入端P3.2/INT0和P3.3/INT1编程,便于测量脉冲宽度。
(四)DS1820测温原理
DS1820测温原理如图2所示。图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1。高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入。计数器1和温度寄存器被预置在-55℃所对应的一个基数值。计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1 ,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。图2中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。
四、基于AT89C51单片机超声波测距的方案设计
(一)系统结构
主要由超声波收发模块、单片机、测温装置、报警电路、LED显示等 5部分组成;
系统框图如下:
(二)硬件设计
1、超声波收发模块
在设计过程中采用HC-SR04,其特性如下:
因此,直接将trig(触发端)和echo(接收端)接在单片机上即可。此时,p2端口只是I/O口的作用,由于内部有上拉电阻,所以可以直接相连。
超声波时序图
2、温度补偿电路
温度补偿电路采用DS18B20芯片,DS1820具有以下特性:
独特的单线接口方式,DS1820在与微处理器连接时仅需要一条口线即可实现微处理器与
DS1820的双向通讯;
DS1820支持多点组网功能,多个DS1820可以并联在唯一的三线上,实现多点测温;
DS1820在使用中不需要任何外围元件;
温范围-55℃~+125℃,固有测温分辨率0.5℃;
测量结果以9位数字量方式串行传送。
DS1820内部结构框图如图1所示
本系统中DS1820由单片机P2.7控制,由LED显示电路动态显示温度。电路图如下:
3、蜂鸣器报警电路
报警电路由小功率三极管Q1和蜂鸣器组成。此电路由单片机产生的脉冲信号控制晶体管驱动蜂鸣器缓急报警,进而判断距离的远近。
4、LCD12864液晶显示模块
系统的显示模块选用12864液晶显示模块,能够显示128×64像素图形或4行16×16中文字符。 液晶显示模块的设计:
本设计液晶显示模块的设计如上图所示,该电路实现的功能是:通过AT89C51的P1.0~P1.7八个口输出控制信号,控制液晶的8位双向数据线,通过单片机的P2.0、P2.1向液晶模块发送命令,控制液晶执行各种命令,其中P2.2控制液晶的使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。当P2.0为低电平时可以写入指令,当P0.2为高电平时可以写入数据。
5、电源设计
(三)软件设计
超声波测距的软件设计主要由主程序,超声波发生子程序,超声波接收子程序,显示子程序,温度检测与补偿子程序,语音报警子程序五部分组成。主程序首先对系统环境初始化,置位总中断允许位EA并给显示端口清零,然后调用超声波发射子程序送出一个超声波脉冲,为了避免超声波从发射器直接传送到接收器引起的直射波触发,需要延时0.1ms后才打开外中断0接收返回信号。一旦检测到返回信号,立即进入中断程序,结束计时,并保存时间,进行计算、编码,与发送编码比较,若不符则重发;若小于报警距离则发出警报。若没有检测到返回信号,则判断接收限时是否已到,若接收限时未到,则继续巡回检测接收,否则返回发射状态重发。
程序流程图如下:
实验代码见附件。
五、实验问题及解决
1、在应用老师提供的汇编程序的时候,我们通过查找资料知道这种在C中调用汇编函数是需要将汇编函数设置为外部函数并添加到group中的,但是在用Keil编译的时候还是出现问题,始终无法解决,所以我们决定自己用C编写超声波发射程序、严格延时程序,在到处查找资料后成功编写;
2、老师给的显示函数对应的是数码管的显示,而且是用汇编编写,而我们实际应用的是LCD12864的液晶显示,所以我们用C重新编写显示函数,最开始显示出来的是一片乱码,我们就在网上查找更多的资料然后整合编写出能显示的程序,但第一次能显示出的是错误的信息,距离的显示和实际相当不吻合,我们发现是在设置距离显示的时候我们设置的位置太靠后导致好多数据无法显示,所以我们调整程序将距离显示的位置提到前面并成功显示;
3、在验证制作出的PCB与实际器材是否匹配时,我们发现有部分元件的封装明显不符,有可能会导致元件无法安装的问题,我们决定实际测量元器件的大小,然后修改PCB图中元件的封装,使之匹配。对于有部分元件在altium designer中没有合适封装的情况,我们通过自己画封装、下载合适封装库等方法成功得到合适的封装。
4、我们发现在altium designer自带的库中没有LCD12864,既没有原理图也没封装,对于我们第一次使用该软件而言,画LCD12864封装比较难,易出错。为了避免出错,我们自己画了LCD12864的原理图,并且采用排针代替LCD12864的方法。
5、在将元件焊接好后在上电后液晶显示屏没有显示,在检查后发现是数据口定义出错,将P1口定义成P0口了,将P0改成P1解决问题,实现显示。
6、在显示距离后调用蜂鸣器的驱动程序来实现超限报警时发现刚打开就在报警然后报警的声音差距不是很大,在很远的地方都在叫,检查主函数知道是蜂鸣器驱动函数的问题,检查后发现是if多条件判断语句运用出错,将该语句改成if-else语句并正确书写if里面的判断条件成功解决刚开始在很远的地方就报警的问题,然后将延时差距加大实现明显的不同距离段的报警。
六、实验总结与提高
该综合实验是制作一个带温度补偿、超限报警以及数字显示功能的超声波测距仪,以单片机作为核心控制器,编写程序控制周围的超声波收发模块、温度补偿模块、蜂鸣器报警装置以及LCD显示部分。在该实验中,最开始我们根据老师提供的资料商量确定了系统的框架以及各模块需要什么器件,然后我们就上网购买相应元件,在等待元件来的过程中,我们小组有明确的分工,软硬件部分分成不同的人来负责,由于我们都没有学习制作PCB板的经验,所以决定一人负责学习绘制PCB板,一人负责编写整合软件,在成功学习绘制PCB以后商量统一PCB板上各引脚的定义就可以将软
件和硬件统一起来,从而绘制我们实验需要的PCB板。因为制作PCB板的实验条件有限,对于没有学习过PCB板的制作的我们来说太复杂考虑到时间的因素和成功率的高低,我们决定将绘制的PCB图交由别人制作。在等待PCB板来的过程中,我们利用单片机学习板调试了程序,经过我们的努力成功调试完成并基本完成了实验报告。在PCB板到后,我们将各模块焊接整合到一起并将程序烧到单片机中重新调试,在解决一个又一个的问题后最终完成指定要求的超声波测距仪的制作并交由老师验收。
该实验是一个综合实验,将以前学到的一些知识运用起来,并学习整合一些新的知识,充分锻炼了同学们的实际应用和动手能力,也考验了同学们处理资料数据、查找资料、学习新知识的能力。通过该实验,我们都意识到实际的应用和制作相对于课本上的理论分析来说还是有很大不同的,也意识到我们在实际应用、解决工程问题上的能力还很是欠缺,更加认识到超声波在实际生活中有着很广泛的应用以及发展潜力。通过该实验,我们对自身以及所学专业有了更加深刻的了解,相信这对我们未来的发展有很大帮助。
成员分工:
xxx:编写程序及调试,写实验报告,焊接元件
xxx:绘制PCB板及电路原理图,焊接元件
xxx:购买元器件,焊接元件
附件:
1、电路原理图
2、PCB图
3、程序代码
#include
#include
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define LCD_data P1 //数据口
data uint i,t,l,c,a;
uchar time; //设置全局变量,专用于严格延时
double T_dist; //定时时间
double M_DIS; //实际距离
uint T_H,T_L; //存传输时间
sbit TEM=P2^7;//DS18B20温度输出口
sbit TRIG=P2^0;//超声波发射端
sbit ECHO=P2^1;//超声波接收端
sbit BEEP=P3^6;//蜂鸣器报警
sbit RS=P2^6;//LCD12864数据指令控制端
sbit RW=P2^5;//LCD12864读写端
sbit EN=P2^4;//LCD12864使能端
sbit PSB = P2^3;
sbit RST = P2^2; //液晶复位端口
void Ini_Lcd(void);
uchar TN; //实际温度的整数部分
uchar TD; //实际温度的小数部分
uchar Tflag,Ttemp; //负温度标志和临时变量
uchar data temp_data[2]={0x00,0x00}; //读出温度暂放
uchar code str0[]={
uchar code str1[]={
uchar code str2[]={
uchar code str3[]={
uchar code str4[]={
uchar code str5[]={
uchar code str6[]={
uchar code str7[]={
uchar code str8[]={
uchar code num[]={
uchar code cnt[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00}; //自定义字符
uchar dis[16]={' ',' ','D','I','S',':',};//距离显示
uchar tem[16]={' ',' ','T','E','M',':',};//温度显示
//中断重启函数
void Restart_int()
{ TMOD = 0X11;//确定定时器0和1的工作方式,方式1(工作方式寄存器);
TCON = 0X00;//定时器中断清零且不允许计数(控制寄存器)
ET1=1;//允许定时器1中断
TH1=0;//定时初值为0
TL1=0;
}
//延时程序
void delaynus(uint i)
{uchar j;
while(i--)
{
for(j=0;j
}
}
//蜂鸣器驱动程序
void beep()
{
uchar i;
if(M_DIS>20.0&&M_DIS
{
for(i=0;i
{
BEEP=1;
delaynus(15);
BEEP=0;
delaynus(15);
}
}
else if(M_DIS>10.0&&M_DIS
{
for(i=0;i
{
BEEP=1;
delaynus(7);
BEEP=0;
delaynus(7);
}
else if(M_DIS
{
for(i=0;i
{
BEEP=1;
delaynus(1);
BEEP=0;
delaynus(1);
}
}
else
BEEP=0;
}
//液晶Busy状态判断函数,数据线的最高位DB7为1则busy
bit Read_busy()
{
bit result;
RS=0;
RW=1;
EN=1;
_nop_();
_nop_();
_nop_();
EN=0;
return result; //返回忙碌标志,1:忙碌
}
//液晶写指令函数
void WR_Cmd(uchar Cmd)
{
while(Read_busy());
RS = 0;
RW = 0;
EN= 1;
delaynus(5);
LCD_data=Cmd;
delaynus(5);
EN= 0;
}
//液晶写数据函数
void WR_Data(uchar Data)
{
while(Read_busy());
RS=1;
EN=1;
delaynus(5);
LCD_data=Data;
delaynus(5);
EN= 0;
}
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if (X==1)
{X=0x80;}
else if (X==2)
{X=0x90;}
else if (X==3)
{X=0x88;}
else if (X==4)
{X=0x98;}
pos=X+Y ;
WR_Cmd(pos); //显示地址
}
//LCD初始化子程序
void Ini_Lcd(void)
PSB=1; //并口方式
EN=0;
RST=0;
delaynus(5);
RST=1;
WR_Cmd(0x34); //扩充指令操作
delaynus(5);
WR_Cmd(0x30); //基本指令操作
delaynus(5);
WR_Cmd(0x01); //清除LCD的显示内容
delaynus(5);
WR_Cmd(0x0c); //显示开,关光标
delaynus(5);
WR_Cmd(0x06);
delaynus(5);
}
void delay1(l) //11us
{
for(;l>0;l--);
}
//初始化DS18B20
ow_reset(void) //DS18B20复位函数
char presence=1;
while(presence)
{
TEM=1;_nop_();_nop_();
TEM=0;
delay1(50); //550us
TEM=1;
delay1(3);
presence=TEM;//如初始化成功,则返回一个低电平0,跳出while循环继续执行后面的延时程序 }
delay1(45);
TEM=1;
}
uchar read_byte(void) //DS18B20读命令函数
{
uchar i;
uchar value=0;
for(i=8;i>0;i--)
{
TEM=1;_nop_();_nop_();
TEM=0;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
TEM=1;_nop_();_nop_();_nop_();_nop_();
value>>=1;
if(TEM) value|=0x80;
delay1(6);
}
return (value);
}
void write_byte(uchar val) //DS18B20写命令函数(温度传感器)
{
uchar i;
for(i=8;i>0;i--)
{
TEM=1;_nop_();_nop_(); //温度输入口TEM
TEM=0;_nop_();_nop_();_nop_();_nop_();_nop_(); //5us
TEM=val&0x01; //最低位移出
delay1(6);
TEM=1;
_nop_();_nop_();
val=val/2; //右移1位
}
delay1(1);
}
//做好读取温度的准备
void TEM_Ready()
ow_reset(); //复位
write_byte(0xcc);//CCH,忽略64位ROM地址,直接向18B20发温度转换命令
write_byte(0x44); //启动温度转换
delay1(200); //转换一次需要延时一定时间
ow_reset(); //复位
write_byte(0xcc);//CCH,忽略64位ROM地址,直接向18B20发温度转换命令
write_byte(0xbe);//BEH,读暂存器,读内部RAM中9字节的温度数据
}
//读取温度值并处理函数
void rw_temp()
{
Tflag=0;//负温度标志
TEM_Ready();//读温度准备
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
if((temp_data[1]&0XF8)!=0x00)//判断温度符号
{
Tflag=1;
temp_data[0]=~temp_data[0];
temp_data[1]=~temp_data[1]; //为负则处理
Ttemp=temp_data[0]+1;
if(Ttemp>255) temp_data[1]++;
TN=temp_data[1]*16+temp_data[0]/16; // 计算温度整数部分
TD=(temp_data[0]%16)*10/16;//计算温度小数部分
}
//温度值存储函数
void tem_sto()
{
uchar i,j,k;
if(Tflag==0)//温度符号存储
tem[6]=' ';
else
tem[6]='-';
i=TN/100;//百位
j=(TN%100)/10;//十位
k=TN%10;//个位
tem[7]=num[i];
if(i==0){tem[7]=' ';}
tem[8]=num[j];
tem[9]=num[k];
tem[10]='.';
tem[11]=num[TD];
}
//温度显示值处理函数
void tem_dis()
{
uchar i;
WR_Cmd(0x01);
delay1(5);
//Set_line(0x00);
//Set_column(0x00);
lcd_pos(2,1);
delay1(5);
i=0;
while(tem[i]!='\0')//显示温度值
{
WR_Data(tem[i]);
i++;
}
WR_Data(' ');
WR_Data(0x00);
delay1(5);
}
//温度显示函数
void tem_msu()
{
rw_temp();
tem_sto();
tem_dis();
}
//距离计算函数 输出M_DIS,单位:cm
void distance()
{
double Speed;
double i;
i=T_dist/2.0; //超声传播时间
Speed=331.4+0.607*TN; //计算超声传播速度
M_DIS=i*Speed; //距离
M_DIS=M_DIS/10000.0;
}
//测距函数
void Measure()
{
uint i,j,k,l;
double m;
uchar tempa;
uchar IsOverFlow=0;
unsigned long Time;
TRIG = 0;//发送一个脉冲
for(tempa = 0; tempa
{
TRIG = 1;
}
TRIG = 0;
while(1)
{
if(ECHO == 1)
{//Start Timer;
TR1=1;//start timer
break;
}
if(TF1 == 1)
{
IsOverFlow = 1;
break;//overflow;
}
}
while(1)
{
if(ECHO == 0)
{//Stop Timer;
TR1=0;
break;
}
if(TF1 == 1)
{
IsOverFlow = 1;
break;//overflow;
}
}
Time = TH1;
Time
Time = Time+TL1;
if((Time>60000)||(Time
{
for(i=10;i
dis[i-4]=str4[i]; //‘ERROR’
dis[11]=' ';
}
else
{
T_dist=Time;
distance(); //距离计算函数
m=M_DIS*10.0; //计算距离
i=(uint)M_DIS/100;//百位
j=((uint)M_DIS%100)/10;//十位
k=(uint)M_DIS%10;//个位
l=(uint)m%10; //小数点后第一位
dis[6]=num[i];
dis[7]=num[j];
dis[8]=num[k];
dis[9]='.';
dis[10]=num[l];
dis[11]=' ';
dis[12]='C';
dis[13]='M';
Ttemp=i*100+j*10+k;//记录延时时长
}
}
//距离显示函数
void DIS_Dis()
{
int i;
// Set_line(0x28);
// Set_column(0x28);
lcd_pos(3,1);
delaynus(10);
i=0;
while(dis[i]!='\0')//显示距离
{
WR_Data(dis[i]);
i++;
}
delaynus(1);
}
//开机初始化函数
void Init()
{
uchar i;
Ini_Lcd();
WR_Cmd(0x01);
delaynus(10);
//Set_line(0x05);
// Set_column(0x05);
lcd_pos(1,1);
delaynus(10);
i=0;
while(str0[i]!='\0')// Init...
{
WR_Data(str0[i]);
i++;
}
delaynus(5);
WR_Cmd(0x40); //设定CGRAM地址
delaynus(5);
i=0;
for(i=0;i
WR_Data(cnt[i]); //写入自定义图形
EA=1;//开总中断
IT0=1; //选择边缘方式触发
TMOD=0X10;//T1定时工作方式1
ET1=1;//允许定时器1中断
TR1=0;//不启动定时器1
TH1=0;//定时初值为0
TL1=0;
TRIG=0;
Tflag=0;
Ttemp=0;
time=0;
TN=0;//实际温度的整数部分
TD=0;// 实际温度的小数部分
// Error=0;//测距超出范围或测距盲区为1
T_dist=0;//定时时间
M_DIS=0;//实际距离
T_H=0;
T_L=0;
delaynus(10000);
}
//开机显示信息函数
void start()
{
uchar i;
i=0;
WR_Cmd(0x01);//清屏
delaynus(5);
lcd_pos(1,1);
delaynus(5);
i=0;
while(str1[i]!='\0')//四川大学
{
WR_Data(str1[i]);
i++;
}
i++;
lcd_pos(3,1);
delaynus(5);
i=0;
while(str8[i]!='\0')//综合实验
{
WR_Data(str8[i]);
i++;
}
i++;
delaynus(10);
delaynus(5000);
WR_Cmd(0x01);
delaynus(20);
lcd_pos(1,2); //施富强
delaynus(50);
i=0;
while(str2[i]!='\0')
{
WR_Data(str2[i]);
i++;
}
i++;
lcd_pos(2,1);
delaynus(50);
i=0;
while(str5[i]!='\0')//1142051080
{
WR_Data(str5[i]);
i++;
}
i++;
lcd_pos(3,2);
delaynus(50);
i=0;
while(str3[i]!='\0')//刘圣忠
{
WR_Data(str3[i]);
i++;
}
i++;
lcd_pos(4,1);
delaynus(50);
i=0;
while(str6[i]!='\0')//1142051077
{
WR_Data(str6[i]);
i++;
}
delaynus(10000);
WR_Cmd(0x01);
delaynus(50);
lcd_pos(2,2);
delaynus(50);
i=0;
while(str4[i]!='\0')
{
WR_Data(str4[i]);//翁鹏飞
i++;
}
i++;
lcd_pos(3,1);
delaynus(50);
i=0;
while(str7[i]!='\0')//1142051207
{
WR_Data(str7[i]);
i++;
}
delaynus(10000);
}
//主函数
void main(void)
{
Init();//开机初始化函数
start();//开机显示函数
while(1)
{
tem_msu(); //测温函数
delaynus(10); //延时
Restart_int(); //中断重启函数
delaynus(10); //延时函数
Measure(); //测距函数
DIS_Dis(); //距离显示
beep(); //蜂鸣器函数
delaynus(Ttemp); //延时函数
}
}
超声波测距仪设计实验报告
一、实验目的
1)了解超声波发生器原理以及超声波测距原理;
2)根据超声波测距原理,设计超声波测距仪硬件电路;
3)熟悉PCB板的设计与制作;
4)熟悉基于单片机或嵌入式系统的开发编程;
5)熟悉电路的综合调试。
二、实验内容
1)认真研究有关理论知识并大量查阅相关资料,确定系统的总体设计方案,设计出系统框图;
2)决定各项参数所需要的硬件设施,完成电路的理论分析和PCB板设计与制作;
3)设计制作或购买单元模块并对各单元模块进行调试与验证;
4)将单元电路及相关零散电子元件整合到PCB板上并进行整体调试;
5)完成原理图设计和硬件制作;
6)编写程序和整体调试电路;
7)完成实验报告,将设计制作成果以及报告交给老师验收。
三、实验原理
超声波是一种在弹性介质中的机械振荡,其指向性强,能量消耗缓慢,在空气中传播的距离较远,因而超声波经常用于距离的测量。超声波测距仪就是以超声波作为测量工具的一种仪器。本实验的超声波测距仪主要由超声波收发装置、单片机、测温装置、语音报警装置、LCD显示等几部分组成。系统测量距离的原理是利用单片机控制超声波收发模块发出40khz的方波串,自动检测接收端能否收到超声波在遇到障碍物后反射回来的回波,反射后的超声波经超声波换能器作为系统的输入,锁相环对此信号锁定产生锁定信号启动单片机中断程序,得到时间T。超声波在空气中的传播速度与温度有关(C=331.5+0.607*T/0C (m/s)),因而在检测是否能收到回波的同时还要通过温度传感器检测环境温度。单片机利用超声波收发装置返回的超声波传输时间和温度传感器返回的温度系数利用给定的算法(S=(C*T)/2)在单片机程序的控制下得出超声波传输的距离同时在LCD上显示距离和温度,当检测到的距离低于给定范围时单片机就会控制超限报警装置报警。
(一)压电式超声波发生器原理
压电式超声波发生器实际上是利用压电晶体的谐振来工作的。它有两个压电晶片和一个共振板。当它的两极外加脉冲信号,其频率等于压电晶片的固有振荡频率时,压电晶片将会发生共振,并带动共振板振动,利用逆压电效应产生超声波。反之,如果两电极间未外加电压,当共振板接收到超声波时,将压迫压电晶片作振动,利用正压电效应将机械能转换为电信号,这时它就成为超声波接收器了。
(二)超声波测距原理
由于超声波指向性强,能量消耗缓慢,在空气中传播的距离较远,因而超声波经常用于距离的测量。利用超声波检测往往比较迅速、方便、计算简单、易于做到实时控制,并且在测量精度方面能达到工业实用的要求。超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。超声波在空气中的传播速度为C,根据计时器记录的时间T,就可以计算出发射点距障碍物的距离S,即S=(C*T)/2.从超声波特性可知:超声波在空气中的传播速度与温度相关C=331.5+0.607t/0C (m/s),如果温度变化不大,则可认为声速是基本不变的,典型的环境温度与超声波的传播速度的关系为:
(三)AT89C51单片机
AT89C51是一种带4K字节flash存储器的低电压、高性能CMOS 8位微处理器。它与工业标准MCS-51的指令和引脚兼容,因而是一种功能强大的微控制器,它对很多嵌入式控制应用提供了一个高度灵活有效的解决方案。
AT89C51有以下特点:4K字节flash闪速存储器,128字节内部RAM,32个I/O口线,两个16定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89C51可降至0HZ的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其他所有不见工作直到下一个硬件复位。具有4.25V至5.5V的电压工作范12MHz/24MHz工作频率,同时还具有加密阵列的二级程序存储器加锁、掉电和时钟电路等。AT89C51有2个16位计时/计数器寄存器Timer0/ Timer1。作为一个定时器,每个机器周期寄存器增加1,这样寄存器即可计数机器周期。因为一个机器周期有12个振荡器周期,所以计数率是振荡器频率的1/12。作为一个计数器,该寄存器在相应的外部输入脚P3.4/T0和P3.5/T1上出现从1至0的变化时增1。由于需要二个机器周期来辨认一次1到0的变化,所以最大的计数率是振荡器频率的1/24,可以对外部的输入端P3.2/INT0和P3.3/INT1编程,便于测量脉冲宽度。
(四)DS1820测温原理
DS1820测温原理如图2所示。图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1。高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入。计数器1和温度寄存器被预置在-55℃所对应的一个基数值。计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1 ,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。图2中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。
四、基于AT89C51单片机超声波测距的方案设计
(一)系统结构
主要由超声波收发模块、单片机、测温装置、报警电路、LED显示等 5部分组成;
系统框图如下:
(二)硬件设计
1、超声波收发模块
在设计过程中采用HC-SR04,其特性如下:
因此,直接将trig(触发端)和echo(接收端)接在单片机上即可。此时,p2端口只是I/O口的作用,由于内部有上拉电阻,所以可以直接相连。
超声波时序图
2、温度补偿电路
温度补偿电路采用DS18B20芯片,DS1820具有以下特性:
独特的单线接口方式,DS1820在与微处理器连接时仅需要一条口线即可实现微处理器与
DS1820的双向通讯;
DS1820支持多点组网功能,多个DS1820可以并联在唯一的三线上,实现多点测温;
DS1820在使用中不需要任何外围元件;
温范围-55℃~+125℃,固有测温分辨率0.5℃;
测量结果以9位数字量方式串行传送。
DS1820内部结构框图如图1所示
本系统中DS1820由单片机P2.7控制,由LED显示电路动态显示温度。电路图如下:
3、蜂鸣器报警电路
报警电路由小功率三极管Q1和蜂鸣器组成。此电路由单片机产生的脉冲信号控制晶体管驱动蜂鸣器缓急报警,进而判断距离的远近。
4、LCD12864液晶显示模块
系统的显示模块选用12864液晶显示模块,能够显示128×64像素图形或4行16×16中文字符。 液晶显示模块的设计:
本设计液晶显示模块的设计如上图所示,该电路实现的功能是:通过AT89C51的P1.0~P1.7八个口输出控制信号,控制液晶的8位双向数据线,通过单片机的P2.0、P2.1向液晶模块发送命令,控制液晶执行各种命令,其中P2.2控制液晶的使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。当P2.0为低电平时可以写入指令,当P0.2为高电平时可以写入数据。
5、电源设计
(三)软件设计
超声波测距的软件设计主要由主程序,超声波发生子程序,超声波接收子程序,显示子程序,温度检测与补偿子程序,语音报警子程序五部分组成。主程序首先对系统环境初始化,置位总中断允许位EA并给显示端口清零,然后调用超声波发射子程序送出一个超声波脉冲,为了避免超声波从发射器直接传送到接收器引起的直射波触发,需要延时0.1ms后才打开外中断0接收返回信号。一旦检测到返回信号,立即进入中断程序,结束计时,并保存时间,进行计算、编码,与发送编码比较,若不符则重发;若小于报警距离则发出警报。若没有检测到返回信号,则判断接收限时是否已到,若接收限时未到,则继续巡回检测接收,否则返回发射状态重发。
程序流程图如下:
实验代码见附件。
五、实验问题及解决
1、在应用老师提供的汇编程序的时候,我们通过查找资料知道这种在C中调用汇编函数是需要将汇编函数设置为外部函数并添加到group中的,但是在用Keil编译的时候还是出现问题,始终无法解决,所以我们决定自己用C编写超声波发射程序、严格延时程序,在到处查找资料后成功编写;
2、老师给的显示函数对应的是数码管的显示,而且是用汇编编写,而我们实际应用的是LCD12864的液晶显示,所以我们用C重新编写显示函数,最开始显示出来的是一片乱码,我们就在网上查找更多的资料然后整合编写出能显示的程序,但第一次能显示出的是错误的信息,距离的显示和实际相当不吻合,我们发现是在设置距离显示的时候我们设置的位置太靠后导致好多数据无法显示,所以我们调整程序将距离显示的位置提到前面并成功显示;
3、在验证制作出的PCB与实际器材是否匹配时,我们发现有部分元件的封装明显不符,有可能会导致元件无法安装的问题,我们决定实际测量元器件的大小,然后修改PCB图中元件的封装,使之匹配。对于有部分元件在altium designer中没有合适封装的情况,我们通过自己画封装、下载合适封装库等方法成功得到合适的封装。
4、我们发现在altium designer自带的库中没有LCD12864,既没有原理图也没封装,对于我们第一次使用该软件而言,画LCD12864封装比较难,易出错。为了避免出错,我们自己画了LCD12864的原理图,并且采用排针代替LCD12864的方法。
5、在将元件焊接好后在上电后液晶显示屏没有显示,在检查后发现是数据口定义出错,将P1口定义成P0口了,将P0改成P1解决问题,实现显示。
6、在显示距离后调用蜂鸣器的驱动程序来实现超限报警时发现刚打开就在报警然后报警的声音差距不是很大,在很远的地方都在叫,检查主函数知道是蜂鸣器驱动函数的问题,检查后发现是if多条件判断语句运用出错,将该语句改成if-else语句并正确书写if里面的判断条件成功解决刚开始在很远的地方就报警的问题,然后将延时差距加大实现明显的不同距离段的报警。
六、实验总结与提高
该综合实验是制作一个带温度补偿、超限报警以及数字显示功能的超声波测距仪,以单片机作为核心控制器,编写程序控制周围的超声波收发模块、温度补偿模块、蜂鸣器报警装置以及LCD显示部分。在该实验中,最开始我们根据老师提供的资料商量确定了系统的框架以及各模块需要什么器件,然后我们就上网购买相应元件,在等待元件来的过程中,我们小组有明确的分工,软硬件部分分成不同的人来负责,由于我们都没有学习制作PCB板的经验,所以决定一人负责学习绘制PCB板,一人负责编写整合软件,在成功学习绘制PCB以后商量统一PCB板上各引脚的定义就可以将软
件和硬件统一起来,从而绘制我们实验需要的PCB板。因为制作PCB板的实验条件有限,对于没有学习过PCB板的制作的我们来说太复杂考虑到时间的因素和成功率的高低,我们决定将绘制的PCB图交由别人制作。在等待PCB板来的过程中,我们利用单片机学习板调试了程序,经过我们的努力成功调试完成并基本完成了实验报告。在PCB板到后,我们将各模块焊接整合到一起并将程序烧到单片机中重新调试,在解决一个又一个的问题后最终完成指定要求的超声波测距仪的制作并交由老师验收。
该实验是一个综合实验,将以前学到的一些知识运用起来,并学习整合一些新的知识,充分锻炼了同学们的实际应用和动手能力,也考验了同学们处理资料数据、查找资料、学习新知识的能力。通过该实验,我们都意识到实际的应用和制作相对于课本上的理论分析来说还是有很大不同的,也意识到我们在实际应用、解决工程问题上的能力还很是欠缺,更加认识到超声波在实际生活中有着很广泛的应用以及发展潜力。通过该实验,我们对自身以及所学专业有了更加深刻的了解,相信这对我们未来的发展有很大帮助。
成员分工:
xxx:编写程序及调试,写实验报告,焊接元件
xxx:绘制PCB板及电路原理图,焊接元件
xxx:购买元器件,焊接元件
附件:
1、电路原理图
2、PCB图
3、程序代码
#include
#include
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define LCD_data P1 //数据口
data uint i,t,l,c,a;
uchar time; //设置全局变量,专用于严格延时
double T_dist; //定时时间
double M_DIS; //实际距离
uint T_H,T_L; //存传输时间
sbit TEM=P2^7;//DS18B20温度输出口
sbit TRIG=P2^0;//超声波发射端
sbit ECHO=P2^1;//超声波接收端
sbit BEEP=P3^6;//蜂鸣器报警
sbit RS=P2^6;//LCD12864数据指令控制端
sbit RW=P2^5;//LCD12864读写端
sbit EN=P2^4;//LCD12864使能端
sbit PSB = P2^3;
sbit RST = P2^2; //液晶复位端口
void Ini_Lcd(void);
uchar TN; //实际温度的整数部分
uchar TD; //实际温度的小数部分
uchar Tflag,Ttemp; //负温度标志和临时变量
uchar data temp_data[2]={0x00,0x00}; //读出温度暂放
uchar code str0[]={
uchar code str1[]={
uchar code str2[]={
uchar code str3[]={
uchar code str4[]={
uchar code str5[]={
uchar code str6[]={
uchar code str7[]={
uchar code str8[]={
uchar code num[]={
uchar code cnt[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00}; //自定义字符
uchar dis[16]={' ',' ','D','I','S',':',};//距离显示
uchar tem[16]={' ',' ','T','E','M',':',};//温度显示
//中断重启函数
void Restart_int()
{ TMOD = 0X11;//确定定时器0和1的工作方式,方式1(工作方式寄存器);
TCON = 0X00;//定时器中断清零且不允许计数(控制寄存器)
ET1=1;//允许定时器1中断
TH1=0;//定时初值为0
TL1=0;
}
//延时程序
void delaynus(uint i)
{uchar j;
while(i--)
{
for(j=0;j
}
}
//蜂鸣器驱动程序
void beep()
{
uchar i;
if(M_DIS>20.0&&M_DIS
{
for(i=0;i
{
BEEP=1;
delaynus(15);
BEEP=0;
delaynus(15);
}
}
else if(M_DIS>10.0&&M_DIS
{
for(i=0;i
{
BEEP=1;
delaynus(7);
BEEP=0;
delaynus(7);
}
else if(M_DIS
{
for(i=0;i
{
BEEP=1;
delaynus(1);
BEEP=0;
delaynus(1);
}
}
else
BEEP=0;
}
//液晶Busy状态判断函数,数据线的最高位DB7为1则busy
bit Read_busy()
{
bit result;
RS=0;
RW=1;
EN=1;
_nop_();
_nop_();
_nop_();
EN=0;
return result; //返回忙碌标志,1:忙碌
}
//液晶写指令函数
void WR_Cmd(uchar Cmd)
{
while(Read_busy());
RS = 0;
RW = 0;
EN= 1;
delaynus(5);
LCD_data=Cmd;
delaynus(5);
EN= 0;
}
//液晶写数据函数
void WR_Data(uchar Data)
{
while(Read_busy());
RS=1;
EN=1;
delaynus(5);
LCD_data=Data;
delaynus(5);
EN= 0;
}
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if (X==1)
{X=0x80;}
else if (X==2)
{X=0x90;}
else if (X==3)
{X=0x88;}
else if (X==4)
{X=0x98;}
pos=X+Y ;
WR_Cmd(pos); //显示地址
}
//LCD初始化子程序
void Ini_Lcd(void)
PSB=1; //并口方式
EN=0;
RST=0;
delaynus(5);
RST=1;
WR_Cmd(0x34); //扩充指令操作
delaynus(5);
WR_Cmd(0x30); //基本指令操作
delaynus(5);
WR_Cmd(0x01); //清除LCD的显示内容
delaynus(5);
WR_Cmd(0x0c); //显示开,关光标
delaynus(5);
WR_Cmd(0x06);
delaynus(5);
}
void delay1(l) //11us
{
for(;l>0;l--);
}
//初始化DS18B20
ow_reset(void) //DS18B20复位函数
char presence=1;
while(presence)
{
TEM=1;_nop_();_nop_();
TEM=0;
delay1(50); //550us
TEM=1;
delay1(3);
presence=TEM;//如初始化成功,则返回一个低电平0,跳出while循环继续执行后面的延时程序 }
delay1(45);
TEM=1;
}
uchar read_byte(void) //DS18B20读命令函数
{
uchar i;
uchar value=0;
for(i=8;i>0;i--)
{
TEM=1;_nop_();_nop_();
TEM=0;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
TEM=1;_nop_();_nop_();_nop_();_nop_();
value>>=1;
if(TEM) value|=0x80;
delay1(6);
}
return (value);
}
void write_byte(uchar val) //DS18B20写命令函数(温度传感器)
{
uchar i;
for(i=8;i>0;i--)
{
TEM=1;_nop_();_nop_(); //温度输入口TEM
TEM=0;_nop_();_nop_();_nop_();_nop_();_nop_(); //5us
TEM=val&0x01; //最低位移出
delay1(6);
TEM=1;
_nop_();_nop_();
val=val/2; //右移1位
}
delay1(1);
}
//做好读取温度的准备
void TEM_Ready()
ow_reset(); //复位
write_byte(0xcc);//CCH,忽略64位ROM地址,直接向18B20发温度转换命令
write_byte(0x44); //启动温度转换
delay1(200); //转换一次需要延时一定时间
ow_reset(); //复位
write_byte(0xcc);//CCH,忽略64位ROM地址,直接向18B20发温度转换命令
write_byte(0xbe);//BEH,读暂存器,读内部RAM中9字节的温度数据
}
//读取温度值并处理函数
void rw_temp()
{
Tflag=0;//负温度标志
TEM_Ready();//读温度准备
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
if((temp_data[1]&0XF8)!=0x00)//判断温度符号
{
Tflag=1;
temp_data[0]=~temp_data[0];
temp_data[1]=~temp_data[1]; //为负则处理
Ttemp=temp_data[0]+1;
if(Ttemp>255) temp_data[1]++;
TN=temp_data[1]*16+temp_data[0]/16; // 计算温度整数部分
TD=(temp_data[0]%16)*10/16;//计算温度小数部分
}
//温度值存储函数
void tem_sto()
{
uchar i,j,k;
if(Tflag==0)//温度符号存储
tem[6]=' ';
else
tem[6]='-';
i=TN/100;//百位
j=(TN%100)/10;//十位
k=TN%10;//个位
tem[7]=num[i];
if(i==0){tem[7]=' ';}
tem[8]=num[j];
tem[9]=num[k];
tem[10]='.';
tem[11]=num[TD];
}
//温度显示值处理函数
void tem_dis()
{
uchar i;
WR_Cmd(0x01);
delay1(5);
//Set_line(0x00);
//Set_column(0x00);
lcd_pos(2,1);
delay1(5);
i=0;
while(tem[i]!='\0')//显示温度值
{
WR_Data(tem[i]);
i++;
}
WR_Data(' ');
WR_Data(0x00);
delay1(5);
}
//温度显示函数
void tem_msu()
{
rw_temp();
tem_sto();
tem_dis();
}
//距离计算函数 输出M_DIS,单位:cm
void distance()
{
double Speed;
double i;
i=T_dist/2.0; //超声传播时间
Speed=331.4+0.607*TN; //计算超声传播速度
M_DIS=i*Speed; //距离
M_DIS=M_DIS/10000.0;
}
//测距函数
void Measure()
{
uint i,j,k,l;
double m;
uchar tempa;
uchar IsOverFlow=0;
unsigned long Time;
TRIG = 0;//发送一个脉冲
for(tempa = 0; tempa
{
TRIG = 1;
}
TRIG = 0;
while(1)
{
if(ECHO == 1)
{//Start Timer;
TR1=1;//start timer
break;
}
if(TF1 == 1)
{
IsOverFlow = 1;
break;//overflow;
}
}
while(1)
{
if(ECHO == 0)
{//Stop Timer;
TR1=0;
break;
}
if(TF1 == 1)
{
IsOverFlow = 1;
break;//overflow;
}
}
Time = TH1;
Time
Time = Time+TL1;
if((Time>60000)||(Time
{
for(i=10;i
dis[i-4]=str4[i]; //‘ERROR’
dis[11]=' ';
}
else
{
T_dist=Time;
distance(); //距离计算函数
m=M_DIS*10.0; //计算距离
i=(uint)M_DIS/100;//百位
j=((uint)M_DIS%100)/10;//十位
k=(uint)M_DIS%10;//个位
l=(uint)m%10; //小数点后第一位
dis[6]=num[i];
dis[7]=num[j];
dis[8]=num[k];
dis[9]='.';
dis[10]=num[l];
dis[11]=' ';
dis[12]='C';
dis[13]='M';
Ttemp=i*100+j*10+k;//记录延时时长
}
}
//距离显示函数
void DIS_Dis()
{
int i;
// Set_line(0x28);
// Set_column(0x28);
lcd_pos(3,1);
delaynus(10);
i=0;
while(dis[i]!='\0')//显示距离
{
WR_Data(dis[i]);
i++;
}
delaynus(1);
}
//开机初始化函数
void Init()
{
uchar i;
Ini_Lcd();
WR_Cmd(0x01);
delaynus(10);
//Set_line(0x05);
// Set_column(0x05);
lcd_pos(1,1);
delaynus(10);
i=0;
while(str0[i]!='\0')// Init...
{
WR_Data(str0[i]);
i++;
}
delaynus(5);
WR_Cmd(0x40); //设定CGRAM地址
delaynus(5);
i=0;
for(i=0;i
WR_Data(cnt[i]); //写入自定义图形
EA=1;//开总中断
IT0=1; //选择边缘方式触发
TMOD=0X10;//T1定时工作方式1
ET1=1;//允许定时器1中断
TR1=0;//不启动定时器1
TH1=0;//定时初值为0
TL1=0;
TRIG=0;
Tflag=0;
Ttemp=0;
time=0;
TN=0;//实际温度的整数部分
TD=0;// 实际温度的小数部分
// Error=0;//测距超出范围或测距盲区为1
T_dist=0;//定时时间
M_DIS=0;//实际距离
T_H=0;
T_L=0;
delaynus(10000);
}
//开机显示信息函数
void start()
{
uchar i;
i=0;
WR_Cmd(0x01);//清屏
delaynus(5);
lcd_pos(1,1);
delaynus(5);
i=0;
while(str1[i]!='\0')//四川大学
{
WR_Data(str1[i]);
i++;
}
i++;
lcd_pos(3,1);
delaynus(5);
i=0;
while(str8[i]!='\0')//综合实验
{
WR_Data(str8[i]);
i++;
}
i++;
delaynus(10);
delaynus(5000);
WR_Cmd(0x01);
delaynus(20);
lcd_pos(1,2); //施富强
delaynus(50);
i=0;
while(str2[i]!='\0')
{
WR_Data(str2[i]);
i++;
}
i++;
lcd_pos(2,1);
delaynus(50);
i=0;
while(str5[i]!='\0')//1142051080
{
WR_Data(str5[i]);
i++;
}
i++;
lcd_pos(3,2);
delaynus(50);
i=0;
while(str3[i]!='\0')//刘圣忠
{
WR_Data(str3[i]);
i++;
}
i++;
lcd_pos(4,1);
delaynus(50);
i=0;
while(str6[i]!='\0')//1142051077
{
WR_Data(str6[i]);
i++;
}
delaynus(10000);
WR_Cmd(0x01);
delaynus(50);
lcd_pos(2,2);
delaynus(50);
i=0;
while(str4[i]!='\0')
{
WR_Data(str4[i]);//翁鹏飞
i++;
}
i++;
lcd_pos(3,1);
delaynus(50);
i=0;
while(str7[i]!='\0')//1142051207
{
WR_Data(str7[i]);
i++;
}
delaynus(10000);
}
//主函数
void main(void)
{
Init();//开机初始化函数
start();//开机显示函数
while(1)
{
tem_msu(); //测温函数
delaynus(10); //延时
Restart_int(); //中断重启函数
delaynus(10); //延时函数
Measure(); //测距函数
DIS_Dis(); //距离显示
beep(); //蜂鸣器函数
delaynus(Ttemp); //延时函数
}
}