基于HC-SR04超声波模块实现“倒车雷达”防撞系统

发布时间:
来源: 电子工程世界

具体功能实现

将遮挡物放置HC-SR04前,可以将超声波模块和遮挡物之间的距离展示在4位数码管上;如果两者之间的距离小于5cm,则LED灯(P2^7)亮起。

器件

HC-SR04超声波模块,4位数码管,LED灯,4根杜邦线

超声波测距展示图:

当距离小于5cm时:


此时超声波和遮挡物的距离为4.5cm< 5cm,所以LED(P2^7)点亮。

当距离大于5cm时:

此时超声波和遮挡物的距离为15.6cm,LED灯熄灭


知识介绍

超声波模块(HC-SR04)

以上是该模块测距的工作原理:由Trig引脚发送一个10us的高电平信号,此时模块内部会自动发送8个40khz的脉冲信号,最后声音返回的信号会传送至Echo引脚,利用距离、时间和速度的公式可以得出两者之间的距离

HC-SR04引脚定义图

该项目代码中,Trig口接至P2^1 , Echo接至P2^0,VCC接3.3v,GND接地

超声波测距公式及原理

测试距离 = (高电平时间 * 声速(340m / s)) /2

测试距离最终要除于2的原因是经历了一个来回,相当于走了原本距离的两倍

定时中断系统

外部中断:

STC89C52有4个外部中断;

STC89C52的外部中断有两种触发方式:

下降沿触发和低电平触发

下降沿触发:当按键按下不松手时只触发一次

低电平触发:当按键按下不松手时会持续触发

中断号:

主函数代码(C语言)KEIL5实现

#include


/*     自定义变量类型    */


typedef unsigned char uchar;   //0~255


typedef unsigned int uint;     //0~65535


sbit Echo = P2^0;


sbit Trig = P2^1;


uchar flag;


uchar date_distance[5];


uchar count;


/* 用于控制数码管的引脚 */


sbit LSA = P2^2;


sbit LSB = P2^3;


sbit LSC = P2^4;


uchar LSA_NODE1[] = {0,1,0,1,0,1,0,1,0};


uchar LSB_NODE1[] = {0,1,1,0,0,1,1,0,0};


uchar LSC_NODE1[] = {0,1,1,1,1,0,0,0,0};


//共阴数码管码表 0-F


uchar SMG[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0X00};


//延时10us


void delay_10us(uchar i)


{


   while(i--);


}


//延迟1ms


void delay_ms(uint c)   //误差 0us


{


   uint a,b;


   for(;c>0;c--)


       for(b=102;b>0;b--)


           for(a=3;a>0;a--);


}


/* 数码管选择函数 */


void init_smg(uchar i)


{


   LSA = LSA_NODE1[i];


   LSB = LSB_NODE1[i];


   LSC = LSC_NODE1[i];


}


//初始化定时器


void init_timer()


{


TMOD = 0x11; //打开定时器0 1


//初始化定时器 0


   TH0 = 0x00;


   TL0 = 0x00;


   EA = 1;


   ET0 = 1;


   //TR0 = 1;


//初始化定时器 1


TH1 = 0xF8; //定时2ms


   TL1 = 0xCD;


   ET1 = 1;


   TR1 = 1;


}


//计算距离


void count_distance()


{


//s = 340m/s * time us /2 = 170*time *10^-6 m = 0.17*time mm


uint distance = (TH0*256 + TL0*1)*0.17;  //单位mm


if(distance<50)


{


P2_7 = 0;


}


else {


P2_7 = 1;


}


TH0 = 0;


TL0 = 0;


date_distance[1] = distance%10000/1000;


date_distance[2] = distance%1000/100;


date_distance[3] = distance%100/10;


date_distance[4] = distance%10/1;


}


void display()


{


uchar i;


for(i = 1;i<=4;i++)


{


if(i==1)


P0 = SMG[date_distance[i]] |0x80;


else


P0 = SMG[date_distance[i]];


delay_ms(1);


P0 = 0x00;


}


}


void main()


{


init_timer();


while (1)


{


while(!Echo); //等待Trig发出


TR0 = 1;        //开始计时


while(Echo);      //当Trig发出时,Echo为高电平


TR0 = 0; //终止计时


count_distance();


}


}


//定时器 1 用来数码管显示数据和发射超声波信号


void timer1() interrupt 3


{


TR1 = 0; //终止定时


TH1 = 0xF8; //定时2ms


   TL1 = 0xCD;


count ++;


display();


if(count>100)   //每200ms启动一次超声波模块


{


count = 0;


//启动超声波模块


Trig = 1;


delay_10us(2);


Trig = 0;


}


TR1 = 1;


}


问题解答

Q:

为什么数码管不是显示完整的静态数?

A:

因为数码管显示扫描的速度过慢,只有当扫描的速度足够块,才能“欺骗”眼睛,也就是将延时的时间修改短一些。

如果想要数码管动态显示,只需要将delay_ms里面的时间修改为500即可。

Q:

为什么数码管不能实时更新显示数据,而是按一下RESET的键才能显示当前距离?

A:

解决的方法如下:将数码管要显示的数据赋值给数组,数组将数据进行短暂的存储,以至于数码管有数字可以显示,如果出现问题中的情况,很大原因是因为直接调用数码管的库函数进行显示

Q:

如何通过定时器得到测量距离?

A:

定时器0的初始值TH0和TL0同时设置为0x00,并且此时的TR0=0,也就是定时器还没开启。当Trig发送信号后,Echo开始接受高电平信号,此时开启TR0=1,当Echo恢复低电平时,TR0=0关闭定时器;此时可以得到TH0和TL0的值,将两者合并即可。


文章来源于: 电子工程世界 原文链接

本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。