之前发过一期使用51单片机开发板完成的超声波测距。今天再发一个基于Proteus仿真的超声波测距。Proteus8.0之前的版本中都没有超声波测距这个模块,所以在Proteus7的软件中大部分超声波测距仿真都是采用的网友自制的超声波测距模块,自制的模块在仿真时交互性不是很友好,所以今天分享的仿真是基于Proteus8.8版本。文章的最后会告知如何仿真和软件的下载方式。
超声波测距模块SRF04
超声波测距模块在Proteus中的名称叫做SRF04,它的工作原理与之前文章中介绍的超声波模块工作原理一致,都是通过一个IO控制超声波模块的发射,通过另外一个IO对超声波接收端的信号进行检测,计算出超声波信号的运动时间,进而计算出模块与障碍物之间的距离。
测距原理
原理方面就不在多说了,贴一下仿真图。
Proteus仿真图
今天分享的超声波测距仿真如图所示,显示部分使用的是LCD1602,由于声波在不同温度下的传播速度不同,所以仿真中使用DS18B20对环境温度进行采集,以便实现超声波的温度补偿。
部分程序截图
检测部分程序如上图所示,程序的大致流程为显示初始化->外设初始化->检测DS18B20温度->发送超声波并启动定时器->等待声波信号返回->计算距离->判断距离是否在范围内->更新显示->进入下一个循环。
程序流程
仿真运行图
仿真运行时效果如图所示。在该仿真的基础上增加按键、蜂鸣器等外设就可以实现倒车雷达的功能。有兴趣的小伙伴可以自行下载研究。
Proteus8.8软件可以在公众号主页发送”Proteus”,系统即可自动回复对应的下载链接。
本文分享的仿真及程序可以在公众号发送”超声波测距仿真”获取相应的下载链接。
下面贴一下主程序。
#include "reg51.h"
#include <stdio.h>
#include "LCD.H"
#include "18B20.H"
#include "delay.h"
sbit csb=P2^5; //超声波发送引脚
sbit csbint=P3^2; //超声波接收引脚
unsigned char aa[]={' ',' ','D','i','s','t','a','n','c','e',':'}; //Distance
unsigned char bb[11]={' ',' ',' ',' ','.',' ',' ',' ',' ',' ',};
unsigned char cc[]={'A','.','A','A','m'};
unsigned char zf; //zf 温度正负标志位
unsigned int s,j,bgz,k;
int temp;
float temperature,csbc,wdz; //温度及温度补偿变量
void main(void)
{
TH0=0;
TL0=0; //定时器0计数器清0
TMOD=0X11; //T1,T0为16位定时器
EA=0; //关闭总中断
init(); //初始化
Init_DS18B20(); //DS18B20初始化
bb[6]=0xdf; //显示摄氏度符号
bb[7]=0x43;
LCD_Write_String(0,0,aa); //对数据进行显示
while(1)
{
temp=ReadTemperature(); //读取DS18B20温度数据
DelayMs(100); //延时100毫秒
if(temp<0) //如果温度小于0
{
temp=-(temp-1); //温度取反处理,并显示负号
zf=1;
bb[0]='-';
}
else //温度为正值
{
zf=0;
bb[0]=' ';
}
csb=0; //给超声波模块发送一个启动脉冲
_nop_();
_nop_();
_nop_(); //启动脉冲需要一定宽度
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
csb=1; //置位
ET0=1; //启动计数器T0,用以计时
TR0=1;
EA=1; //开启总中断
j=80; //延时一段时间
while(j--){}
csbint=1;
j=0;
while(csbint) //判断接收回路是否收到超声波的回波
{
j++;
if(j>=2500) //如果达到一定时间没有收到回波,则将csbint置零,退出接收回波处理程序
csbint=0;
}
TR0=0; //关闭定时器0
s=TH0*256+TL0; //读取时间数据
TH0=0; //定时器清0
TL0=0;
wdz=0.00000607*temp; //计算温度补偿值
if(zf==0)
{
csbc=0.03315+wdz; //对超声波速度进行温度补偿,温度为正值时+,温度为负值时-
}
else csbc=0.03315-wdz;
csbc=csbc/2; //
s=s*csbc-4; //速度*时间=位移
if(s<5) //测量值小于下限
{
cc[0]='-';
cc[2]='-'; //测量距离小于下限,显示---,
cc[3]='-';
}
else if(s>500) //测量值大于上限
{
cc[0]='C';
cc[2]='C'; //测量距离大于上限值,显示CCC
cc[3]='C';
}
else
{
cc[0]=s/100+'0';
cc[2]=s/10%10+'0'; //距离在范围内,显示距离数值
cc[3]=s%10+'0';
}
//显示测量的温度
bb[1]=temp/1000+0x30;
bb[2]=temp/100%10+0x30; //显示十位
bb[3]=temp%100/10+0x30; //显示个位
bb[5]=temp%10+0x30; //小数
if(zf==0)
{
if(temp<1000)
{
bb[1]=' ';
if(temp<100)
{
bb[2]=' ';
}
}
}
else
{
if(temp<1000)
{
bb[1]='-';
bb[0]=' ';
if(temp<100)
{
bb[0]=' ';
bb[1]=' ';
bb[2]='-';
}
}
}
LCD_Write_String(4,1,bb);
LCD_Write_String(11,0,cc);
}
}