HC-SR04超声波模块工作原理:
(1)采用 IO 口 TRIG 触发测距,给最少10us 的高电平信号。
(2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
(3)有信号返回,通过 IO 口 ECHO 输出一个高电平,一有输出就打开定时器计时,此口变为低电平时停止计时,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;
应用领域:
机器人、避障物体测距、液位检测、公共安防、停车场检测。
传感器内部电路图:
时序图说明:
/*
hc-sr04 超声波测距模块 DEMO 程序
晶振:11.0592
接线:模块TRIG接 P1.2 ECH0 接P1.1
数码管:共阳数码管P0接数据口,P2.2 P2.1 P2.0接选通数码
*/
#include <AT89x51.H> //器件配置文件
#include <intrins.h> //51基本运算(包括_nop_空函数)
#define ECHO P1_1 //接收引脚
#define TRIG P1_2 //Trig触发引脚
unsigned int time=0; //存放定时器时间
unsigned int timer=0; //计时器
unsigned char posit=0; //定义是数码管显示
unsigned long S=0;
bit flag =0; //量程溢出标志位
unsigned char const discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff};
unsigned char const positon[3]={ 0xfe,0xfd,0xfb}; //P2口位选动态扫描
unsigned char disbuff[4] ={ 0,0,0,0,};
void Display(void);
void Conut(void);
/*************主函数********************************************/
void main( void )
{
//初始化
TMOD=0x11; //设T0为方式1,GATE=1;
TH0=0;
TL0=0;
TH1=0xf8; //2MS定时
TL1=0x30;
ET0=1; //允许T0中断
ET1=1; //允许T1中断
TR1=1; //开启定时器
EA=1; //开启总中断
while(1)
{
while(!ECHO); //当ECHO为零时等待
TR0=1; //开启计数
while(ECHO); //当ECHO为1计数并等待
TR0=0; //关闭计数
Conut(); //计算
}
}
/**********************扫描数码管*********************************/
void Display(void) //扫描数码管
{
if(posit==0) //如果是第一个位置那么显示小数点
{P0 = (discode[disbuff[posit]]) & 0x7f;} //清除Bit7位 //&按位与,&&逻辑与即全真为真
else //不是第一个位置就不显示小数点
{P0 = discode[disbuff[posit]];} //赋段码的值
P2 = positon[posit]; //赋位码的值
if(++posit>=3) //动态扫描,位置的值在0~3之间循环
//++posit:使用posit之前先递增它
posit = 0;
}
/********************************************************/
void Conut(void)
{
time=TH0*256+TL0; //这个就是你的定时器的初值是零,然后你的ECHO=1后就开启定时器
TH0=0; //等待接收信号,ECHO=0时,计时结束
TL0=0;
S=(time*1.7)/100; //算出来是CM
if((S>=700)||flag==1) //超出测量范围显示“-”
{
flag=0;
disbuff[0]=10; //显示横杠
disbuff[1]=10; // " - "
disbuff[2]=10; // " - "
}
else
{
disbuff[0]=S%1000/100;
disbuff[1]=S%1000%100/10;
disbuff[2]=S%1000%10 %10;
}
}
/********************* T0中断用来计数器溢出,超过测距范围***********************************/
void zd0() interrupt 1
{
flag=1; //中断溢出标志
}
/******************* T1中断用来扫描数码管和计800MS启动模块*************************************/
void zd3() interrupt 3
{
TH1=0xf8;
TL1=0x30;
Display();
timer++;
if(timer>=400) //计数超过400次,即800ms,启动模块
{
timer=0;
TRIG=1;
_nop_(); //空函数,发送10us以上高电平给Trig
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TRIG=0;
}
}