基于Arduino Uno以及51单片机的超声波测距

本文将对两者实现超声波测距进行对比

原材料:Arduino,51单片机,杜邦线,HC-SR04(市面常见)

HC-SR04工作原理:网络上相关的介绍很多,这里我将以我的理解来进行阐述:它有四个引脚,一个接VCC,一个接GND。另外两个分别是Trig以及Echo。其中,Trig的作用是启动该模块;而Echo引脚的作用是接受返回的声波。

启动模块的步骤:Trig置为高电平,持续时间大于10us即可,之后将其置为低电平。

之所以我们通过这个模块来测距,是因为我们可以通过计算Echo引脚高电平持续时间进而求出对应的距离。所以核心在于计算高电平的持续时间。

  1. Arduino
    Arduino中,有一个特别的函数可以简单直接求出高电平的持续时间–pulseIn(引脚,高/低电平);它的输出就是时间。完全不需要像单片机使用定时计数器那样麻烦。
const int TrigPin = 2;             //触发控制信号输入
const int EchoPin = 3;             //回响信号输出
float cm;

void setup() {
  Serial.begin(9600);
  pinMode(TrigPin,OUTPUT);
  pinMode(EchoPin,INPUT);
}

void loop() {
  digitalWrite(TrigPin,LOW);
  delayMicroseconds(2);             //delayMicroseconds也是延时函数,单位是微秒
  digitalWrite(TrigPin,HIGH);
  delayMicroseconds(10); 
  digitalWrite(TrigPin,LOW); 
  cm = pulseIn(EchoPin,HIGH)/58;     //pulseIn用于检测引脚输出的高低电平的脉冲宽度。58用于将回波时间换算成cm
  cm = (int(cm*100))/100;            //保留两位小数
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  delay(1000);
}
  1. 51单片机
#include"reg51.h"

#include <intrins.h>
sbit RX=P2^0;
sbit TX=P2^1;
unsigned int  time=0;
unsigned int  timer=0;
unsigned char posit=0;
unsigned long S=0;
bit      flag =0;
//--定义使用的IO--//
#define GPIO_DIG P0

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

//--定义全局变量--//
unsigned char code DIG_CODE[17]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
unsigned char disbuff[4]	   ={ 0,0,0,0,};

void DigDisplay()
{
	unsigned char i;
	unsigned int j;
	for(i=0;i<8;i++)
	{
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=1;LSB=1;LSC=1; break;//显示第7位
			case(1):
				LSA=0;LSB=1;LSC=1; break;//显示第6位
			case(2):
				LSA=1;LSB=0;LSC=1; break;//显示第5位
			case(3):
				LSA=0;LSB=0;LSC=1; break;//显示第4位		
		}
		GPIO_DIG=disbuff[i];//发送段码
		j=10;						 //扫描间隔时间设定
		while(j--);	
		GPIO_DIG=0x00;//消隐
	}
}
    void Conut(void)
	{
	 time=TH0*256+TL0;
	 TH0=0;
	 TL0=0;
	
	 S= (long)(time*0.17);     //算出来是CM
	 if((S>=4000)||flag==1) //超出测量范围显示“ERR0”
	 {	 
	  flag=0;
	  disbuff[0]=0x3f;	   //“-”
	  disbuff[1]=0x50;	   //“-”
	  disbuff[2]=0x50;	   //“-”
	  disbuff[3]=0x79;	   //“-”
	 }
	 else
	 {
	  disbuff[0]=DIG_CODE[S%10000/1000];
	  disbuff[1]=DIG_CODE[S%1000/100];
	  disbuff[2]=DIG_CODE[S%100/10];
	  disbuff[3]=DIG_CODE[S%10/1];
	 }
	}

     void zd0() interrupt 1 		 //T0中断用来计数器溢出,超过测距范围
  {
    flag=1;							 //中断溢出标志
  }
   void  zd3()  interrupt 3 		 //T1中断用来扫描数码管和计800MS启动模块
  {
	 TH1=0xf8;
	 TL1=0x30;
	 DigDisplay();
	 timer++;
	 if(timer>=100)
	 {
	  timer=0;
	  TX=1;			                //800MS  启动一次模块
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_();
	  _nop_(); 
	  _nop_(); 
	  _nop_(); 
	  _nop_();
	  TX=0;
	 } 
  }

	void  main(  void  )

  {  
    TMOD=0x11;		   //设T0为方式1,GATE=1;gate位置1,相当于测量脉宽。
	TH0=0;
	TL0=0;          
	TH1=0xf8;		   //2MS定时
	TL1=0x30;
	ET0=1;             //允许T0中断
	ET1=1;			   //允许T1中断
	TR1=1;			   //开启定时器
	EA=1;			   //开启总中断

	while(1)
	{
	 while(!RX);		//当RX为零时等待
	 TR0=1;			    //开启计数
	 while(RX);			//当RX为1计数并等待
	 TR0=0;				//关闭计数
     Conut();			//计算
	}

  }

当然了,为了直观显示测距后的结果,我这里用到了数码管,这个模块用起来十分的方便,如果有不懂的话,可以在评论区留言。

  1. 总结
    从代码的行数来看,显然是Arduino实现起来方便,仅一句pulseIn就完成了51单片机定时计数器的任务。当然了,像我这种初学者最开始接触的就是51了,用它来实现也可以帮助我们深入理解定时计数器。为以后学习stm32打下基础。

PS:作为一名通信专业的毕业生,目前仍然在学习51以及Arduino,处于找工作的路上,Fighting!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值