藍橋杯單片機必備知識-----(9)超聲波測距
超聲波測距原理:
超聲波發射器向某一方向發射超聲波,在發射時刻的同時開始計時,超聲波在空氣中傳播,途中碰到障礙物就立即回傳來,超聲波接收器收到反射波就立即停止計時,超聲波在空氣中的傳播速度為340m/s,根據計時器記錄的時間t,就可以計算出發射點距障礙物的距離(s),即:s=340t/2 ,這就是所謂的時間差測距法,
超聲波測距的原理是利用超聲波在空氣中的傳播速度為已知,測量聲波在發射后遇到障礙物反射回來的時間,根據發射和接收的時間差計算出發射點到障礙物的實際距離,由此可見,超聲波測距原理與雷達原理是一樣的,
測距的公式表示為:L=C×T
式中L為測量的距離長度;C為超聲波在空氣中的傳播速度;T為測量距離傳播的時間差(T為發射到接收時間數值的一半),
超聲波測距主要應用于倒車提醒、建筑工地、工業現場等的距離測量,雖然目前的測距量程上能達到百米,但測量的精度往往只能達到厘米數量級,
由于超聲波易于定向發射、方向性好、強度易控制、與被測量物體不需要直接接觸的優點,是作為液體高度測量的理想手段,在精密的液位測量中需要達到毫米級的測量精度,但是目前國內的超聲波測距專用集成電路都是只有厘米級的測量精度,
核心代碼:
//切記,計算距離不使用分頻
sbit TX = P1^0; //發射引腳
sbit RX = P1^1; //接收引腳
void main(void)
{
cls();
AUXR = 0x80;
TMOD = 0x10; //配置定時器作業模式
TH0 = 0xcd;
TL0 = 0xd4;
TH1 = 0;
TL1 = 0;
TR0 = 1; //啟動定時器
EA = 1;
ET0 = 1; //打開定時器0中斷
while(1)
{
/** 100毫秒更新一次資料 */
if(s_flag)
{
s_flag = 0;
send_wave(); //發送方波信號
TR1 = 1; //啟動計時
while((RX == 1) && (TF1 == 0)); //等待收到脈沖,沒有計滿溢位
TR1 = 0; //關閉計時
//發生溢位
if(TF1 == 1)
{
TF1 = 0;
distance = 9999; //無回傳
}
else
{
/** 計算時間 */
time=TH1*256+TL1;
distance = (unsigned int)(time*0.017); //計算距離
}
TH1 = 0;
TL1 = 0;
}
}
}
//12us
void Delay12us()//@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 30;
while (--i);
}
void send_wave()//發送八段脈沖波(40Khz)
{
unsigned char i = 8;
while(i --)
{
TX = 1;
Delay12us();
TX = 0;
Delay12us();
}
}
測驗結果:

整個代碼粘貼
#include <stc15f2k60s2.h>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit TX = P1^0; //發射引腳
sbit RX = P1^1; //接收引腳
uchar tab[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff};
uchar dspbuf[] = {10,10,10,10,10,10,10,10};
uint distance,time = 0;
uchar s_flag = 0;
void display();
void load();
void Delay12us();
void send_wave();
void cls()
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 = 0x1f;
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0x00;
P2 = 0x1f;
}
void main(void)
{
cls();
AUXR = 0x80;
TMOD = 0x10; //配置定時器作業模式
TH0 = 0xcd;
TL0 = 0xd4;
TH1 = 0;
TL1 = 0;
TR0 = 1; //啟動定時器
EA = 1;
ET0 = 1; //打開定時器0中斷
while(1)
{
/** 200毫秒更新一次資料 */
if(s_flag)
{
s_flag = 0;
/** 關閉定時器0中斷:計算超聲波發送到回傳的時間 */
// ET0 = 0;
send_wave(); //發送方波信號
TR1 = 1; //啟動計時
while((RX == 1) && (TF1 == 0)); //等待收到脈沖,沒有計滿溢位
TR1 = 0; //關閉計時
//發生溢位
if(TF1 == 1)
{
TF1 = 0;
distance = 9999; //無回傳
}
else
{
/** 計算時間 */
time=TH1*256+TL1;
distance = (unsigned int)(time*0.017); //計算距離
}
TH1 = 0;
TL1 = 0;
}
}
}
//定時器0中斷服務函式
void time0() interrupt 1 //默認中斷優先級 1
{
static unsigned int intr = 0;
if(++intr == 100){s_flag = 1;intr = 0;}
display();
}
void load()
{
dspbuf[5] = distance/100;
dspbuf[6] = distance%100/10;
dspbuf[7] = distance%10;
}
void Delay12us()//@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 30;
while (--i);
}
void send_wave()//發送八段脈沖波(40Khz)
{
unsigned char i = 8;
while(i --)
{
TX = 1;
Delay12us();
TX = 0;
Delay12us();
}
}
void display()
{
static unsigned char dspcom = 0;
load();
P2 = (P2 & 0x1f) | 0xe0;
P0 = 0xff;
P2 = 0x1f;
P2 = (P2 & 0x1f) | 0xc0;
P0 = 1 << dspcom;
P2 = 0x1f;
P2 = (P2 & 0x1f) | 0xe0;
P0 = tab[dspbuf[dspcom]];
P2 = 0x1f;
if(++dspcom == 8) dspcom = 0;
}
這時好多人會有疑惑,12us延時該如何做;

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/226944.html
標籤:其他
