HC-SR04超声波模块程序原理和Proteus ISIS仿真

一、原理介绍

遇到障碍物,能够感应做出反应,超声波可以作为一种测量手段,超声波在固体液体气体中传播良好,气体中速度约为340m/s。如果知道时间,那么就可以计算出距离。利用宏晶STC89C52计算超声波模块HC-SR04反馈信号高电平的时间,换算成距离显示在数码管上(这里用573和138组合的共阴极数码管显示电路)

STC89C52是国产宏晶的一块8位寄存器芯片,IO准双向口,可以输入输出,七个中断源,六个中断通道,有ISP系统,支持USB串口下载,8KB系统可编程下载Flash(程序储存空间),512BRAM(数据储存空间),27个特殊功能寄存器。

HC-SR04超声波模块,模块四个引脚触发信号Trig,回声信号Echo,供电VCC和GND,测量周期60ms以上。当给Trig一个10us以上的脉冲时,HC-SR04内部自动循环发出8个40KHz的脉冲,Echo刚收到回波时置一(超出一定范围收到的信号不够HC-SR04置一定时器不计数),单片机定时器开始计数,直到Echo没有收到信号置零,记了TH+TL次机器周期,一个机器周期需要12个振荡周期,由此时间就可以计算出来,再用时间X速度就可以计算出距离S。

数码管有七段的,十四段的,十六段的,这里用的八位共阴极七段数码管。共阴极数码管就是共地,a,b,c,d,e,f,g,h对应哪一段输入高电平,哪一段LED亮,所以特定的组合可以显示0~9数字,所以有共阴极段码表,一组数组,显示几就对P0端口赋值对应这个数值的下标的数组元素。

HC-SR04收发信号,STC89C52计算结果,数码管显示,74HC573负责数码管的段选,74LS138负责数码管的位选。

二、仿真测试

完整的电路仿真图如图一所示,首先打开Protues ISIS新建一个空白文件,从库中拾取元件,选择IC芯片AT89C52,第一步取两个20PF~33PF的电容一个晶振和个地信号组成晶振电路,第二步给P0口上拉一的330欧的排阻,第三步加入两个四位共阴极(CC)七段数码管,第四步加一个74HC573进行段选,连接数码管的段选引脚,第五步加入一个74LS138,三位地址线控制八位位选,连接上数码管的位选位,第六步构造一个HC-SR04超声波传感器模块,并根据程序连好线,第七步加入一个信号源和一个示波器,方便模拟测试,电路连接完成。


图一 仿真电路

激励源连接在HC-SR04模块的Echo脚上,进行如图二的设置。

图二 激励源设置

示波器分别接上HC-SR04TrigEcho脚,双击主控芯片,打开程序生成的hex文件,点击运行,得到如图三的结果。

图三 仿真结果

首先黄色线是Trig,放大看了下,如图四。单位5us,由图可见四格多,这个触发信号高电平20几us,符合资料中Trig触发信号高电平要保持10us以上。其次水平滚轮每20代表一格即一个单位,结合图三和图五,两个发射信号水平滚轮数间隔16000左右,800格左右,单位为1ms,即800ms,符合程序中发射间隔800ms。最后数码管显示34,给Echo的方波200hz,占空比40%,即高电平2ms,12M晶振的单片机一个机器周期1us,定时器需要计数2000次,所以TH+TL=2000,根据公式S=(Th+TL)X1.7/100=34cm。综上所述,仿真程序设计没有问题。


图四 触发信号保持时间

图五 触发信号间隔时间

三、程序设计

   
#include "reg51.h"
#include <intrins.h>

//常变量定义:
code unsigned char table[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//表:共阴数码管 0-9 -
unsigned int  time=0;
unsigned int  timer=0;
unsigned long S=0;
bit flag =0;


unsigned char l_disbuff[4]={ 0,0,0,0};//显示缓冲
unsigned char l_posit=1; //位选择


//引脚定义:
//sbit SMG_q = P2^2; //定义数码管阳级控制脚(千位)本例程只用到三位数码管
sbit SMG_b = P2^2; //定义数码管阳级控制脚(百位)
sbit SMG_s = P2^3; //定义数码管阳级控制脚(十位)
sbit SMG_g = P2^4; //定义数码管阳级控制脚(个位)


sbit RX = P2^1; //模块引脚
sbit TX = P2^0;
/********************************************************/


//显示函数,参数为显示内容
void display()
{
P0=0X00; //
switch(l_posit){
case 0: //选择千位数码管,关闭其它位
//SMG_q=0;
SMG_b=1;
SMG_s=1;
SMG_g=1;
P0=table[l_disbuff[0]];
break;
case 1: //选择百位数码管,关闭其它位
//SMG_q=1;
SMG_b=0;
SMG_s=1;
SMG_g=1;
P0=table[l_disbuff[1]];//加入小数点要与一下
break;
case 2: //选择十位数码管,关闭其它位
//SMG_q=1;
SMG_b=1;
SMG_s=0;
SMG_g=1;
P0=table[l_disbuff[2]];
break;
case 3: //选择个位数码管,关闭其它位
//SMG_q=1;
SMG_b=0;
SMG_s=0;
SMG_g=1;
P0=table[l_disbuff[3]];
break;
}
l_posit++;
if(l_posit>3)
l_posit=0;

}




/********************************************************/
void Count(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;

S=(time*1.7)/100;     //算出来是CM
if((S>=700)||flag==1) //超出测量范围显示“-”
{  
 flag=0;
 l_disbuff[1]=10;   //“-”
 l_disbuff[2]=10;   //“-”
 l_disbuff[3]=10;   //“-”
}
else
{
 l_disbuff[1]=S%1000/100;
 l_disbuff[2]=S%1000%100/10;
 l_disbuff[3]=S%1000%10 %10;
}
}
/********************************************************/
void zd0() interrupt 1 //T0中断用来计数器溢出,超过测距范围
{
    flag=1; //中断溢出标志
}
/********************************************************/
void  zd3()  interrupt 3 //T1中断用来扫描数码管和计800MS启动模块
{
TH1=0xf8;
TL1=0x30;
display();
timer++;
if(timer>=400)
{
 timer=0;
 TX=1;        //800MS  启动一次模块
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_();
 _nop_(); 
 _nop_(); 
 _nop_(); 
 _nop_();
 TX=0;

}
/*********************************************************/


void  main(  void  )
{  
    TMOD=0x11;   //设T0,T1为方式1
TH0=0;
TL0=0;          
TH1=0xf8;   //2MS定时
TL1=0x30;
ET0=1;             //允许T0中断
ET1=1;   //允许T1中断
TR1=1;   //开启定时器
EA=1;   //开启总中断


while(1)
{
while(!RX); //当RX为零时等待
TR0=1;    //开启计数
while(RX); //当RX为1计数并等待
TR0=0; //关闭计数
     Count(); //计算
}
}

                

四、实物测试


  • 29
    点赞
  • 209
    收藏
    觉得还不错? 一键收藏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值