单片机学习

关于超声波测距简单示例

2016-12-13  本文已影响138人  Deng_Wei

       最近由于事情比较杂,加上自己懒得动手码字,一直没有更简书。刚好最近帮学弟做了一个超声波测距(含温度补偿)的小项目,觉得再看以前的示例程序不够通俗明了,站在过来人的视点,写一段简单的示例程序,给大家看看。

       首先想说的是,单片机程序应该从时序图入手。了解外围器件的工作时序,并按照时序,对控制时序的引脚上拉下拉各种跳变,就可以对外围器件进行读写。是不是觉得有点抽象。没有关系,接下来不多说,实际例子来教新手使用HC-SR04这个超声波模块。四个引脚分别是电源正负和收发,探头带有T的是传送(Transmission),带有R的是接收(Receiva)实物如下图1所示。

图1

                                                      

硬件连接图如图2。VCC&GND常规的电源正负,ECHO&TRIG两个脚分别为读写引脚。

图2

介绍了硬件,接下来就是关键的软件部分了,在讲软件之前,一定要说下最核心的时序部分(理解时序是十分重要的工程师素养)。下图3就是这个模块的时序图。

图3

触发信号就是Trig引脚的信号,TTL的10us就是出发信号,由图知道,10us的高电平(TTL规格,不懂TTL得话自己百度哟,主要区别于CMOS电平。)。即可启动模块内部的工作时序,模块内部的发出信号我们不用管,只需要了解接口程序怎么按照时序编写就好了,模块内部的工作,只需要配置好工作时序。直接看第三根线(输出回响信号),其实在模块收到trig=1以后,模块就很快(可以忽略的时间)开始发出声波,同时Echo引脚产生高电平,直到声波接触物体并且返回的时候,Echo才变为低电平。所以第三根时序线的高电平时长除以2就是距离所耗时间。错误的理解探头发出的声波被物体挡住以后,声波返回,R探头接收到声波,Echo引脚产生高电平,直到物体消失,Echo引脚电平变低。声波从T探头发出,物体挡住声波,沈波返回到R探头接收。这段时间就是声波走的总路程。看图4了解测距原理吧。

图4 测距的原理

有没有发现,输出回响信号(时序图第三根线)的高电平保持时间就是声波从发出然后碰到到障碍物返回,所消耗的总时间。把这段时间所走的距离除以2.就是模块与障碍物的距离拉~~~

    那么来看程序吧骚年们,主程序如下。

```

void main()

{

uint L; //定义距离变量为无符号integer

TMOD = 0x01; // 初始化单片机的计时器0,方式1

L=GetDistance();    //调用距离计算的子函数

while(1);            //死循环

}

```

主函数写的应该不难看懂,就是定义要得到的距离是L,然后开启定时器(89C51定时器有T0&T1两个,工作模式有4种,后面我会写文章详细讲定时器/计数器,尽情期待哟),然后调用GetDistance()这个函数获得距离的值,需要注意的是子函数的类型一定要和主函数定义的一致,都是无符号int,避免数据不准确。

```

uint GetDistance(void)

{

uint ss;               // 用于记录测得的距离

TH0=0;              //初始化定时器的高位为0 

TL0=0;              //初始化定时器的低位为0

Trig_P=1;          // 给超声波模块一个开始脉冲

DelayMs(1);       //延时的意义就在于时序要求启动信号要有10um的高电平

Trig_P=0;          //恢复低电平

//前面的程序都是配置时序,使模块工作起来

//模块一旦开始工作,发出声波的同时,会使得ECHO引脚变高

while(!Echo_P);      // 等待超声波模块的Echo变高  直到Echo引脚不再是0

TR0=1;                   // 启动定时器,开始计时

while(Echo_P);      // 等待超声波模块接收到返回声波

TR0=0;                  // 停止定时器,停止计时

ss=((TH0*256+TL0)*0.034)/2;    // 距离cm=(时间us * 速度cm/us)/2

return ss;

}

```

上面这段程序就是严格按照时序写的。如果说有难懂的语句就是定时器的使用,定时器最开始初始化为0。从Echo脚变为1开始计时,收到声波返回停止计时。低位最大只能是256,满了256就要向前进位。举例说明吧,26(十进制数)低位最大是10,挡计数到10的时候,就要向前进位,高位(十位)就会变为3,低位清零继续从0开始计数到10,又进一位。之后十进制数的结果就是 十位X10+个位。同理,计数器也是这样。所以有(TH0*256+TL0)。注意换算单位以后进行运算,并且注意是来回的距离,除以2后就是实际距离哟。讲到这里,简单的超声波测距就完全讲完了,有人跟我吐槽,说我写的例子没有完整的程序,不方便查阅,现附上完整的程序。谢谢大家。

```

/**************Copyrigfht:DENGWEI

TIME:2016.12.12

FUNCTION:超声波测距 

VISION: v1.0**********************/

#include<reg52.h>

#include<intrins.h>  //自带的库 

#define  uchar unsigned char // 以后unsigned char就可以用uchar代替

#define  uint  unsigned int  // 宏定义

sbit Trig_P  = P2^2;        // 超声波模块的Trig管脚

sbit Echo_P  = P2^3;      // 超声波模块的Echo管脚

/*********************************************************/

// 毫秒级的延时函数,time是要延时的毫秒数

/*********************************************************/

void DelayMs(uint time)

{

uint i,j;

for(i=time;i>0;i--)

for(j=110;j>0;j--);

}

/*********************************************************/

// 计算测到的距离

/*********************************************************/

uint GetDistance(void)

{

uint ss; // 用于记录测得的距离

TH0=0;

TL0=0;

Trig_P=1; // 给超声波模块一个开始脉冲

DelayMs(1);        //延时的意义就在于时序要求启动信号要有10um的高电平

Trig_P=0;          //恢复低电平

//前面的程序都是配置时序,使模块工作起来

//模块一旦开始工作,发出声波的同时,会使得ECHO引脚变高

while(!Echo_P); // 等待超声波模块的Echo变高  直到Echo引脚不再是0

TR0=1;     // 启动定时器,开始计时

while(Echo_P); // 等待超声波模块接收到返回声波

TR0=0; // 停止定时器,停止计时

ss=((TH0*256+TL0)*0.034)/2; // 距离cm=(时间us * 速度cm/us)/2

return ss;

}

/*********************************************************/

//主函数

/*********************************************************/

void main()

{

uint L; //定义距离变量为无符号integer

TMOD = 0x01; // 初始化单片机的计时器0,方式1

L=GetDistance();    //调用距离计算的子函数

while(1);            //死循环

}

//end
```

上一篇下一篇

猜你喜欢

热点阅读