Advertisement

开发基于51单片机的超声波测距系统用于实现精确测量

阅读量:

本文阐述了利用51单片机与超声波模块构建一个简易测距装置的具体实现方式。

一、先介绍一下超声波模块

模块的正面配置了两个探头,一个负责发射超声波信号,另一个则用于捕捉障碍物反射后的回波信号。
该模块共设有四个引脚,依次为VCC、Trig、Echo以及GND。
其中,VCC与GND引脚承担着供电功能。
Trig引脚为触发信号输入端口,当此端口接收到持续时间为10微秒的高电平信号后,超声波模块将启动发射探头发出声波。
Echo引脚为回响信号输出端口,在模块发送声波之后,该端口会维持高电平状态,直到接收探头检测到由障碍物反射回来的声波信号后,才会回落至低电平状态。

二、程序的实现思路

首先,单片机向超声波模块的Trig引脚施加一个持续时间为10微秒的高电平信号,以触发声波的发射,并在同时启动定时器,用于测量Echo引脚上高电平信号的持续时间。由于声波在空气中的传播速度为340米每秒,因此可通过公式计算距离,即距离等于(340米每秒乘以时间)除以2。

补充知识内容

1、如何计算定时时间

51单片机的定时器内部配置了一个用于计数脉冲信号的寄存器,当定时器被激活后,该寄存器会在每个机器周期结束时自动增加1,直至其数值超过65535时发生溢出,此时定时器将触发中断信号。而这一机器周期的长短则取决于所采用的晶振频率。(1M=1*10^6)

计算一个机器周期所需时间的公式为:t=1∗12/fosc(其中fosc代表晶振频率)

2、如何根据定时的时间计算出距离

首先需要明确的是,速度与运动时间的关系可表示为距离等于速度乘以时间,即距离 = 速度 × 时间。

在实际测量过程中,我们所测得的是声波从发射到碰到障碍物并反射回来所需的时间。由于声波在这段时间内已经往返一次,因此所测得的距离实际上是目标距离的两倍,因此需要将总路程除以2,即距离 = (速度 × 时间) / 2。

接下来需要进行单位转换,其中1米等于1×10²厘米,同时1秒等于1×10⁶微秒。

以下为具体示例(单位为厘米):

S = t × 340 × 10² / 2 cm

三、51单片机的示例代码

