制作51单片机超声波测距仪时,程序设计及试工作是一项重要内容,所设计的程序51单片机超声波测距程序只是在编译环境下通过编译,消除编程工作中产生的语法错误后,直接将程序写入单片机中与硬件一起进行联调,如果这时硬件设计制作是正确的还好说,只需要进行软件的调试修改,烧写到硬件环境中验证直到达到设计要求即可,但这个工作也是需要反复不停地修改程序并烧录到硬件单片机中进行调试,但如果说硬设计、制作及程序设计都存在问题,整个调试工作就显得无从下手,给软件调试、硬件故障排出带来非常大的困难,增加不少工作量,甚至造成整个超声波测距系统设计制作的失败。有好的解决办法吗?回答是肯定的,就是程序仿真,编译通过的程序,在Proteus环境下,按设计的硬件原理图,把仿真图画好,调入程序在Proteus仿真环境下进行程序的仿真,来验证程序设计的正确性及各项功能是否达到设计要求,在仿真环境下完成程序的调试工作。通过仿真调试满意后的程序,再烧写到硬件环境下调试,这时,如果硬件工作正常,可以进一步的验证程序的功能及正确性,如果工作不正常,这时可排出软件设计的问题,集中精力排出硬件设计、制作的问题,有针对性的排出,从而可提高设计制作过程中的效率,大大减轻制作工作量,51单片机超声波测距仪制作成功率可以得到100%的保证。
一、51单片机超声波测距仿真如何进行呢
Proteus仿真软件内没有超声波仿真模型,是不是超声波测距仿真就不能进行了,答案是否定的。超声波测距仿真的方法归纳起来,有一下:
1、 利用按键直接入单片机超声波接收判断端口,人工加载一个信号到单片机端口上,模拟超声波测距接收电路收到超声波回波信号,让单片机停止时间测量过程,从而对超声波测距进行一个最最简单的仿真。这种方式的仿真,仿真效果不直观,不理想,不能得到想要的准确的仿真显示的结果值。需要人为手工不止的反复按下按键开关。
2、 利用延时方法进行仿真。这样的仿真,电子乐屋 上制作得最好。仿真原理是这样的,利用一个延时电路代替超声波发送接收电路,模拟超声波头发送出超声波后碰到被测物体返射回回波被超声波接收头接收到波的这一时间过程,从而实现超声波的测距的仿真。使用延时电路的方式比较多,可用模拟电路,也可以用单片机。但最简单的方法就是利用555时基电路搭建一个延时电路,延时时长可调,由单片机超声波发端发送一超声波信号触发,延时时长由可调延地电路决定,时长0.2毫秒到30毫秒,这样可实现仿真距离0.0 2-5米可调。比较简单就是555电路搭的仿真电路,但这种电路不形象,好一些的就是利用Proteus软件,对仿真元件进行封装,这样仿真时比较直观形象。仿真元件的封装这里就不进行讨论。这种仿真的方式,可以通过调节RV1可调电阻的阻值仿真出不同的距离值,方便仿真时仿真进行如报警功能的仿真,整个仿真过程不象用按键开关仿真哪样需要人为的进行按键操作,只需要根据需要调节可调电阻就行。
51单片机超声波测距仿真截图中可以看到,黄色的波形是单片机送给HC-SR04模块TRIG端口高电平信号,绿色的是HC-SR04模块ECHO端送出的高电平,高电平持续的时间就是超声波从发射到返回的时间,图中显示的是1.65毫秒,按照计算公式S=340×t/2计算距离,计算时把速度的单位换算成厘米/微秒。按照图中时间计算的距离值为:S=0.034×(14.70×1000)/2=249.9厘米。仿真时用示波器测量到时间换算成距离与显示基本一至。
下面是经过本次仿真运行的程序,该程序同时也写进单片机超声波测距仪硬件中验证过了。
#define uint unsigned int
#define uchar unsigned char
sbit rs=P2^0; //1602的数据/指令选择控制线
sbit rw=P2^1; //1602的读写控制线
sbit en=P2^2; //1602的使能控制线
sbit trig=P2^5; //超声波测距模块Trig
sbit echo=P3^2; //超声波测距模块Echo
bit flag1; //触发信号标志位//
uchar count; //中断累加变量
long int distance; //测量所得距离
unsigned char code table[ ]={"0123456789"}; //定义字符数组显示数字
void delay(uint n)
{
uint x,y;
for(x=n;x>0;x--)
for(y=110;y>0;y--);
}
void delayt(uint x)
{
uchar j;
while(x-- > 0)
{
for(j = 0;j < 125;j++)
{
;
}
}
}
void lcd_wcom(uchar com)
{
rs=0; //选择指令寄存器
rw=0; //选择写
P0=com; //把命令字送入P0
delay(5); //延时一小会儿,让1602准备接收数据
en=1; //使能线电平变化,命令送入1602的8位数据口,这点非常重要
en=0;
}
void lcd_wdat(uchar dat)
{
rs=1; //选择数据寄存器
rw=0; //选择写
P0=dat; //把要显示的数据送入P0
delay(5); //延时一小会儿,让1602准备接收数据,也就是检测忙信号,这点非常重要。
en=1; //使能线电平变化,数据送入1602的8位数据口
en=0;
}
void lcd_init()
{
lcd_wcom(0x38); //8位数据,双列,5*7字形 ,用到功能设定指令
lcd_wcom(0x0c); //开启显示屏,关光标,光标不闪烁,用到显示开关控制指令
lcd_wcom(0x06); //显示地址递增,即写一个数据后,显示位置右移一位,用到了写入模式设置指令
lcd_wcom(0x01); //清屏,用到了清屏指令
}
void lcd_xianshi()
{
lcd_wcom(0x80+0x40);
lcd_wdat('D');
lcd_wdat('i');
lcd_wdat('s');
lcd_wdat('t');
lcd_wdat('a');
lcd_wdat('n');
lcd_wdat('c');
lcd_wdat('e');
lcd_wdat(':');
lcd_wcom(0x80+0x4c);
lcd_wdat('.');
lcd_wcom(0x80+0x4e);//单位是厘米//
lcd_wdat('c');
lcd_wdat('m');
}
void init_t0()
{
TMOD=0x01;
TL0=0x66;
TH0=0xfc; //1ms
ET0=1;
EA=1;
}
void trigger()
{
trig=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
trig=0;
}
void init_measuring()
{
trig=0;
echo=1;
count=0;
}
void measuring()
{
uchar l;
uint h;
TR0 = 1;
while(echo==1)
{
;
}
TR0 = 0;
l = TL0;
h = TH0;
distance =h*256+l;//计算总时间,单位是微秒
TL0 =0;
TH0 =0;
delayt(30);
distance = 3400* distance / 20000;//原始为:(0.34毫米/us)*时间/2//
}
void display(uint x)
{
uchar qian,bai,shi,ge;
qian=x/1000;
bai=(x/100);
shi=(x/10);
ge=x;
lcd_wcom(0x80+0x49);//单位是厘米//
lcd_wdat(table[qian]);
lcd_wdat(table[bai]);
lcd_wdat(table[shi]);
lcd_wcom(0x80+0x4d);
lcd_wdat(table[ge]);
}
void main()
{ lcd_init(); //液晶初始化
init_t0(); //定时器0初始化
init_measuring(); //超声波相应端口初始化
while(1)
{
lcd_xianshi(); //液晶显示特定字符
trigger(); //触发超声波启动
while(echo==0) //等待回声
{
;
}
measuring(); //进行距离测量
display(distance); //对测量结果进行显示
init_measuring(); //超声波相应端口初始化
delayt(600); //每次测量间隔60ms
}
}
//……………………………………………中断服务函数…………………………………………………//
void T_0()interrupt 1
{
TF0 = 0;
TL0 = 0x66;
TH0 = 0xfc;
count++;
if(count==18)
{
TR0 =0;
TL0 = 0x66;
TH0 = 0xfc;
count = 0;
}
}
上一篇:STC89C52RC单片机超声波测距程序
下一篇:51单片机1602显示的超声波测距源程序
推荐阅读最新更新时间:2024-03-16 15:35