版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hhye_l/article/details/50262717
1. 模块(OUT脚不知有什么用)
2. 工作原理
3. 时序图
4. 计算公式
5. 51测试源码,串口显示
/**********************************************************************************
* 功能:HY-SRF05超声波测距模块测试,通过串口打印
* 处理器:STC89C52RC
* 晶振:11.0592
* 编译环境:Keil uVision4
* 时间:2015-12-10
* 作者:ly
* 备注:Trig --- P1_0
* Echo --- 外部中断0(P3_2)
* OUT ---
* Vcc --- VCC
* GND --- GND
**********************************************************************************/
#include <reg52.h>
#include <stdio.h> //sprintf
#include <string.h> //strlen
#include <intrins.h> //_nop_
#define uint unsigned int
#define uchar unsigned char
sbit TX = P3^1;
sbit Trig = P1^0;
int time; //计算回响信号脉冲宽度
/****************************** 初始化函数 *****************************************/
//外部中断0初始化(P3_2)
void int0_init(void)
{
IE0 = 0; //外部中断0标志位清0
IT0 = 1; //外部中断0下降沿触发
EX0 = 1; //外部中断0允许
}
//定时器0初始化
void time0_init(void)
{
TMOD |= 0x09; //0000 1001: GATE门控开,只有 TRx==1 && INTx==1 才可启动T0,T0定时方式1(16位)
TH0 = 0;
TL0 = 0;
TF0 = 0; //T0标志位清0
ET0 = 1; //T0中断允许
TR0 = 1; //T0工作允许
}
//串口初始化
void uart_init(void)
{
SCON = 0x40; //0100 0000:串行方式1
TMOD |= 0x20; //T1定时方式2(8位自动装入)
TH1 = 0xFD; TL1 = 0xFD; //波特率:9600
ES = 0; //串口中断禁止
TR1 = 1; //T1启动
}
void init(void)
{
EA = 0; //总中断禁止
Trig = 0;
uart_init();
time0_init();
int0_init();
EA = 1; //总中断允许
}
/************************************************************************************/
void delay15us(void)
{
_nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
}
void delay15ms(void)
{
int i;
for (i = 0; i < 1000; i++)
delay15us();
}
void uart_send_char(uchar ch) //串口发送一个Byte
{
SBUF = ch;
while (!TI);
TI = 0;
}
void uart_send_string(uchar str[], uint len) //串口发送字符串
{
int i;
for (i = 0; i < len; i++)
uart_send_char(str[i]);
}
/* 主函数 */
void main(void)
{
int i;
float distance; //距离
uchar display[20]; //串口显示距离
init();
while (1)
{
//建议测量周期60ms以上,以防止发射信号对回响信号的影响
for (i = 0; i < 4; i++)
delay15ms();
//发送触发信号(10us以上TTL脉冲),如果检测到回响,Echo(P3^2)将拉高,则T0开始计时
Trig = 1;
delay15us();
Trig = 0;
//等待Echo(P3^2)下降沿到来(回响信号脉冲)触发外部中断
time = 0; i = 0;
while (time==0 && i<=65536) //直到time被中断计算出时间或者被标记计时溢出或者i超时
i++; //防止死循环
if (i > 65536) //一直监测不到回响,Echo(P3^2)没有拉高,超时
{
uart_send_string("time out", 8);
uart_send_char(0x0A); //换行/新行
uart_send_char(0x0D); //回车
continue;
}
if (time == -1) //计时溢出
{
uart_send_string("T0 overflow", 11);
uart_send_char(0x0A); //换行/新行
uart_send_char(0x0D); //回车
}
else
{
distance = time / 58.0; //公式:uS / 58 = 厘米
sprintf(display, "%f CM", distance);
uart_send_string(display, strlen(display));
uart_send_char(0x0A); //换行/新行
uart_send_char(0x0D); //回车
}
}
}
/*************************** 中断处理 ******************************/
// 外部中断0处理
void int0() interrupt 0
{
EA = 0; //总中断禁止
time = TH0 * 256 + TL0; //回响时间
TH0 = 0;
TL0 = 0;
EA = 1; //总中断允许
}
// 定时器0中断处理
void time0() interrupt 1
{
//进入到这里,说明计时溢出
EA = 0; //总中断禁止
TH0 = 0;
TL0 = 0;
time = -1;
EA = 1; //总中断允许
}
/********************************************************************/