复制代码
 #include <reg52.h>

    
  
    
 //定义数码管的位选引脚
    
 sbit wei_1 = P1^0;
    
 sbit wei_2 = P1^1;
    
 sbit wei_3 = P1^2;
    
 sbit wei_4 = P1^3;
    
  
    
 //定义超声波引脚
    
 sbit Trig = P1^6;//发送波端口
    
 sbit Echo = P1^7;//接收端口
    
  
    
  
    
 //共阴极数码管段码0~F
    
 unsigned char code smg[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
    
 	                          0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    
  
    
  
    
 void smg_saomiao(unsigned char weu,unsigned char dat);//声明数码管扫描函数
    
 void delay_ms(unsigned int i);	//声明延时函数	
    
 void startHC(void); //声明触发超声波传感器函数	
    
  
    
  
    
 void main(void)
    
 {
    
 	float time=0.0,dis=0.0;
    
 	int  num=0;
    
  	
    
 	//选择定时器0、工作模式为1,初始值设定0开始数数,先不开始数数	
    
 	TMOD &= 0xf0;
    
 	TMOD |= 0x01;	//使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响	
    
 	
    
 	TH0=0;	      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
    
 	TL0=0;
    
 	
    
 	TR0=0;        //关闭定时器
    
 	
    
 	
    
 	while(1)
    
 	{
    
 		//超声波测距频率约10Hz,既100ms测量一次
    
 		if(num>14)
    
 		{
    
 			startHC();//发射声波
    
 			
    
 			while(Echo==0);//等待模块发射声波
    
 			
    
 			TR0=1;        //打开定时器开始计时
    
 			
    
 			while(Echo==1 && TF0==0);//等待模块接收碰撞障碍物后反射回来的声波
    
  
    
 			TR0=0;        //关闭定时器停止计时
    
 			
    
 			//计算出中间经过多少时间(晶振为11.0592Mhz的计数脉冲时间单位为1.085us,12Mhz为1us)
    
 			time = (float)(TH0 * 256.0 + TL0)*1.085;    //us为单位
    
 			
    
 			//距离 = 速度(340m/s)* 时间/2
    
 			dis = (float)time * 0.017;//计算得出单位为CM
    
 			
    
 			num=0;//将计数变量清零
    
 			TH0=0;//将定时器的计数值清零
    
 	    TL0=0;//将定时器的计数值清零
    
 		}
    
 		
    
 		num++;
    
 		
    
 		//扫描一遍数码管约7ms,7*14=98 约100ms
    
 		smg_saomiao(1,16);
    
 		smg_saomiao(2,(int)dis/100);
    
 		smg_saomiao(3,(int)dis%100/10);
    
 		smg_saomiao(4,(int)dis%10);
    
 	}
    
 }
    
  
    
  
    
 /**************************************************************** * 函 数 名       : Delay10us
    
 * 函数功能		   : 延迟10us
    
 * 参数           : 无
    
 * 返回值         : 无
    
 ******************************************************************/
    
 void Delay10us(void) //@11.0592MHz
    
  {
    
    unsigned char i;
    
     i = 3;
    
    while (--i);
    
 }
    
  
    
 /**************************************************************** * 函 数 名       : startHC
    
 * 函数功能		   : 触发超声波传感器发出声波
    
 * 参数           : 无
    
 * 返回值         : 无
    
 ******************************************************************/ 
    
 void startHC(void)
    
 {
    
 	//发送触发信号
    
 	Trig = 0;
    
 	Trig = 1;
    
 	Delay10us();
    
 	Trig = 0;
    
 }
    
  
    
 /**************************************************************** * 函 数 名       : delay
    
 * 函数功能		   : 延时函数,i=1时,大约延时1ms
    
 *参数i           : 需要延时的毫秒数
    
 *返回值          : 无
    
 ******************************************************************/
    
 void delay_ms(unsigned int i)
    
 {
    
 	unsigned int n;
    
   while(i--)
    
   for(n=0;n<110;n++);		
    
 }
    
  
    
 /**************************************************************** * 函 数 名       : smg_saomiao
    
 * 函数功能		   : 驱动4位的共阴数码管
    
 *参数wei         : 选择要点亮的那一位数码管(1~4)
    
 *参数dat         : 显示的段码内容( 0~15 ——> 0~F)
    
 *返回值          : 无
    
 ******************************************************************/
    
 void smg_saomiao(unsigned char wei,unsigned char dat)
    
 {
    
 	//判断要点亮哪一位数码管
    
    if(wei ==1)
    
 	 {
    
 			wei_1 = 0;
    
 			wei_2 = 1;
    
 			wei_3 = 1;
    
 			wei_4 = 1;		 
    
 	 }else if(wei ==2)
    
 	 {
    
 			wei_1 = 1;
    
 			wei_2 = 0;
    
 			wei_3 = 1;
    
 			wei_4 = 1;		 
    
 	 }else if(wei ==3)
    
 	 {
    
 			wei_1 = 1;
    
 			wei_2 = 1;
    
 			wei_3 = 0;
    
 			wei_4 = 1;		   
    
 	 }else if(wei ==4)
    
    {
    
 			wei_1 = 1;
    
 			wei_2 = 1;
    
 			wei_3 = 1;
    
 			wei_4 = 0;		 
    
 	 }
    
 	 
    
 	 P0 = smg[dat];//显示该位数码管的段码内容
    
 	 delay_ms(3);//延时3-5ms
    
 	 P0 = 0;//熄灭所有段码,即消影
    
 }

四、提升

1、优化

示例中仍存在一些需要改进的方面,例如在测量距离较长的情况下,数码管可能出现频闪现象;同时,当测量距离超出一定范围时,定时器用于记录脉冲数量的寄存器可能会发生溢出并被自动清零的情况,这些问题可供你们尝试进行优化与解决……

2、拓展

本示例仅完成了基本的测距与显示功能,用户还可进一步拓展报警功能,例如当检测到距离过近时,可通过蜂鸣器发出警报(类似倒车雷达的功能);当距离过远时,同样可利用蜂鸣器进行提示(用于跟随场景)等。

3、说明部分概述

该示例旨在为电子创新基地的新成员提供培训时使用

五、实物效果

1、图片相关研究

2、视频相关内容

全部评论 (0)

还没有任何评论哟~