测距原理
- 超声波发射模块向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。
计算公式
- 距离 = 声速 × 发出超声波到接收返回的时间/2
- 因为超声波在空气中的传播速度受温度影响。声波在空气中的传播速度与温度的关系是:
在20摄氏度时,声速V = 332 + 0.607t (m/s) - 利用超声波进行距离测量,要求精度一般都不高,取20摄氏度时候的声速344M/S进行计算,再进行适当的补偿就可以。所以,其计算公式为:
距离L = 344M/S * T / 2 = 172M/S * T 。
实现步骤
- 产生8个40KHz的超声波信号,通过TX引脚发射出去。 (产生一个40KHz的超声信号,计算得周期为25us,所以产生一个40KHz信号即是发送开始,延时12us,再停止发送,也就是一个高电平12us,一个低电平12us)
- 启动定时器,计算计数脉冲。
- 等待超声波信号返回,如果接收到反射回来的信号,RX引脚变为低电平。
- 停止定时器,读取脉冲个数,即获得时间T。
- 根据公式,L = V * T /2m,进行距离的计算。
在蓝桥杯单片机的竞赛综合平台CT107D中,超声波模块的TX引脚接到单片机的P1.0端口,RX引脚接到单片机的P1.1端口。
设计程序,进行超声波测距,最大测量范围约140cm。测量结果用cm作为显示单位,显示在数码管的最右边三位。如果测量距离超出范围,则以“F”作为标志,显示在数码管的最左边一位。
#include <STC15F2K60S2.H>
#include <absacc.h>
#include <intrins.h>
void delay_ms(int n);
void delay12us();
void show_hc(unsigned char pos, unsigned char value);
void Delay(unsigned char n);
void Display_Distance();
void send_wave();
void measure_distance();
sbit TX=P1^0; //超声波发送端
sbit RX=P1^1; //超声波接收端
unsigned char table[18]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f}; //0~F 最后两个为——和.
unsigned int distance=0; //超声波测量距离
void main()
{
XBYTE[0X8000]=0XFF;//关闭LED
XBYTE[0XA000]=0X00;//关闭蜂鸣器,继电器
while(1)
{
measure_distance();
Delay(10);
}
}
//显示超声波测的距离函数
void Display_Distance()
{
if(distance==999) //超出测量范围,显示"F"
{
show_hc(0,table[15]);
delay_ms(1);
}
else
{
show_hc(5,table[distance/100]);
delay_ms(1);
show_hc(6,table[(distance%100)/10]);
delay_ms(1);
show_hc(7,table[distance%10]);
delay_ms(1);
}
}
//发送超声波信号 产生8个40KHz信号
void send_wave()
{
unsigned char i;
for(i=0;i<8;i++)
{
TX=1;
delay12us();
TX=0;
delay12us();
}
}
//超声波测距
void measure_distance()
{
unsigned int time=0; //用于计数脉冲个数
TMOD&=0x0f; //定时器1模式0,13位,最大8192个计数脉冲
TH1=0X00;
TL1=0X00;
send_wave(); //发送超声波信号
TR1=1; //启动定时器,开始测距
while((RX==1)&&(TF1==0)); //等待接收到超声波信号返回,或者等到测量超出范围 TF1是溢出标志位,计满溢出后置1
TR1=0; //停止定时器
if(TF1==0) //正常测量范围
{
time=TH1;
time=(time<<8)|TL1; //读取定时器脉冲个数,获得时间T
distance=((time/10)*17)/100+3; //计算距离
}
else //超出测量范围,将溢出标志位置0
{
TF1=0;
distance=999;
}
}
//数码管显示增强
void Delay(unsigned char n)
{
while(n--)
{
Display_Distance();
}
}
//单个数码管显示函数
void show_hc(unsigned char pos, unsigned char value)
{
XBYTE[0xE000] = 0xFF; //消隐
XBYTE[0xC000] = 0x01 << pos; //选择数码管的位置
XBYTE[0xE000] = value; //输出数码管显示的内容
}
//延时1ms函数
void delay_ms(int n)
{
int i,j;
for(i=n;i>0;i--)
for(j=110;j>0;j--);
}
//延时12us函数
void delay12us() //@12.000MHz 延时12us
{
unsigned char i;
_nop_();
_nop_();
i = 33;
while (--i);
}