一、 设计要求
1、提供2cm—400cm的非接触式距离测量功能,测距精度达到3mm。
2、测量结果通过液晶屏实时显示。
3、当测量距离小于20cm时,进行声音和灯光报警。
二、 超声波测距原理
测量距离的方法有很多种,短距离的可以用米尺,远距离的有激光测距等,超声波测距适用于高精度的中长距离测量。因为超声波在标准空气中的传播速度为331.45米/秒,由单片机负责计时,系统的测量精度理论上可以达到毫米级。
超声波测距的原理一般采用渡越时间法TOF(time of flight),也可以称为回波探测法,如图1所示。超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在介质中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。根据传声介质的不同,可分为液介式、气介式和固介式三种。根据所用探头的工作方式,又可分为自发自收单探头方式和一发一收双探头方式。而倒车雷达一般是装在车尾,超声波在空气中传播,超声波在空气中(20℃)的传播速度为340m/s(实际速度为344m/s这里取整数),根据计时器记录的时间就可以计算出发射点距障碍物的距离,公式S340*t/2。
图1 超声波测距原理
由于超声波也是一种声波,其声速c与温度有关,表1列出了几种不同温度下的声速。在使用时,如果温度变化不大,则可认为声速是基本不变的。如果测距精度要求很高,则应通过温度补偿的方法加以校正。
表1 声速与温度的关系
温度(℃) 声速(m/s) -30 313 -20 319 -10 325 0 323 10 338 20 344 30 349 100 386 三、 硬件系统设计
1、设计框图
本研究设计的超声波测距仪框图如图2所示。
US-100超声波收发模块模拟电压信号STC89C52单片机触发电路中断接收计算距离LCD距离显示声光报警
图2 超声波测距仪方框图
2、US-100超声波收发模块
该超声波收发模块可自己产生40kHz的方波,并经放大电路驱动超声波发射探头发射超声波,发射出去的超声波经障碍物反射后由超声波接收探头接收。经接收电路的检波放大,积分整形,在ECHO引脚上产生方波脉冲,该脉冲宽度与被测距离成线性关系。具体过程如图3所示。
图3 US-100超声波收发模块工作时序图
上图表明:只需要在Trig/TX管脚输入一个10us以上的高电平,系统便可发出8个40KHZ的超声波脉冲,然后检测回波信号,当检测到回波信号后,模块还要进行温度值的测量,然后根据当前温度对测距结果进行校正,将校正后的结果通过Echo/RX管脚输出。
在此模式下,模块将距离值转化为340m/s时的时间值的2倍,通过Echo端输出一个高电平,可根据此高电平的持续时间来计算距离值。即距离值为:(高电平时间*340m/s)/2
注:因为距离值已经经过温度校正,此时无需再根据环境温度对超声波声速进行校正,也就是不管温度多少,声速选择340m/s即可。
使用US-100超声波收发模块进行距离测量测量时,单片机只需要输出触发信号,并监视回响引脚,通过定时器计算回响信号宽度,并换算成距离即可。该模块简化了发送和接收的模拟电路,工作稳定可靠,其参数指标如表2所示。
表2 US-100模块电气参数
应注意测量周期必须在60毫秒以上,防止发射信号对回响信号的影响。
图4 US-100超声波模块外形图
模块共有两个接口,即模式选择跳线和5pin接口。模式选择跳线接
口设置为当安装上短路帽时为UART(串口)模式,拔掉时为电平触发模式。 3、单片机电路
本设计选用宏晶公司高性能单片机STC89C52,其管脚如图5所示。
图5 STC89C52单片机管脚图
该芯片为52内核8位单片机,兼容Intel等52内核单片机,支持ISP下载,适用于常用检测控制电路。由STC89C52组成的单片机系统原理图如图6所示。
图中TRIG引脚为单片机发送触发信号的引脚,ECHO引脚为US-100模块送回回响信号的引脚,接至单片机外部中断P3.2脚上,可以利用外部中断测量回响信号宽度。
当测量距离小于阈值20cm时,单片机通过管脚P3.6发出灯光报警信号,触发LED报警灯亮,同时通过管脚P3.7发出声音报警信号beep,该信号用以触发蜂鸣器鸣响报警。
图6 单片机系统及超声波模块接口原理图
4、蜂鸣器报警电路
图7所示为蜂鸣器报警电路。由于单片机管脚的灌电流比拉电流容量大,因此电路设计为低电平输出时蜂鸣器响,高电平关闭。当P3.7脚输出低电平时,
PNP型三极管8550导通,有集电极电流通过,蜂鸣器鸣响。当P3.7脚输出高电平时,三极管截止,蜂鸣器关闭。
图7 蜂鸣器报警电路
5、显示电路
显示部分采用SMC 1602液晶屏进行数据显示,其主要技术参数为:
表3 液晶屏技术指标
接口信号说明如表4所示。
表4 液晶屏接口信号说明
与单片机接口电路如图8所示。
图8 LCD与单片机接口电路
6、供电及程序下载电路
本设计采用USB接口供电,电源电压5V。同时,USB接口通过内含PL2303芯片的转换电路对单片机进行程序编写。其电路原理如图9所示。
图9 供电及程序下载电路
四、 软件编程
1、软件流程图
本设计软件主程序流程图如图10所示, (a)为主程序流程图,(b)为定时中断子程序流程图,(c)为外部中断子程序流程图。
数据初始化定时器初始化显示初始化进入后台while循环超声波测量触发有回波否?有外部中断子程序无计算距离并显示距离小于20cm否?是声光报警否外部中断入口读取定时器当前值延时60ms置测量成功标志
返回 (a) 主程序流程图 (b) 外部中断流程图
图10 程序流程图 2、主程序
下面介绍main.c主程序编写,其他程序略。
(1) 头文件和一些宏定义
/*******************************************************************/ /*******************超声波测距仪************************************/ /*******************(液晶屏显示)************************************/ /*******************晶振 11.0592MHz********************************/ #include typedef unsigned char U8; /* defined for unsigned 8-bits integer variable无符号8位整型*/ typedef signed char S8; /* defined for signed 8-bits integer variable有符号8位整型*/ typedef unsigned int U16; /* defined for unsigned 16-bits integer variable无符号16位整型*/ typedef signed int S16; /* defined for signed 16-bits integer variable有符号16位整型*/ typedef unsigned long U32; /* defined for unsigned 32-bits integer variable无符号32位整型*/ typedef signed long S32; /* defined for signed 32-bits integer variable 有符号32位整型*/ typedef float F32; /* single precision floating point variable (32bits)单精度浮点数32位长度*/ typedef double F64; /* double precision floating point variable (64bits)双精度浮点数64位*/ //定时器0的定时值为1mS,即11059/12=922个时钟脉冲,其补为65536-922=64614 #define SYSTEMCLK 921600 //11059200/12 #define T0CLK 921600 //11059200/12 #define T1CLK 921600 //11059200/12 #define T1PERIOD 1000000/921600 //T1周期时间,以微秒为单位,约为1.085uS #define TIMER0H 0xFC //64614/256=252 #define TIMER0L 0x66 //54447%256=102 (2) 管脚、常量、变量定义和函数声明 //管脚定义 sbit Trig = P1^3; sbit Echo = P3^2; //回波必须接在外部中断引脚上 sbit LedAlarm = P3^6; //报警灯,低电平亮 sbit Beep = P3^7; //报警蜂鸣器 //定义标志 volatile bit FlagSucceed = 0; //测量成功标志 volatile bit FlagDisplay = 0; //显示标志 //定义全局变量 U16 DisplayCount=0; U16 time=0; U32 distance=0; //函数声明 void delay_20us(); void Start_Module(); void INT0_Init(void); void Data_Init(); void Timer0_Init(); void Timer1_Init(); (3) 各子程序 //20us延时程序,不一定很准 void delay_20us() { U16 bt ; for(bt=0;bt<100;bt++); //8M晶振是100 } //数据初始化 void Data_Init() { Trig = 0; distance = 0; DisplayCount = 0; } //外部中断初始化函数 void INT0_Init(void) { IT0 = 0; //负边沿触发中断 EX0=0; //关闭外部中断 } //外部中断处理用做判断回波电平 void INT0_ISR (void) interrupt 0 { time =TH1*256+TL1; //取出定时器的值 FlagSucceed = 1; //置成功测量的标志 EX0=0; //关闭外部中断 } //定时器0初始化,16位定时模式,初始化为1ms中断一次。 void Timer0_Init() { TMOD = 0x11; //定时器0和1工作在16位方式 TH0 = TIMER0H; TL0 = TIMER0L; TR0 = 1; //启动定时器 ET0 = 1; //允许定时器0中断 } //定时器0中断,用做显示计时 void Timer0_ISR(void) interrupt 1 // 定时器0中断是1号 { TH0 = TIMER0H; TL0 = TIMER0L; DisplayCount ++; if (DisplayCount >= 1000) //1秒钟显示一次 { FlagDisplay = 1; DisplayCount = 0; } } //定时器1初始化,16位计数模式,时钟为11059200/12=921600Hz //60ms计数为55296,即0xD800 void Timer1_Init() { TMOD = 0x11; //定时器0和1工作在16位方式 TH1 =0; TL1= 0; ET1 = 1; } //启动模块,Trig管脚20us正脉冲 void Start_Module() //启动模块 { Trig=1; //启动一次模块 delay_20us(); Trig=0; } /******************************************************************** * 名称 : Main() * 功能 : 主函数 ***********************************************************************/ void main() { U16 i, j; EA = 0; INT0_Init(); Timer0_Init(); //定时器0初始化 Timer1_Init(); //定时器1初始化 Data_Init(); EA = 1; L1602_init(); L1602_string(1,1,\"Welcome to my \"); L1602_string(2,1,\"distance meter! \"); //延时 for (i=0;i<1000;i++) for (j=0;j<1000;j++) {;} while(1) { EA= 0; //以下为一次检测过程:先发出Trig电平,打开外部中断,清零T1, //最后在外部中断下降沿触发时取出T1当前值,计算出Trig脉冲宽度。 Start_Module(); while(Echo==0); //等待Echo回波引脚变高电平 FlagSucceed = 0; EX0=1; TH1= 0; TL1= 0; TF1= 0; TR1=1; //启动定时器1开始计数 EA = 1; while (TH1<80) ; //盲区 TR1 = 0 ; //关闭定时器1 EX0 = 0; //关闭外部中断 if(FlagSucceed==1) //一次测试成功,则计算距离,单位为厘米 { distance = time * 1.085 ; //计算得到脉冲时间(以微秒为单位) //将微秒时间转变成厘米距离的算法: Y米=(X秒*344)/2 // X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58 distance /=58; //如果距离小于20cm,则声光报警 if ((FlagSucceed == 1) && (distance < 20)) { LedAlarm = 0; Beep = 0; } else { LedAlarm = 1; Beep = 1; } } if (FlagDisplay == 1) //1秒显示时间到 { if(FlagSucceed==0) { //LCD提示无回波 L1602_string(1,1,\"OutOfRange(0-4m)\"); L1602_string(2,1,\" ------ \"); } else { //LCD显示数据 L1602_string(1,1,\"Distance Result:\"); L1602_string(2,1,\" cm \"); L1602_int(2, 5, distance ); } FlagDisplay = 0; } } } 3、显示程序 /******************************************************************** * 文件名 : 液晶1602显示.c * 描述 : 该程序实现了对液晶1602的控制。 ***********************************************************************/ #include \"1602.h\" #include \"math.h\" /******************************************************************** * 名称 : delay() * 功能 : 延时,延时时间大概为140US。 * 输入 : 无 * 输出 : 无 ***********************************************************************/ void delay() { int i,j; for(i=0; i<=10; i++) for(j=0; j<=2; j++) ; } /******************************************************************** * 名称 : Convert(uchar In_Date) * 功能 : 因为电路设计时,P0.0--P0.7接法刚好了资料中的相反,所以设计该函数。 * 输入 : 1602资料上的值 * 输出 : 送到1602的值 ***********************************************************************/ uchar Convert(uchar In_Date) { /* uchar i, Out_Date = 0, temp = 0; for(i=0; i<8; i++) { temp = (In_Date >> i) & 0x01; Out_Date |= (temp << (7 - i)); } return Out_Date; */ return In_Date; } /******************************************************************** * 名称 : enable(uchar del) * 功能 : 1602命令函数 * 输入 : 输入的命令值 * 输出 : 无 ***********************************************************************/ void enable(uchar del) { P0 = Convert(del); RS = 0; RW = 0; E = 0; delay(); E = 1; delay(); } /******************************************************************** * 名称 : write(uchar del) * 功能 : 1602写数据函数 * 输入 : 需要写入1602的数据 * 输出 : 无 ***********************************************************************/ void write(uchar del) { P0 = Convert(del); RS = 1; RW = 0; E = 0; delay(); E = 1; delay(); } /******************************************************************** * 名称 : L1602_init() * 功能 : 1602初始化,请参考1602的资料 * 输入 : 无 * 输出 : 无 ***********************************************************************/ void L1602_init(void) { enable(0x01); enable(0x38); enable(0x0c); enable(0x06); enable(0xd0); } /******************************************************************** * 名称 : L1602_char(uchar hang,uchar lie,char sign) * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示\"b\" ,调用该函数如下 L1602_char(1,5,'b') * 输入 : 行,列,需要输入1602的数据 * 输出 : 无 ***********************************************************************/ void L1602_char(uchar hang,uchar lie,char sign) { uchar a; if(hang == 1) a = 0x80; if(hang == 2) a = 0xc0; a = a + lie - 1; enable(a); write(sign); } /******************************************************************** * 名称 : L1602_string(uchar hang,uchar lie,uchar *p) * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示\"ab cd ef\" ,调用该函数如下 L1602_string(1,5,\"ab cd ef;\") * 输入 : 行,列,需要输入1602的数据 * 输出 : 无 ***********************************************************************/ void L1602_string(uchar hang,uchar lie,uchar *p) { uchar a; if(hang == 1) a = 0x80; if(hang == 2) a = 0xc0; a = a + lie - 1; enable(a); while(1) { if(*p == '\\0') break; write(*p); p++; } } //显示整型的温湿度数据用,共占用4位,其中一位符号位 void L1602_int(uchar hang, uchar lie, int num) { uint temp; uint gewei,shiwei,baiwei,sign; if (num >= 0) { sign = 0; } else { sign = 1; } temp = abs(num); baiwei = temp / 100; temp = temp - baiwei*100; shiwei = temp / 10; gewei = temp - shiwei*10; num = abs(num); if (num>=100) { if (sign == 1) //负数 { L1602_char(hang, lie, '-'); } L1602_char(hang, lie+1, baiwei+48); L1602_char(hang, lie+2, shiwei+48); L1602_char(hang, lie+3, gewei+48); } else if (num>=10) { if (sign == 1) { L1602_char(hang, lie+1, '-'); } L1602_char(hang, lie+2, shiwei+48); L1602_char(hang, lie+3, gewei+48); } else { if (sign == 1) { L1602_char(hang, lie+2, '-'); } L1602_char(hang, lie+3, gewei+48); } } 五、 下载与调试 当程序在uVision环境下编写完成,并编译生成.hex文件后,就可以下载并进行调试了。 1、 USB转串口驱动安装 打开USB驱动文件夹下的PL2303_Prolific_DriverInstaller_v130.exe安装文件,按提示安装USB转串口驱动程序。安装完成后,插入USB下载线后,在[开始]-[控制面板]-[打印机和其他硬件]-[设备管理器],在“端口”分支下有(Prolific USB-to-Serial Comm Port(COMX)。X表示串口号,如果没有说明USB转串口驱动没有安装,须重新安装。记住括号里的COM口号。 图11 成功安装USB转串口驱动示意图 2、 下载程序 打开STC单片机下载软件文件夹,点击运行STC_ISP_V481.exe程序,出现如下界面。 图12 下载软件 正确选择MCU 类型为STC89C52,COM口(与刚才安装的COM号一致),最高波特率和最低波特率都选2400bps或者1200bps (下载线内PL2303芯片所限,没办法!),并打开正确的.hex数据文件。 点击“Download/下载”按纽,窗口出现提示: Chinese:正在尝试与 MCU/单片机 握手连接 ... Connection is failure. You can try: 1.Give your MCU Power On Reset. 2.Stop operation, then re-select COM Port. 3.Because PLCC-DIP/PQFP-DIP Socket trace too long. 4.Update the STC ISP.exe version. 5.If still error, your MCU Firmware is error or null. Chinese:连接失败,请尝试以下操作: 1.在单片机停电状态下,点下载按钮,再给单片机上电 2.停止下载,重新选择 RS-232 串口, 接好电缆 3.可能需要先将 P1.0/P1.1 短接到地 4.可能外部时钟未接 5.因 PLCC、PQFP 转换座引线过长而引起时钟不振荡,请 调整参数 6.可能要升级电脑端的 STC ISP.exe 软件 7.若仍然不成功,可能 MCU/单片机内无 ISP 系统引导码, 或需退回升级,或 MCU 已损坏 8.若使用 USB 转 RS-232 串口线下载,可能会遇到不兼容 的问题,可以让我们帮助购买兼容的 USB 转 RS-232 串口线 仍在连接中, 请给 MCU 上电... 按下电路板上的电源按纽,保证其有个失电至上电的过程,则窗口显示开始烧录芯片。芯片烧录成功后,程序开始运行,超声波测距仪正常工作。 因篇幅问题不能全部显示,请点此查看更多更全内容