HY-SRF05超聲波測距
阿新 • • 發佈:2018-12-04
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; //總中斷允許
}
/********************************************************************/