超声波测距.docx
《超声波测距.docx》由会员分享,可在线阅读,更多相关《超声波测距.docx(11页珍藏版)》请在冰豆网上搜索。
超声波测距
总体方案
本设计主要是进行距离的测量和报警,设计中涉及到的内容较多,主要是将单片机控制模块、超声波测距模块、蜂鸣器报警模块、4位数码管显示模块这几个模块结合起来。
而本设计的核心是超声波测距模块,其他相关模块都是在测距的基础上拓展起来的,测距模块是利用超声波传感器,之后选择合适单片机芯片,以下就是从相关方面来论述的。
超声波测距仪
超声波是一种超出人类听觉极限的声波即其振动频率高于20kHz的机械波。
超声波传感器在工作的时候就是将电压和超声波之间的互相转换,当超声波传感器发射超声波时,发射超声波的探头将电压转化的超声波发射出去,当接收超声波时,超声波接收探头将超声波转化的电压回送到单片机控制芯片。
超声波具有振动频率高、波长短、绕射现象小而且方向性好还能够为反射线定向传播等优点,而且超声波传感器的能量消耗缓慢有利于测距。
在中、长距离测量时,超声波传感器的精度和方向性都要大大优于红外线传感器,但价格也稍贵。
从安全性,成本、方向性等方面综合考虑,超声波传感器更适合设计要求。
综合上述三种测距仪的对比,本实验选着超声波测距仪。
系统方案
本系统选择52单片机作为控制系统核心,所测得的距离数值由4位共阴极数码管显示,与障碍物之间的不同距离利用蜂鸣器频率的不同报警声提示,超声波发射信号由52单片机的P1.0口送出到超声波发射电路,将超声波发送出去,报警系统由蜂鸣器电路构成。
本设计中将收发超声波的探头分离这样不会使收发信号混叠,从而能避免干扰,可以很好的提高系统的可靠性。
系统框图如下:
硬件设计
超声波测距模块
模块功能
该模块利用超声波测距仪,测试小车与障碍物之间的距离,当距离小于某一给定值时,利用程序,将信号传递给单片机的某个引脚。
其他控制模块检测该引脚的电平高低,根据电平的高低,控制小车的行驶状态。
基本实现原理
HC-SR04超声波测距模块简介
HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达到3mm,模块包括超声波发射器,接收器与控制电路。
基本工作原理:
1)采用IO口TRIG触发测距,给至少10us的高电平信号;
2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间,测试距离=(高电平时间*声速)、
实物图
如上图接线,VCC供5V电源,GND为地线,TRIG触发控制信号输入,ECHO回响信号输出等四支线。
测距时序图
观察时序图可知,提供一个10us以上的脉冲触发信号给TRIG引脚,模块内部将发出8个40KHZ周期电平并检测回波。
检测到有回波信号则输出回响信号,回响信号的脉冲宽度与所测的距离成正比,由此可通过回响信号的脉宽计算距离
系统模块
显示模块
数码管分动态显示和静态显示,这里选用动态显示
动态显示驱动:
数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。
通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。
在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。
报警模块
根据距离显示结果的远近,控制蜂鸣器的鸣叫(利用I/O口产生一个频率的方波)
软件设计
系统程序设计的主要的功能是发射超声波、接受超声波、计算测量距离、数据计算、蜂鸣器报警和数码管显示
主程序流图
主程序流程图如上,当发生中断时,则会进行中断处理。
设计中断处理流程图
中断处理流程包括,报警处理和数码管扫描处理
YN报警中断处理
误差分析
上述实际为73cm实验数据位71cm
超声波测距误差分析
根据超声波测距的原理,测量误差的来源有:
1、启动发射和启动计时之间的偏差;
2、收到回波到被检测出的滞后;
3、收到中断到中断响应停止计时之间的滞后;
4、计时器本身的误差;
5、温度对声波速度以及上述因素的影响。
第二项误差源于检测电路的灵敏度和判断偏差,从收到实际回波到电路确认并输出相应信号肯定存在滞后,这和回波信号强弱、检测电路原理以及判断电路的敏感性相关,也是超声波测距的核心。
因为如果灵敏度过高,则会将一些干扰信号误作为回波,导致测量出错,如果过低,又大大限制了检测距离,因为回波衰减是距离的平方关系。
这部分误差是导致数据不稳定的主要来源,因为判断滞后会随着回波的强弱而变化。
代码
//晶振=12M
//MCU=STC10F04XE
//P0.0-P0.6共阳阴数码管引脚
//Trig=P1^0
//Echo=P3^2
#include//包括一个52标准内核的头文件
#defineucharunsignedchar//定义一下方便使用
#defineuintunsignedint
#defineulongunsignedlong
//***********************************************
//sfrCLK_DIV=0x97;//为STC单片机定义,系统时钟分频
////为STC单片机的IO口设置地址定义
sfrP0M1=0X93;
sfrP0M0=0X94;
sfrP1M1=0X91;
sfrP1M0=0X92;
SfrP2M1=0X95;
SfrP2M0=0X96;
//***********************************************
sbitTrig=P1^0;//产生脉冲引脚
sbitEcho=P3^2;//回波引脚
sbitspk=P2^0;//蜂鸣器
ucharcodeSEG7[10]={0xeb,0x28,0xb3,0xba,0x78,0xda,0xdb,0xa8,0xfb,0xfa};//数码管0-9
uintdistance[4];//测距接收缓冲区
ucharge,shi,bai,qian,temp,flag,outcomeH,outcomeL,i;//自定义寄存器
bitsucceed_flag;//测量成功标志
//********函数声明
voidconversion(uinttemp_data);
voiddelay_30us();
voidmain(void)//主程序
{uintdistance_data,a,b,j=1000;
ucharCONT_1;
P0M1=0;//将io口设置为推挽输出
P1M1=0;
P2M1=0;
P0M0=0XFF;
P1M0=0XFF;
P2M0=0XFF;
spk=0;
i=0;
flag=0;
Trig=0;//首先拉低脉冲输入引脚
TMOD=0x11;//定时器0,定时器1,16位工作方式
TR0=1;//启动定时器0
IT0=0;//由高电平变低电平,触发外部中断
ET0=1;//打开定时器0中断
//ET1=1;//打开定时器1中断
EX0=0;//关闭外部中断
EA=1;//打开总中断0
while
(1)//程序循环
{
while(j--);//保证系统足够上电时间
EA=0;//关闭中断时为了准确的计时
Trig=1;
delay_30us();
Trig=0;//产生一个30us的脉冲,在Trig引脚
while(Echo==0);//等待Echo回波引脚变高电平
succeed_flag=0;//清测量成功标志
EX0=1;//打开外部中断
TH1=0;//定时器1清零
TL1=0;//定时器1清零
TF1=0;//需要软件清零吗?
TR1=1;//启动定时器1
EA=1;
while(TH1<30);//等待测量的结果,周期65.535毫秒(可用中断实现)
TR1=0;//关闭定时器1
EX0=0;//关闭外部中断
if(succeed_flag==1)
{
distance_data=outcomeH;//测量结果的高8位
distance_data<<=8;//放入16位的高8位
distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据
//distance_data*=12;//因为定时器默认为12分频
distance_data/=58;//微秒的单位除以58等于厘米
if(distance_data<=50)
spk=1;
elsespk=0;
}//为什么除以58等于厘米,Y米=(X秒*344)/2
//X秒=(2*Y米)/344==》X秒=0.0058*Y米=>厘米=微秒/58
if(succeed_flag==0)
{
distance_data=0;//没有回波则清零
}
a=distance_data;
if(b==a)CONT_1=0;//这一段程序的作用是什么?
if(b!
=a)CONT_1++;
if(CONT_1>=3)
{
CONT_1=0;
b=a;
conversion(b);
}
}
}
//***************************************************************
//外部中断0,用做判断回波电平
INTO_()interrupt0//外部中断是0号,外部中断已设置为了下降沿触发
{
outcomeH=TH1;//取出定时器的值
outcomeL=TL1;//取出定时器的值
succeed_flag=1;//至成功测量的标志
EX0=0;//关闭外部中断
}
//****************************************************************
//定时器0中断,用做显示
timer0()interrupt1//定时器0中断是1号
{
TH0=0xfd;//写入定时器0初始值
TL0=0x77;
switch(flag)
{case0x00:
P0=ge;P2=0xEF;flag++;break;//个位片选对应于p0.0
case0x01:
P0=shi;P2=0xDF;flag++;break;
case0x02:
P0=bai;P2=0xBF;flag++;break;
case0x03:
P0=qian;P2=0x7F;flag=0;break;
if(shi<30)//判断蜂鸣器的鸣叫
spk=!
spk;
}
}
//******************************************************************
//显示数据转换程序
voidconversion(uinttemp_data)
{
ucharge_data,shi_data,bai_data,qian_data;
qian_data=temp_data/1000;
temp_data=temp_data%1000;//取余运算
bai_data=temp_data/100;
temp_data=temp_data%100;//取余运算
shi_data=temp_data/10;
temp_data=temp_data%10;//取余运算
ge_data=temp_data;
EA=0;
qian=SEG7[qian_data];
bai=SEG7[bai_data];
shi=SEG7[shi_data];
ge=SEG7[ge_data];
EA=1;
}
//******************************************************************
voiddelay_30us()
{ucharbt;
for(bt=0;bt<10;bt++);
}
//voiddelay_750us()
//{ucharbt;
//for(bt=0;bt<250;bt++);
//}
仅供个人用于学习、研究;不得用于商业用途。
Forpersonaluseonlyinstudyandresearch;notforcommercialuse.
NurfürdenpersönlichenfürStudien,Forschung,zukommerziellenZweckenverwendetwerden.
Pourl'étudeetlarechercheuniquementàdesfinspersonnelles;pasàdesfinscommerciales.
толькодлялюдей,которыеиспользуютсядляобучения,исследованийинедолжныиспользоватьсявкоммерческихцелях.
以下无正文