【蓝桥杯16】——超声波测距

测距原理
  1. 超声波发射模块向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。
计算公式
  1. 距离 = 声速 × 发出超声波到接收返回的时间/2
  2. 因为超声波在空气中的传播速度受温度影响。声波在空气中的传播速度与温度的关系是:
    在20摄氏度时,声速V = 332 + 0.607t (m/s)
  3. 利用超声波进行距离测量,要求精度一般都不高,取20摄氏度时候的声速344M/S进行计算,再进行适当的补偿就可以。所以,其计算公式为:
    距离L = 344M/S * T / 2 = 172M/S * T 。
实现步骤
  1. 产生8个40KHz的超声波信号,通过TX引脚发射出去。 (产生一个40KHz的超声信号,计算得周期为25us,所以产生一个40KHz信号即是发送开始,延时12us,再停止发送,也就是一个高电平12us,一个低电平12us)
  2. 启动定时器,计算计数脉冲。
  3. 等待超声波信号返回,如果接收到反射回来的信号,RX引脚变为低电平。
  4. 停止定时器,读取脉冲个数,即获得时间T。
  5. 根据公式,L = V * T /2m,进行距离的计算。

在蓝桥杯单片机的竞赛综合平台CT107D中,超声波模块的TX引脚接到单片机的P1.0端口,RX引脚接到单片机的P1.1端口。
设计程序,进行超声波测距,最大测量范围约140cm。测量结果用cm作为显示单位,显示在数码管的最右边三位。如果测量距离超出范围,则以“F”作为标志,显示在数码管的最左边一位。

#include 
#include 
#include 

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);
}

你可能感兴趣的:(蓝桥杯,单片机)