很给力的教程,楼主大神!!
11、吴鉴鹰单片机项目详细解析系列(连载)之基于单片机的超声波测距仪设计(一)——硬件设计一
图1
1、超声波测距原理
发射器发出的超声波以速度v在空气中传播,在到达被测物体是被反射返回,由接受器接受,其往返时间为t,有s=vt/2即可算出被测物体的距离。由于超声波也是一种声波,其声速v与温度有关,下表列出了几种不同温度下的声速。在使用时,如果温度变化不大,则可认为声速是基本不变的。如果测距精度要求很高,则应该通过温度补偿的方法加以校正。
1超声波测距仪原理框图单片机发出40khz的信号,经放大后通过超声波发射器输出;超声波接受器将接受到得超声波信号经放大器放大,用锁相环电路进行检波处理后,启动单片机中断程序,测得时间为t,再由软件进行辨别、计算,得出距离数并送LCD显示并送语音播报模块播报。
2、吴鉴鹰的项目成品具有的功能
1) 具有超声波测距功能,测量距离0.20m~5.00m测距精度±1㎝。2) 具有测量距离数值无线传输功能。3) 实时显示测量的距离,显示格式为:X.XXm。4) 汉字提醒显示:距离在0.40m~1.00m,显示“危险距离”并用红色LED灯指示;距离在1.00m~2.00m,显示“保持距离”,并用黄书LED灯指示;距离在2.00m以上,显示“安全距离”并用绿色LED灯指示。5) 具有实时语音播报功能,实时播报测量距离数值,格式:X.XXm,实时播报时间间隔≤10s,实时播报声音清晰明亮、无明显失真,在1m距离处人耳能准确分辨。语音播报要与显示同步。
图2
3、超声波测距方法的选择
超声波测距的原理一般采用渡越时间法TOF(time of flight)。首先测出超声波从发射到遇到障碍物返回所经历的时间,再乘以超声波的速度就得到二倍的声源与障碍物之间的距离。测量距离的方法有很多种,短距离的可以用尺,远距离的有激光测距等,超声波测距适用于高精度的中长距离测量。因为超声波在标准空气中的传播速度为331.45米/秒,由单片机负责计时,单片机使用12.0MHZ晶振,所以此系统的测量精度理论上可以达到毫米级。由于超声波指向性强,能量消耗缓慢,在介质中传播距离远,因而超声波可以用于距离的测量。利用超声波检测距离,设计比较方便,计算处理也较简单,并且在测量精度方面也能达到要求。根据设计任务、控制对象和现有条件本系统硬件电路采用由单片机最小系统、温度补偿电路、超声波发射电路、超声波接收电路、显示电路无线通信电路以及语音播报电路构成。本超声波测距仪的具体工作过程如下,单片机控制的振荡源产生40kHz的频率信号来驱动超声传感器。每次发射包含6个脉冲左右,当第一个超声波脉冲发射后,计数器开始计数,在检测到第一个回波脉冲的瞬间,计数器停止计数,得到从发射到接收的时间t 后,单片机读取温度值补偿声速,利用测距公式可计算出被测距离,同时由无线通信模块将测量数据传到下位机进行显示和语音播报。系统总体框图如图所示。
图3 发射模块
图 4 图4 接收模块
4、超声波发生器选择
超声波发生器可以分为两类:一类是用电气方式产生超声波,一类是用机械方式产生超声波。本课题属于近距离测量,可以采用常用的压电式超声波换能器来实现。超声波测距的原理是利用超声波的发射和接受,根据超声波传播的时间来计算出传播距离。实用的测距方法有两种,一种是在被测距离的两端,一端发射,另一端接收的直接波方式,适用于身高计;一种是发射波被物体反射回来后接收的反射波方式,适用于测距仪。此次设计采用反射波方式。测距仪的分辨率取决于对超声波传感器的选择。超声波传感器是一种采用压电效应的传感器,常用材料是压电式陶瓷。由于超声波在空气传播时会有相当的衰减,衰减的程度与频率的高低成正比;而频率高分辨率也高,故短距离测量时应选择高频率的传感器,而长距离测量时应用低频率的传感器。
5、超声波接受传感器
超声探头的核心是其塑料外套或者金属外套中的一块压电晶片。构成晶片的材料可以有许多种。晶片的大小,如直径和厚度也各不相同,因此每个探头的性能是不同的,我们使用前必须预先了解它的性能。超声波传感器的主要性能指标包括:工作频率。工作频率就是压电晶片的共振频率。当加到它两端的交流电压的频率和晶片的共振频率相等时,输出的能量最大,灵敏度也最高。工作温度。由于压电材料的居里点一般比较高,特别时诊断用超声波探头使用功率较小,所以工作温度比较低,可以长时间地工作而不失效。医疗用的超声探头的温度比较高,需要单独的制冷设备。灵敏度。主要取决于制造晶片本身。机电耦合系数大,灵敏度高;反之,灵敏度低。因此超声波接受传感器应该应用集成电路CX20106A,CX20106A是一款红外线检波接收的专用芯片,常用于电视机红外遥控接收器。考虑到红外遥控常用的载波频率38kHz与测距的超声波频率40kHz较为接近,可以利用它制作超声波检测接收电路(如图2-3)。实验证明用CX20106A接收超声波(无信号时输出高电平),具有很好的灵敏度和较强的抗干扰能力。适当更改电容CS的大小,可以改变接收电路的灵敏度和抗干扰能力。此部分电路在集成芯片上2.5显示单元选择显示单元是计算机系统开发时使用的主要设备之一,它可将计算机的运算结果、中间结果、存储器地址以及存储器、寄存器中的内容显示出来,从而实现人机对话。可以做显示器的有:LED,LCD,CRT等。CRT就是常见的显像管式的显示器。优点是颜色视觉效果好,视角宽,可靠性高,便宜;缺点是体积大耗电多,有微量的X射线辐射。LED就是发光二极管。LED一般适合做大屏幕的显示设备,最突出的有点那就是屏幕尺寸可以不受限制,亮度可以做的很高,其他的如显色性、对比度等都不如CRT显示器。但是考虑到本设计需要显示测量距离,补偿温度以及危险,保持 ,安全等警告信号。所以选择采用128*64液晶模块。2.6语音播报电路选择语音播报语音芯片有很多种,例如WT1380、WT588D等。WT1380具有多种报警功能,定时器功能,时钟输出功能,中断输出功能以及语音播报功能。它的语音功能和万年历功能可以同时工作,主频采用RC振荡,副频采用32.768K晶振精确分频。可以计算年、月、日、时、分、秒等信息,并可以将时间信息反馈给主控单片机。因而,WT1380是一款性价比极高的语音时钟芯片。但是本设计不要求芯片有可以计算年、月、日、时、分、秒等信息的复杂功能。所以播报电路采用WT588D系列的集单片机和语音电路于一体的可编辑语音芯片。WT588D系列语音单片机是广州唯创科技有限公司联合台湾华邦共同研发出来的集单片机和语音电路于一体的可编辑语音芯片。功能多音质好应用范围广性能稳定是WT588D系列语音单片机的特长,弥补了以往各类语音芯片应用领域狭小的缺陷,MP3控制模式、按键控制模式、按键组合控制模式、并口控制模式、一线串口控制模式、三线串口控制模式以及三线串口控制I/O口扩展输出模式,让应用人员能将产品投放在几乎可以想象得到的场所。WT588D是一款功能强大的可重复擦除烧写的语音单片机芯片。WT588D让语音芯片不再为控制方式而寻找合适的外围单片机电路,高度集成的单片机技术足于取代复杂的外围控制电路。配套WT-APP上位机操作软件可随意更换WT588D语音单片机芯片的任何一种控制模式,把信息下载到SPI-Flash上即可。软件操作方式简洁易懂,撮合了语音组合技术,大大减少了语音编辑的时间。2.7温度传感器的选择大家知道,声音在不同温度的空气中传播速度是不同的,所以这里要考虑到温度补偿的问题。温度传感器有很多种,例如温度传感器AD590。AD590是美国模拟器件公司生产的单片集成两端感温电流源。流过器件的电流(mA)等于器件所处环境的热力学温度(开尔文)度数。AD590的测温范围为-55℃~+150℃。AD590的电源电压范围为4V~30V。电源电压可在4V-6V范围变化,电流变化1mA,相当于温度变化1K。AD590可以承受44V正向电压和20V反向电压,因而器件反接也不会被损坏。输出电阻为710WM。它的精度高。AD590共有I、J、K、L、M五档,其中M档精度最高,在-55℃~+150℃范围内,非线性误差为±0.3℃。但是考虑到成本问题我选用TS-18B20数字温度传感器。该产品采用美国DALLAS公司生产的DS18B20可组网数字温度传感器芯片封装而成,具有耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。独特的一线接口,只需要一条口线通信多点能力,简化了分布式温度传感应用无需外部元件可用数据总线供电,电压范围为3.0V至5.5V无需备用电源测量。温度范围为-55°C至+125℃ 。-10°C至+85°C范围内精度为±0.5°C
温度传感器可编程的分辨率为9~12位温度转换为12位数字格式最大值为750毫秒用户可定义的非易失性温度报警设置应用范围包括恒温控制,工业系统,消费电子产品温度计,或任何热敏感系统。
12、吴鉴鹰单片机项目详细解析系列(连载)之基于单片机的超声波测距仪设计(二)——硬件设计二
6、硬件电路的设计
硬件电路的设计主要包括单片机系统及显示电路、语音播报电路、温度补偿电路、无线传输、超声波发射电路和超声波检测接受电路五部分。单片机采用AT89C51或其兼容系列。采用12MHz高精度的晶振,以获得较稳定的时钟频率,减小测量误差。单片机用P3.6端口输出超声波换能器所需的40KHz的方波信号,利用外部中断1口检测超声波接受电路输出的返回信号。显示单元部分采用12864液晶模块。3.1 AT89S51单片机的功能及特点AT89S51是美国ATMEL公司生产的低电压,高性能CMOS8位单片机,片内含有4K bytes的课反复擦写的只读程序存储器(PEROM)和128bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度。非易失性存储技术生产,兼容标准MCS—51指令系统,片内置通用8位中央处理器(CPU)和Flash存储单元,功能强大AT89S51单片机可以为您提供许多高性价比的应用场合,可灵活应用于各种控制领域。3.1.1主要性能参数Ø 与MCS—51产品指令系统完全兼容。Ø 4K字节可以重复擦写Flash闪速存储器。Ø 1000吃擦写周期。Ø 全静态操作:0Hz—24Hz。Ø 三级加密程序存储器。Ø 128*8字节内部RAM。Ø 32个可编程I/O口线。Ø 6个中断源。Ø 可编程串行UART通道。Ø 低功耗空闲和掉电模式。3.1.2功能特性概述AT89S51提供以下功能:Ø 4k字节Flash闪速存储器;Ø 128字节内部RAM;Ø 32个I/O口线;Ø 两个16位定时器/计时器;Ø 一个5向量两级中断结构;Ø 一个双工串行口通信;Ø 片内振荡器及时钟电路。同时,AT89S51可以降至0Hz的静态逻辑操作,并支持两种软件可选的节点工作模式。空闲方式停止CPU的工作,当允许RAM,定时/计数器,串行口及中断系统继续工作。掉电式保存RAM中的内容,但振荡器停止工作并禁止其他左右部件工作直到下一个硬件复位。
图5
图5,AT89S51单片机 3.2单片机最小系统其作用主要是为了保证单片机系统能正常工作。如图3-2所示,单片机最小系统主要由AT89S51单片机、外部振荡电路、复位电路和+5V电源组成。在外部振荡电路中,单片机的XTAL1和XTAL2管脚分别接至由12MHZ晶振和两个30PF电容构成的振荡电路两侧,为电路提供正常的时钟脉冲。在复位电路中,单片机RESET管脚一方面经20 F的电容接至电源正极,实现上电自动复位,另一方面经开关s接电源。其主要功能是把PC初始化为0000H,是单片机从0000H单元开始执行程序,除了进入系统的初始化之外,当由于程序出错或者操作错误使系统处于死锁状态时,为了摆脱困境,也需要按复位键重新启动。因此,复位电路是单片机系统中不可缺少的一部分。
图6
图6,单片机最小系统,单片机测距原理单片机发出超声波测距是通过不断检测超声波发射后遇到障碍物所反射的回波,从而测出发射和接收回波的时间差tr,然后求出距离S=Ct÷2 式中的C为超声波波速。限制该系统的最大可测距离存在4个因素:超声波的幅度、反射的质地、反射和入射声波之间的夹角以及接收换能器的灵敏度。接收换能器对声波脉冲的直接接收能力将决定最小的可测距离。为了增加所测量的覆盖范围、减小测量误差,可采用多个超声波换能器分别作为多路超声波发射/接收的设计方法,限于实际需要,本电路只采用单路超声波发射接收。由于超声波属于声波范围,其波速C与温度有关。
7、超声波发射电路
超声波发射电路压电式超声波换能器是利用压电晶体的谐振来工作的。超声波换能器内部有两个压电晶片和一个换能板。当它的两极外加脉冲信号,其频率等于压电晶片的固有振荡频率时,压电晶片会发生共振,并带动共振板振动产生超声波,这时它就是一个超声波发生器;反之,如果两电极问未外加电压,当共振板接收到超声波时,将压迫压电晶片作振动,将机械能转换为电信号,这时它就成为超声波接收换能器。超声波发射换能器与接收换能器在结构上稍有不同,使用时应分清器件上的标志。
图7
发射电路主要由反相器74LS04和超声波发射换能器T构成,如图所示,单片机P2.7端口输出的40kHz的方波信号一路经一级反向器后送到超声波换能器的一个电极,另一路经两级反向器后送到超声波换能器的另一个电极,用这种推换形式将方波信号加到超声波换能器的两端,可以提高超声波的发射强度。输出端采两个反向器并联,用以提高驱动能力。上位电阻R2、R3一方面可以提高反向器74LS04输出高电平的驱动能力,另一方面可以增加超声波换能器的阻尼效果,缩短其自由振荡时间。
8、超声波检测接收电路
超声波接收电路CX20106A是一款红外线检波接收的专用芯片,常用于电视机红外遥控接收器。考虑到红外遥控常用的载波频率38kHz与测距的超声波频率40kHz较为接近,可以利用它制作超声波检测接收电路。实验证明用CX20106A接收超声波(无信号时输出高电平),具有很好的灵敏度和较强的抗干扰能力。适当更改电容C16
的大小,可以改变接收电路的灵敏度和抗干扰能力。其电路由图所示。
图8
CX20106A的引脚注释:1脚IN:超声波信号输入端,该脚的输入阻抗约为40kΩ。2脚AGC:该脚与GND之间连接RC串联网络,它们是负反馈串联网络的一个组成部分,改变它们的数值能改变前置放大器的增益和频率特性。增大电阻R或减小C,将使负反馈量增大,放大倍数下降,反之则放大倍数增大。但C的改变会影响到频率特性,一般在实际使用中不必改动,推荐选用参数为R=4.7Ω,C=3.3μF。3脚C0:该脚与GND之间连接检波电容,电容量大为平均值检波,瞬间相应灵敏度低;若容量小,则为峰值检波,瞬间相应灵敏度高,但检波输出的脉冲宽度变动大,易造成误动作,推荐参数为3.3μF。4脚GND:接地端。5脚RC0:该脚与电源端VCC接入一个电阻,用以设置带通滤波器的中心频率f0,阻值越大,中心频率越低。例如,取R=200kΩ时,fn≈42kHz,若取R=220kΩ,则中心频率f0≈38kHz。6脚C:该脚与GND之间接入一个积分电容,标准值为330pF,如果该电容取得太大,会使探测距离变短。7脚OUT:遥控命令输出端,它是集电极开路的输出方式,因此该引脚必须接上一个上拉电阻到电源端,该电阻推荐阻值为22kΩ,没有接收信号时该端输出为高电平,有信号时则会下降。8脚RC1:电源正极,4.5V~5V。9、温度补偿电路
DS18B20温度传感器是美国DALLAS半导体公司推出的一种改进型智能温度传感器,测温范围为-55~125℃,最大分辨率可达0.0625℃。DS18B20可以直接读出被测温度值,而且采用了一线制与单片机相连,减少了外部的硬件电路,具有低成本和易使用的特点。测温电路图3-5所示。DS18B20温度传感器:(1):技术性能描述独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。Ø 测温范围-55℃~+125℃,固有测温分辨率0.5℃。Ø 工作电源:3~5V/DC。Ø 在使用中不需要任何外围元件。Ø 测量结果以9~12位数字量方式串行传送。Ø 不锈钢保护管直径Φ6。Ø 适用于DN15~25,DN40~DN250各种介质工业管道和狭小空间设备测温。Ø 标准安装螺纹M10X1,M12X1.5,G1/2任选。Ø PVC电缆直接出线或德式球型接线盒出线,便于与其它电器设备连接。
10、显示模块
带中文字库的128X64是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×64。内置8192个16*16点汉字,和128个16*8点ASCII字符集。利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4行16×16点阵的汉字。12864液晶模块可完成图形显示。低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
图9
11、语音播报电路
语音播报电路采用WT588D系列的集单片机和语音电路于一体的可编辑语音芯片。功能多音质好应用范围广性能稳定是WT588D系列语音单片机的特长,同时具有MP3控制模式、按键控制模式、按键组合控制模式、并口控制模式、一线串口控制模式、三线串口控制模式以及三线串口控制I/O口扩展输出模式。可控制的语音地址位能达到220个!每个地址位里能加载可组合语音为128段语音。只需通过适当的访问地址就可以实现语音播报,使用方便,语音播报电路设计如图所示。
图 10
11、 APC240无线通信模块
无线发射与接收电路采用APC240无线通信模块。它是新一代的多通道嵌入式无线数传模块,其可设置众多的频道,发射功率高,而仍然具有较低的功耗。它可以在工业等强干扰的恶劣环境中使用。在任何状态下都可以1次传输256bytes的数据,当设置空中波特率大于串口波特率时,可1次传输无限长度的数据。同时它还提供标准的UART/TTL,RS485和RS232三种接口1200/2400/4800/9600bps四速率,和三种接口校验方式.采用串口设置模块参数。具有丰富便洁的软件编程设置选项。无线发射与接收电路见
图 11
图12
Ø 接口方式:232/485/TTL串口,格式有8N1/8E1/8O1可选;Ø 接受灵敏度高,视距可靠传输距离可达1200m;Ø 采用FSK的方式调制,支持OOK/ASK/MSK调制;Ø 载频433MHz,可定制315M/868M/915M等其他ISM频段;Ø 提供PC机配置软件,可以灵活设置模块的各种参数;Ø 串口速率:4800/9600/19200/38400/57600/115200bps;Ø 空中速率:5K/10K/20K/30K/40K/50K/77K/100K/150K/200K/250Kbps;Ø 功耗和休眠省电模式:功率<100 mw,接收电流<35mA,发射电流<100mA,休眠时电流<12uA;Ø 支持多个字网组群工作模式,网络地址配置相同的模块间才可以相互通讯;Ø 具有中继功能,可选择中继节点进行传输,有效扩大传输距离;Ø 支持透明传输方式和地址传输方式,可以组成点对点、点对多点、对点对多点等无线通信网络;Ø 5V直流供电(可以选择3.3V);3.9.2APC240无线通信模块主要技术指标工作频率:433M 调制方式:FSK发射功率:<20dBm(100mW)接收灵敏度:-119dB发射电流:<35mA接收电流:<100mA休眠电流:<12uA工作信道:32个频段选择数据接口:232/485/TTL串口数据格式:8N1/8E1/8O1串口速率:4800/9600/19200/38400/57600/115200bps空中速率:5K/10K/20K/30K/40K/50K/77K/100K/150K/200K/250Kbps硬件接口:2.0插针/插座通讯距离:0-700米(10dbm,10kbps,可视距离)天线阻抗:50Ω工作温度:-40-85℃供电方式:DC3.3V/5V尺寸:32.3x54.0mm(不包括天线)
13、吴鉴鹰单片机项目详细解析系列(连载)之基于单片机的超声波测距仪设计(三)——软件设计(一)
/***********************************************************************************************************************
吴鉴鹰程序风格简简单介绍:① 每个子程序的开头都会有一个简介,介绍程序的功能,输入、输出变量,以及程序的作者,修改日期,
还有程序的难点、重点简单介绍,为了增强程序的可读性。
② IO口定义的格式为:A_B_C 其中A为该口对应的器件,B为功能,C为输入输出方向。
③ 输入输出方向定义原则:输入:_IN 输出:_OUT 输入输出:_IO
************************************************************************************************************************/
** 函数名称: 主机程序
** 功能描述: 超声波的发送和接收,将测得的数据发给从机
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
#include
#include
#include
#include #define uchar unsigned char
#define uint unsigned int
#define ufloat unsigned float
#define ulong unsigned long
#define NOP _nop_();_nop_();_nop_()
#define nop _nop_() sbit DS18B20_DQ_OUT = P2^6; //定义DS18B20端口DS18B20_DQ A_B_C分别对应为DS18B20_DQ_OUT
uchar presence ;
uchar Send[5];
uchar temp_data[2]={0x00,0x00};
uchar display[5]={0x00,0x00,0x00,0x00,0x00};
uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,
0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
bit flash=0; //显示开关标记
//*位定义/*//
sbit LS2_csb_OUT=P3^6;
bit flag_1=0;
uint speed=340;
uint temp2;
uint temp;
uint count=0;
uchar high_time,low_time,flag=0,tc=2;
uchar flag_2=0;
uchar tc_say=0;
uint dis,dis_4[9]; /**********************************************************************************
** 函数名称: void delay(int ms)
** 功能描述: 延时n毫秒
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void delay(int ms)
{
while(ms--)
{
uchar i;
for(i=0;i<246;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/**********************************************************************************
** 函数名称: void delay_tms(uint t)
** 功能描述: 延时n毫秒
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void delay_tms(uint t)
{
uchar k;
while(t--)
{
for(k=0; k<125; k++)
{ }
}
}
/**********************************************************************************
** 函数名称: void delay_lcd(int ms)
** 功能描述: 延时函数200us
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void delay_lcd(int ms)
{
uchar t;
while(ms--)
{
for(t=0; t<20; t++) ;
}
}
/**********************************************************************************
** 函数名称: void delay_nms(uint ms)
** 功能描述: 延时n个ms函数
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void delay_nms(uint ms) //delay ms function
{
uchar i;
while(ms--)
{
for(i = 0; i < 123; i++);
}
}
/**********************************************************************************
** 函数名称: void delay100us()
** 功能描述: 延时100us函数
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void delay100us()
{
uchar j;
for(j=50;j>0;j--);
}
void Delay_1(uint num) //延时函数
{
while( --num );
}
//*函数名:Init_DS18B20
//功能:DS18B20初始化*//
/**********************************************************************************
** 函数名称: Init_DS18B20(void)
** 功能描述: DS18B20初始化
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
uchar Init_DS18B20(void)//初始化ds1820
{
DS18B20_DQ_OUT = 1; //DS18B20_DQ复位
Delay_1(8); //稍做延时
DS18B20_DQ_OUT = 0; //单片机将DS18B20_DQ拉低
Delay_1(90); //精确延时 大于 480us
DS18B20_DQ_OUT = 1; //拉高总线
Delay_1(8);
presence = DS18B20_DQ_OUT; //如果=0则初始化成功 =1则初始化失败
Delay_1(100);
DS18B20_DQ_OUT = 1;
return(presence); //返回信号,0=presence,1= no presence
}
/**********************************************************************************
** 函数名称: ReadOneChar(void)
** 功能描述: 从18B20中读一个字节数据
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
ReadOneChar(void)//读一个字节
{
unsigned char i = 0;
unsigned char LCD_RW_OUT = 0;
for (i = 8; i > 0; i--)
{
DS18B20_DQ_OUT = 0; // 给脉冲信号
LCD_RW_OUT >>= 1;
DS18B20_DQ_OUT = 1; // 给脉冲信号
if(DS18B20_DQ_OUT)
LCD_RW_OUT |= 0x80;
Delay_1(4);
}
return (LCD_RW_OUT);
}
/**********************************************************************************
** 函数名称: WriteOneChar(uchar DAT)
** 功能描述: 写入一个字节数据
** 输 入: DAT(送入的数字)
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void WriteOneChar(uchar DAT)//写一个字节
{
unsigned char i = 0;
for (i = 8; i > 0; i--)
{
DS18B20_DQ_OUT = 0;
DS18B20_DQ_OUT = DAT&0x01;
Delay_1(5);
DS18B20_DQ_OUT = 1;
DAT>>=1;
}
}
/**********************************************************************************
** 函数名称: Read_Temperature(void)
** 功能描述: 读取温度
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void Read_Temperature(void) //读取温度
{
Init_DS18B20();
if(presence==1)
{
flash=1; //DS18B20不正常
}
else
{
flash=0;
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器
temp_data[0] = ReadOneChar(); //温度低8位
temp_data[1] = ReadOneChar(); //温度高8位
}
}
/**********************************************************************************
** 函数名称: void temp_all(void)
** 功能描述: 进行温度补偿
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void temp_all()
{
Read_Temperature();
display[4]=temp_data[0]&0x0f;
display[0]=ditab[display[4]]; //查表得小数位的值
display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//温度整数值
display[3]=display[4]/100;
display[1]=display[4]%100;
display[2]=display[1]/10;
display[1]=display[1]%10;
if(display[4]>50) //温度高于50度,则不修正
{
flash=1; //表示测试的温度不正常
}
//*if((flash==0)&&(flag_1 == 0))
//{
// Disp_Temperature();
//}*/
if(flash==0) //温度传感器正常检测到温度并温度小于50度
{
speed=(uint)(331+(display[4]*61+display[0]*6+45)/100);//声音的速度加上温度因素
}
}
/**********************************************************************************
** 函数名称: uint Distance_count()
** 功能描述: 距离计算函数
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void Distance_count()
{
float temp1;
ulong tt;
temp2 = high_time*256+low_time;
temp = high_time*256+low_time;
tt = (ulong)temp*344 ;
temp1 = (float)(tt/2000.0);
temp = (uint)(temp1);
temp = (uint)(temp1+0.5);
// return temp;
}
/**********************************************************************************
** 函数名称: uint do_s(uint dis_1)
** 功能描述: 距离补偿函数
** 输 入: uint dis_1
** 输 出: uint dis_1
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
uint do_s(uint dis_1)
{
uchar n;
if((dis_1>70)&(dis_1<100))
{
n = dis_1/10;
switch(n)
{
case 7:dis_1-=40;break;
case 8:dis_1-=22;break;
case 9:dis_1-=26;break;
}
return(dis_1);
}
else
{
n = dis_1/100;
switch(n)
{
case 1:dis_1-=43;break;
case 2:dis_1-=42;break;
case 3:dis_1-=34;break;
case 4:dis_1-=30;break;
case 5:dis_1-=32;break;
case 6:dis_1-=31;break;
case 7:dis_1-=28;break;
case 8:dis_1-=29;break;
case 9:dis_1-=34;break;
case 10:dis_1-=34;break;
case 11:dis_1-=34;break;
case 12:dis_1-=35;break;
case 13:dis_1-=30;break;
case 14:dis_1-=35;break;
case 15:dis_1-=46;break;
case 16:dis_1-=46;break;
case 17:dis_1-=39;break;
case 18:dis_1-=36;break;
case 19:dis_1-=37;break;
case 20:dis_1-=32;break;
case 21:dis_1-=33;break;
case 22:dis_1-=34;break;
case 23:dis_1-=38;break;
case 24:dis_1-=40;break;
case 25:dis_1-=35;break;
case 26:dis_1-=35;break;
case 27:dis_1-=37;break;
case 28:dis_1-=62;break;
case 29:dis_1-=64;break;
case 30:dis_1-=68;break;
case 31:dis_1-=64;break;
case 32:dis_1-=256;break;
case 33:dis_1-=262;break;
case 34:dis_1-=268;break;
case 35:dis_1-=271;break;
case 36:dis_1-=282;break;
case 37:dis_1-=290;break;
case 38:dis_1-=302;break;
case 39:dis_1-=332;break;
case 40:dis_1-=352;break;
case 41:dis_1-=350;break;
case 42:dis_1-=367;break;
case 43:dis_1-=285;break;
case 44:dis_1-=350;break;
case 45:dis_1-=290;break;
case 46:dis_1-=295;break;
case 47:dis_1-=295;break;
case 48:dis_1-=374;break;
case 49:dis_1-=395;break;
case 50:dis_1-=395;break;
case 51:dis_1-=405;break;
case 52:dis_1-=425;break;
case 53:dis_1-=394;break;
case 54:dis_1-=395;break;
case 55:dis_1-=495;break;
}
return(dis_1);
}
}
/**********************************************************************************
** 函数名称: void tran(),void tran1(),void tran2()
** 功能描述: 超声波的发射
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void tran()
{
uchar i;
TH0=0;
TL0=0;
TR0=1;
for(i=4;i>0;i--)
{
LS2_csb_OUT=!LS2_csb_OUT;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
}
LS2_csb_OUT=1;
delay_ms(1);
EX1=1;
delay_ms(30);
if(flag==1)
{
Distance_count();
dis=temp;
flag=0;
}
else dis=0;
}
/**********************************************************************************
** 函数名称: void tran(),void tran1(),void tran2()
** 功能描述: 超声波的发射
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void tran1()
{
uchar i;
TH0=0;
TL0=0;
TR0=1;
for(i=20;i>0;i--)
{
LS2_csb_OUT=!LS2_csb_OUT;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
}
LS2_csb_OUT=1;
delay_ms(2);
EX1=1;
delay_ms(50);
if(flag==1)
{
Distance_count();
dis = temp;
flag=0;
}
else dis=0;
}
/**********************************************************************************
** 函数名称: void tran(),void tran1(),void tran2()
** 功能描述: 超声波的发射
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void tran2()
{
uchar i;
TH0=0;
TL0=0;
TR0=1;
for(i=16;i>0;i--)
{
LS2_csb_OUT=!LS2_csb_OUT;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
}
LS2_csb_OUT=1;
delay_ms(20);
EX1=1;
delay_ms(150);
if(flag==1)
{
Distance_count();
dis=temp;
flag=0;
}
else
{
dis=0;
}
}
/**********************************************************************************
** 函数名称: void fit_1(void)
** 功能描述: 取最大值
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void fit_1(void)
{
uint h;
uchar m,k,p;
for(m=0;m<7;m++) //以下语句为冒泡法排序
{
for(k=0;k<=8-m;k++)
{
if(dis_4[k]>dis_4[k+1])
{
h=dis_4[k];
dis_4[k]=dis_4[k+1];
dis_4[k+1]=h;
}
}
}
dis =(dis_4[3]+dis_4[4]+dis_4[5])/3;
p=0;
}
/**********************************************************************************
** 函数名称: void send( char B )
** 功能描述: 串口发送程序
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void send( char B ) //发送一个字节
{
SBUF=B;
while(!TI);
TI=0;
}
/**********************************************************************************
** 函数名称: void USART_init(void)
** 功能描述: 播放“测量距离"
** 输 入: uint dis_say(测得的距离)
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void USART_init(void) //串口的初始化
{
TH1=0xfd;
TL1=0xfd;
TR1=1;
SM0=0;
SM1=1;
REN=1;
}
/**********************************************************************************
** 函数名称: void main(void)
** 功能描述: 主函数
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void main(void)
{
unsigned char i,j,TEST;
P0 = 0xff;
P1 = 0xff;
P2 = 0xff;
TMOD=0x01;
TH0=0;
TL0=0;
EA=1;
IE=0x80;
IT1=0;
USART_init();
while(1)
{
if(tc_say==4)
{
temp_all();
tc_say=0;
}
tc_say++;
for(i=0;i<9;i++)
{
IE=0x80;
tran1();
dis= do_s(dis);
dis_4=dis;
}
fit_1();
Send[2] = dis>>8;
Send[3] = dis;
if( flag == 1 )
{
ES=0;
i=0;
Send[0] = temp_data[0];
Send[1] = temp_data[1];
TEST = Send[0];
for(i = 1; i < 4;i ++)
{
TEST = TEST&Send; //这是发送的数据取&得到的数据作为第八位,也就是吴鉴鹰定义的检验位
}
Send[4] = TEST;
for(i=0;i<4;i++)
{
send(Send); //发送数据
}
//Num=0;
flag=0;
ES=1;
}
/*if(dis4000) time=time-1000;
else
{
if((time-dis)<2500) time=dis;
else time=time-100;
}
}
else*/
/*dis_all(dis);
dis=0;
lcd_pos(1,6);
for(j=0;j<4;j++)
write(1,space4[j]);
lcd_pos(1,6);
for(j=0;j<4;j++)
{
write(1,point4[j]);
delay(100);
}*/
}
}
/**********************************************************************************
** 函数名称: void TT() interrupt 2
** 功能描述: 中断,产生脉冲
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void TT() interrupt 2
{
TR0=0;
ET1=0;
flag=1;
high_time = TH0;
low_time = TL0;
TR0=0;
}
/**********************************************************************************
** 函数名称: 从机程序
** 功能描述: LCD12864的显示,语音播报模块的启动
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
//*包含头文件*//
#include
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define ufloat unsigned float
#define ulong unsigned long
#define NOP _nop_();_nop_();_nop_()
#define nop _nop_()
//*常量定义*//
#define KEY_circle_IN 0xf2//循环播放
#define KEY_stopplay_IN 0xfe//停止播放
#define adjust_volice_0 0xe0//调节音量1
#define adjust_volice_1 0xe1//调节音量2
#define adjust_volice_2 0xe2//调节音量3
#define adjust_volice_3 0xe3//调节音量4
#define adjust_volice_4 0xe4//调节音量5
#define adjust_volice_5 0xe5//调节音量6
#define adjust_volice_6 0xe6//调节音量7
#define adjust_volice_7 0xe7//调节音量8
uchar vo_vo=0xe7;
uchar Num;
uchar flag_2;
uchar flag;
//*程序功能:ST7920控制芯片(汉字库),串口模式。12864 图片与文字显示*//
uchar code DIS1[] = {"超声波测距中...."};
uchar code DIS3[] = {"距障碍物: . m"};
uchar code DIS4[] = {"测距情况: 安全 "};
uchar code DIS5[] = {"测距情况: 请保持"};
uchar code DIS6[] = {"测距情况: 危险!!"};
uchar code DIS8[] = {" "};
uchar code DIS9[] = {"超声波倒车测距仪"};
uchar code DIS10[]= {" V1.0 2008.12.4 "};
uchar point4[];
uchar space4[];
unsigned int dis;
unsigned char DIS_receive_data[3];
unsigned char display_TEMP_DATA[5]={0x00,0x00,0x00,0x00,0x00};
unsigned char dist_test_DATA[5]={0x00,0x00,0x00,0x00,0x00};
//*位定义*//
sbit LCD_RST_OUT = P1^4; //LCDLCD_RST_OUT
sbit LCD_RS_OUT = P1^1;//片选端 RS
sbit LCD_CLK_OUT = P1^2;//时钟 SLCD_CLK_OUT
sbit LCD_RW_OUT = P1^3;//数据位 RW
sbit WT_busy_OUT = P1^0;//忙信号
sbit LED_green_OUT=P2^4;
sbit LED_yellow_OUT=P2^5;
sbit LED_red_OUT=P2^5;
/**********************************************************************************
** 函数名称: void delay_nms(uint ms)
** 功能描述: 延时n个ms函数
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void delay_nms(uint ms) //delay ms function
{
uchar i;
while(ms--)
{
for(i = 0; i < 123; i++);
}
}
/**********************************************************************************
** 函数名称: void delay(int ms)
** 功能描述: 延时函数n毫秒
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void delay(int ms)
{
while(ms--)
{
uchar i;
for(i=0;i<246;i++)
{
_nop_();
_nop_(); _nop_();
_nop_();
}
}
}
/**********************************************************************************
** 函数名称: void delay_lcd(int ms)
** 功能描述: 延时函数200us
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void delay_lcd(int ms)
{
uchar t;
while(ms--)
{
for(t=0; t<20; t++) ;
}
}
/**********************************************************************************
** 函数名称: void sendbyte(uchar bbyte)
** 功能描述: 向LCD12864液晶数据位发送一个字节
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void sendbyte(uchar bbyte)
{
uchar i;
for(i=0;i<8;i++)
{
LCD_RW_OUT = bbyte&0x80; //取出最高位
LCD_CLK_OUT = 1;
_nop_();
_nop_();
LCD_CLK_OUT=0;
bbyte<<=1; //左移
}
}
/**********************************************************************************
** 函数名称: void write(bit start, uchar ddata)
** 功能描述: 向LCD12864液晶写指令或数据函数
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void write(bit start, uchar ddata)
{
uchar start_data,Hdata,Ldata;
if(start==0) //11111,(0),(0),0
{
start_data=0xf8; //写指令
}
else //11111,(0),(1),0
{
start_data=0xfa; //写数据
} //
// //Hdata = ddata & 0xf0; //取高四位 Hdata = ddata&0xf0;
Ldata = (ddata<<4)&0xf0; //取低四位
sendbyte(start_data); //发送起始信号
delay_lcd(1); //延时
sendbyte(Hdata); //发送高四位
delay_lcd(1); //延时
sendbyte(Ldata); //发送低四位
delay_lcd(1); //延时
}
回复
| 有奖活动 | |
|---|---|
| 硬核工程师专属补给计划——填盲盒 | |
| “我踩过的那些坑”主题活动——第002期 | |
| 【EEPW电子工程师创研计划】技术变现通道已开启~ | |
| 发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
| 【EEPW在线】E起听工程师的声音! | |
| 高校联络员开始招募啦!有惊喜!! | |
| 【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
| 送您一块开发板,2025年“我要开发板活动”又开始了! | |
我要赚赏金
