总体方案本设计主要是进行距离的测量和报警,设计中涉及到的内容较多,主要是将单片机控制模块、超声波测距模块、蜂鸣器报警模块、4位数码管显示模块这几个模块结合起来。
而本设计的核心是超声波测距模块,其他相关模块都是在测距的基础上拓展起来的,测距模块是利用超声波传感器,之后选择合适单片机芯片,以下就是从相关方面来论述的。
超声波测距仪超声波是一种超出人类听觉极限的声波即其振动频率高于20 kHz的机械波。
超声波传感器在工作的时候就是将电压和超声波之间的互相转换,当超声波传感器发射超声波时,发射超声波的探头将电压转化的超声波发射出去,当接收超声波时,超声波接收探头将超声波转化的电压回送到单片机控制芯片。
超声波具有振动频率高、波长短、绕射现象小而且方向性好还能够为反射线定向传播等优点,而且超声波传感器的能量消耗缓慢有利于测距。
在中、长距离测量时,超声波传感器的精度和方向性都要大大优于红外线传感器,但价格也稍贵。
从安全性,成本、方向性等方面综合考虑,超声波传感器更适合设计要求。
综合上述三种测距仪的对比,本实验选着超声波测距仪。
系统方案本系统选择52单片机作为控制系统核心,所测得的距离数值由4位共阴极数码管显示,与障碍物之间的不同距离利用蜂鸣器频率的不同报警声提示,超声波发射信号由52单片机的P1.0口送出到超声波发射电路,将超声波发送出去,报警系统由蜂鸣器电路构成。
本设计中将收发超声波的探头分离这样不会使收发信号混叠,从而能避免干扰,可以很好的提高系统的可靠性。
系统框图如下:硬件设计超声波测距模块模块功能该模块利用超声波测距仪,测试小车与障碍物之间的距离,当距离小于某一给定值时,利用程序,将信号传递给单片机的某个引脚。
其他控制模块检测该引脚的电平高低,根据电平的高低,控制小车的行驶状态。
基本实现原理超声波接收器 放大器 检波电路显示模块51单片机放大电路报警模块 超声波接收器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口产生一个频率的方波)软件设计系统程序设计的主要的功能是发射超声波、接受超声波、计算测量距离、数据计算、蜂鸣器报警和数码管显示主程序流程图如上,当发生中断时,则会进行中断处理。
设计中断处理流程图中断处理流程包括,报警处理和数码管扫描处理N报警中断处理误差分析上述实际为73cm 实验数据位71cm超声波测距误差分析根据超声波测距的原理,测量误差的来源有:1、启动发射和启动计时之间的偏差;2、收到回波到被检测出的滞后;3、收到中断到中断响应停止计时之间的滞后;4、计时器本身的误差;5、温度对声波速度以及上述因素的影响。
第二项误差源于检测电路的灵敏度和判断偏差,从收到实际回波到电路确认并输出相应信号肯定存在滞后,这和回波信号强弱、检测电路原理以及判断电路的敏感性相关,也是超声波测距的核心。
因为如果灵敏度过高,则会将一些干扰信号误作为回波,导致测量出错,如果过低,又大大限制了检测距离,因为回波衰减是距离的平方关系。
这部分误差是导致数据不稳定的主要来源,因为判断滞后会随着回波的强弱而变化。
代码//晶振=12M//MCU=STC10F04XE//P0.0-P0.6共阳阴数码管引脚//Trig = P1^0//Echo = P3^2#include <reg52.h> //包括一个52标准内核的头文件#define uchar unsigned char //定义一下方便使用#define uint unsigned int#define ulong unsigned long//***********************************************//sfr CLK_DIV = 0x97; //为STC单片机定义,系统时钟分频// //为STC单片机的IO口设置地址定义sfr P0M1 = 0X93;sfr P0M0 = 0X94;sfr P1M1 = 0X91;sfr P1M0 = 0X92;Sfr P2M1 = 0X95;Sfr P2M0 = 0X96;//***********************************************sbit Trig = P1^0; //产生脉冲引脚sbit Echo = P3^2; //回波引脚sbit spk = P2^0; //蜂鸣器uchar code SEG7[10]={0xeb,0x28,0xb3,0xba,0x78,0xda,0xdb,0xa8,0xfb,0xfa};//数码管0-9uint distance[4]; //测距接收缓冲区uchar ge,shi,bai,qian,temp,flag,outcomeH,outcomeL,i; //自定义寄存器bit succeed_flag; //测量成功标志//********函数声明void conversion(uint temp_data);void delay_30us();void main(void) // 主程序{ uint distance_data,a,b,j=1000;uchar CONT_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; //启动定时器0IT0=0; //由高电平变低电平,触发外部中断ET0=1; //打开定时器0中断//ET1=1; //打开定时器1中断EX0=0; //关闭外部中断EA=1; //打开总中断0while(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; //启动定时器1EA=1;while(TH1 < 30);//等待测量的结果,周期65.535毫秒(可用中断实现)TR1=0; //关闭定时器1EX0=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;else spk=0;} //为什么除以58等于厘米,Y米=(X秒*344)/2// X秒=(2*Y米)/344 ==》X秒=0.0058*Y米=>厘米=微秒/58if(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_() interrupt 0 // 外部中断是0号,外部中断已设置为了下降沿触发{outcomeH =TH1; //取出定时器的值outcomeL =TL1; //取出定时器的值succeed_flag=1; //至成功测量的标志EX0=0; //关闭外部中断}//****************************************************************//定时器0中断,用做显示timer0() interrupt 1 // 定时器0中断是1号{TH0=0xfd; //写入定时器0初始值TL0=0x77;switch(flag){ case 0x00:P0=ge; P2= 0xEF;flag++;break; //个位片选对应于p0.0case 0x01:P0=shi; P2= 0xDF;flag++;break;case 0x02:P0=bai; P2= 0xBF;flag++;break;case 0x03:P0=qian;P2= 0x7F;flag=0;break;if(shi<30) //判断蜂鸣器的鸣叫spk=!spk;}}//显示数据转换程序void conversion(uint temp_data){uchar ge_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;}void delay_30us(){ uchar bt ;for(bt=0;bt<10;bt++); }// void delay_750us()// { uchar bt ;// for(bt=0;bt<250;bt++); // }。