第十五届蓝桥杯单片机组——超声波测距

发布时间:2024年01月22日

一、超声波测距原理

超声波测距是一种常用的测量距离的方法,凭借其非接触性、准确度高以及对环境因素影响小的优点,广泛应用于各类机器人、自动驾驶车辆、物体探测、避障等场景。
这种技术的基础是发送超声波并计算其返回时间。在理想情况下,超声波在空气中的速度约为343米/秒(在20°C下)。通过量化超声波单向或双向的传播时间,就可以计算出距离。

操作步骤如下:

  1. 发射超声波:发送器首先发射一束超声波,通常是在40kHz频率。
  2. 接收反射的超声波:发送出去的超声波会碰到障碍物然后反射回来,被超声波接收器接收。
  3. 计算传播时间:通过电路_timer_或者微控制器,计算超声波被发射和接收的时间差。
  4. 计算距离:最后,使用以下公式计算到障碍物的距离:距离= (超声波速度 * 时间) / 2

这种测距方法可以实现中短距离的精确测量,受环境条件影响小,适合在各种环境中使用。

二、利用定时器实现测距

2.1 结合定时器实现过程

  1. 设置Trig引脚高电平:通过软件使Trig引脚输出10微秒以上的高电平,这将促使超声波模块发出8个40kHz的超声波。
  2. 等待接收到Echo信号:然后等待Echo引脚从低电平变为高电平,当接收到Echo信号时,开始用定时器测量时间。
  3. 计算超声波来回时间:当Echo引脚再度变为低电平时,立即停止计时。这个时间就是超声波从发射到反射并接收回来的所有时间。
  4. 计算距离:将这个时间(单位应转化为秒)除以2(因为是来回的时间),然后乘以声速(在空气中为343m/s)即可得到距离。为了方便,我们通常直接把数值转成厘米,公式如下: 距离 =(时间 * 声速 / 2) * 100。

2.2 伪代码

#define Trig P2_0  // Trig接口
#define Echo P2_1  // Echo接口
#define Sound_Velocity 343 // 声速343m/s

void Timer0Init(void);  // 初始化定时器
void Ultrasonic_Init(void); // 超声波初始化

double Distance; 
unsigned int High_Time; // 高电平时间
unsigned int Low_Time; // 低电平时间

void main()
{
    Ultrasonic_Init();
    while(1)
    {
       Trig = 1;
       delay(15);   // 发出至少10us的高电平
       Trig = 0;
       while(!Echo); //等待Echo反馈
       TL0 = 0; TH0 = 0; // 装初值
       TR0 = 1;      // 打开定时器
       while(Echo);
       TR0 = 0;      // 关闭定时器
       High_Time = TH0<<8|TL0;  //读取计数器值
       
       Distance = (double)High_Time * Sound_Velocity / 2 / 12;
       delay(50);   // 延时等待超声波模块稳定
    }
}

三、代码示例

#include <stc15f2k60s2.h>
#include <intrins.h>
//#include <smg.h>
sbit Tx=P1^0;
sbit Rx=P1^1;
unsigned long dis;

unsigned char code dat[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99,
					      0x92, 0x82, 0xf8, 0x80, 0x90,
						  0x88,0x80,0xc6,0xc0,0x86,0x8e,
						  0xbf,0x7f,0xff};

unsigned char smg_display[]={18,18,18,18,18,18,18,18}; //保存数码管显示的数字

void Delay2ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 24;
	j = 85;
	do
	{
		while (--j);
	} while (--i);
}

void selectHC573(unsigned char num)  
{
	switch(num)
	{
		case 4:
			P2=(P2 & 0x1f) | 0x80;
			break;
		case 5:
			P2=(P2 & 0x1f) | 0xa0;
			break;
		case 6:
			P2=(P2 & 0x1f) | 0xc0;
			break;
		case 7:
			P2=(P2 & 0x1f) | 0xe0;
			break;
		case 0:
			P2=(P2 & 0x1f) | 0x00;
			break;
	}
}

void display_SMG_Bit(unsigned char dat, unsigned pos)
{
	/*消影法1*/
//	selectHC573(6);
//	P0=0x01<<(pos-1);
//	selectHC573(7);
//	P0=dat;
//	
//	delay(100);
//	P0=0xff;
	
	/*消影法2*/
	P0=0xff;
	selectHC573(7);
	selectHC573(0);
	
	P0=0x01<<(pos-1);
	selectHC573(6);
	selectHC573(0);


	P0=dat;
	selectHC573(7);
	selectHC573(0);
	
}

void display_D_SMG()
{	
	display_SMG_Bit(dat[smg_display[0]],1);
	Delay2ms();
	
	display_SMG_Bit(dat[smg_display[1]],2);
	Delay2ms();
	
	display_SMG_Bit(dat[smg_display[2]],3);
	Delay2ms();

	display_SMG_Bit(dat[smg_display[3]],4);
	Delay2ms();
	
	display_SMG_Bit(dat[smg_display[4]],5);
	Delay2ms();
	
	display_SMG_Bit(dat[smg_display[5]],6);
	Delay2ms();
	
	display_SMG_Bit(dat[smg_display[6]],7);
	Delay2ms();

	display_SMG_Bit(dat[smg_display[7]],8);
	Delay2ms();
}


void system_Init()
{
	selectHC573(5);
	P0=0x00;
	selectHC573(0);
}



void Delay13us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 36;
	while (--i);
}



void Timer0_Init(void)		//100微秒@12.000MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x00;				//设置定时初始值
	TH0 = 0x00;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 0;				//定时器0开始计时
}


void csb_test()
{
	unsigned char i=0;
	for(i=0;i<2;i++){
		Tx=0;
		Delay13us();
		Tx=1;
		Delay13us();
	}
	
	//如果Rx=1或TF0=1者开始计算距离,如果Rx=0且TF0=1说明距离过远
	
	/* V1.0版本
	
	while(Rx==0);  //我不知道我发完触发信号好Rx引脚会不会马上置为高电平
	//如果马上置为高电平,它卡在这个while语句出不来。
	TR0=1;
	while(Rx==1);
	
	*/
	
	/* V1.1版本 假设它马上高电平,那我去掉那个while语句
	TR0=1;  
	while(Rx==1);  // 如果太近或者太远那么Rx永远不会为0,也就一直卡在这里
	*/
	
	/* V2.0	*/
	TR0=1;
	while(Rx==1 && TF0==0);  // Rx=1,或者定时器还没有计数满就一直循环。
	if(TF0==0){
		TR0=0;
		dis=TH0*256+TL0;
		dis=((dis*1700)/110592);
		//340*100/11059200/2
		smg_display[5]=dis/100;
		smg_display[6]=dis/10%10;
		smg_display[7]=dis%10;
	}
	else{
		TF0=0;
		TR0=0;
		smg_display[6]=18;
		smg_display[7]=18;
		smg_display[8]=18;
	}
	TH0=0;
	TL0=0;
	
	
}


void main()
{
	system_Init();
	Timer0_Init();
	while(1){
		csb_test();
		display_D_SMG();
	}
}
文章来源:https://blog.csdn.net/struggle_success/article/details/135737991
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。