基于AT89C51单片机的超声波传感器测距

目录

  基于超声波测距传感器的汽车倒车报警器


 

一、项目目的

1. 了解超声波测距传感器工作原理及引脚功能。

2. 学会使用超声波测距传感器测量距离。

3. 会使用1602液晶显示器显示测量距离。

4. 学会控制LED灯亮灭。

5. 学会使用蜂鸣器发出报警声

二、项目要求

为避免汽车倒车时与后方障碍物发生碰撞,请设计一款基于超声波测距传感器的汽车倒车报警器,要求如下:

①在显示屏上随时显示汽车与车后物体间的距离。

②一旦进入危险距离(<=1m)范围内,蜂鸣器将发出“嘀。。。嘀。。。”声音,LED灯开始闪烁,提示驾驶员;当距离越来越近是,提示声音越急促,LED灯闪烁越快(亮灭间隔越短)。

 

三、系统连接图:

 

 

四、代码实现

1602液晶显示代码:

#include <1602.h>

sbit LCDEN=P3^4;
sbit RS=P3^5;
//RW直接接地,只允许写不允许读
sbit BF=P0^7;

//u8 DectectBusyBit(void)//状态判断函数(忙/闲?)
//{   
//	bit result;
//	P0 = 0xff;	//读状态前先置高电平,防止误判
//	RS = 0;
//	delay_ms(5);
//    RW = 1;
//	LCDEN = 1;
//	delay_ms(5);
//	result=BF; //若LCM忙,则反复测试,在此处原地踏步;当LCM闲时,才往下继续
//	LCDEN = 0;
//	return result;		      
//}

//u8 RdACAdr(void)//读当前光标地址
//{   
//	u8 result;
//	P0 = 0xff;	//读地址前先置高电平,防止误判
//	RS = 0;
//	delay_ms(5);
//    RW = 1;
//	LCDEN = 1;
//	delay_ms(5);
//	result=P0&0x7f; //去掉最高位忙闲标记,只保留低7位地址值
//	LCDEN = 0;
//	return result;		      
//} 

void WrComLCD(u8 ComVal)//写命令函数
{
//	while(DectectBusyBit()==1);         //先检测LCM是否空闲
	RS = 0;
	delay_ms(1);
//  RW = 0;
	LCDEN = 1;
	P0 = ComVal;
	delay_ms(1);
	LCDEN = 0;	
}

void WrDatLCD(u8 DatVal)//写数据函数
{
//	while(DectectBusyBit()==1); 
	RS = 1;
	delay_ms(1);
//  RW = 0;
	LCDEN = 1;
	P0 = DatVal;
	delay_ms(1);
	LCDEN = 0;	
}

void LCD1602_Init(void)//1602初始化函数
{ 
	WrComLCD(0x38);     // 功能设定:16*2行、5*7点阵、8位数据接口
	WrComLCD(0x38);
	WrComLCD(0x38);    
//多次重复设定功能指令,因为LCD启动后并不知道使用的是4位数据接口还是8位的,所以开始时总是默认为4位,这样刚开始写入功能设定指令时,低4位被忽略,为了可靠,最好多写几遍该指令 
	WrComLCD(0x01);    // 清屏 
	WrComLCD(0x06);    // 光标自增、屏幕不动  
	delay_ms(1);	      // 延时,等待上面的指令生效,下面再显示,防止出现乱码
	WrComLCD(0x0C);    // 开显示、关光标
	delay_ms(5);
}

void LCD1602pos(u8 x,u8 y)//1602显示坐标定位函数:x为行标,0:第一行,1:第二行;y为列标,0-15
{
	u8 t;
	t=x?0x40:0x00;
	WrComLCD(0x80+t+y);  
}

void LCD1602_disstr(u8 *p,u8 x,u8 y)//从指定坐标开始显示英文字符串(长度不超过32)
{	
	u8 i=0,t;
    LCD1602pos(x,y);
	while(p[i]!='\0')
	{  
	  	WrDatLCD(p[i]);
		i++;
		delay_ms(5);
	
	//	t=RdACAdr();
    //  if(t==0x10) LCD1602pos(1,0);//读当前坐标,如果第1行写完换行到第2行	
	//	if(t==0x50) LCD1602pos(0,0);//读当前坐标,如果第2行写完换行到第1行
	    
	    if(y+i==16) {x=x^0x01;LCD1602pos(x,0);}//x=x^0x01;//如果第1行写完换行到第2行,如果第2行写完换行到第1行	
		
	}	
}
void LCD1602_disch(u8 ch,u8 x,u8 y)//显示一个英文字符
{	
   	LCD1602pos(x,y);
	WrDatLCD(ch);
	delay_ms(5);	
}

void LCD1602_clear(void)//1602清屏函数
{
 	WrComLCD(0x01);    // 清屏
} 

void LCD1602_backspace(void)//向左删除一个字符
{
 	WrComLCD(0x10);//光标左移
	WrDatLCD(' ');//输出空格
	WrComLCD(0x10);//光标左移
}
超声波 Supersonic代码实现:

#include <supersonic.h>
#define VELOCITY_30C	3495  //30摄氏度时的声速,声速V= 331.5 + 0.6*温度;速度扩大了10倍, 
#define VELOCITY_23C	3453  //23摄氏度时的声速,声速V= 331.5 + 0.6*温度;速度扩大了10倍,

sbit ECHO = P2^0;  //回声接收端口
sbit TRIG = P2^1;  //超声触发端口

u8 count;

void Init_Timer0(void)//定时器0初始化
{
	TMOD = TMOD|0x01;	 //定时器0初始化,设置为:工作方式1(16位计数值)
 	TL0 = 0x66;
	TH0 = 0xfc;	 //定时1ms
    EA = 1;		 //总中断使能
	ET0 = 1;	 //开定时器0 	
}

void Init_Supersonic()//超声波传感器初始化
{
	 TRIG =0;
	 ECHO = 0;
	 count = 0;
	 Init_Timer0();
}

void Trig_SuperSonic()//发出声波
{
	 TRIG = 1;
	 delay_us(1); //延时10微秒;
	 TRIG = 0;
}


u32 Measure_Distance()//计算距离函数,返回为距离值,单位mm  
{
	u32 distance=0;    //距离变量
	u8 l;
	u16 h,y;
	
	while(ECHO == 0);  //等待回声
    
	TR0 = 1;
	while(ECHO);	
	TR0 = 0;

	l = TL0;
	h = TH0;
	y = (h << 8) + l;//将计数值转换为16位
	y = y - 0xfc66;//us部分,不足1ms的时间
	distance = y + 1000 * count;
	count = 0;
//计算总时间(单位us)=若干(count)ms+us(y)
	TL0 = 0x66;
	TH0 = 0xfc;
	delay_us(30);
	distance = VELOCITY_30C * distance / 20000;//距离单位换算成MM
	return distance;
}

void timer0 () interrupt 1//T0中断处理函数  
{
	TL0 = 0x66;
	TH0 = 0xfc;
	count++;
	if(count == 18)//超声波回声脉宽最多18ms
	{
		TR0 =0;
		TL0 = 0x66;
		TH0 = 0xfc;
		count = 0;
	}
}
//输出到串口代码实现

Uart代码部分:

#include <uart.h>

void Init_COM(void) //串口初始化 9600
{
	 TMOD = TMOD|0x20;
     PCON = 0x00;
     SCON = 0x50;
     TH1 = 0xFd;
     TL1 = 0xFd;
     TR1 = 1;
}

void Print_str_COM(u8 *str)//输出字符串到串口
{
	TI=1;
	printf("%s\n",str);
	while(!TI);
	TI=0;
}
Main函数代码实现:

#include <config.h>
#include <uart.h>
#include <supersonic.h>
#include <1602.h>
u8 print[20];//缓冲区
u8 *p={"Distance:"};
sbit beep=P2^3;	//蜂鸣器引脚

void delay_ms(u16 x)//毫秒延时函数
{u16 i;
 u8 j;
 for(i=0;i<x;i++)
    for(j=0;j<115;j++);
}

void delay_us(u8 t) //10倍微秒延时函数,延时10*t微秒
{u8 i;
 for(i=0;i<=t;i++);
}

void Alarm(u8 t) //蜂鸣器报警,持续t秒
{
 u8 i,j,k; 	
 for(j=0;j<t;j++)
 { for(i=0;i<200;i++)
      {beep=0;delay_us(50);beep=1;delay_us(50);}
   //for(k=0;k<100;k++)
     // {beep=0;delay_us(110);beep=1;delay_us(110);}
 }
}
    
void timerinit()
{
	 
      TMOD=0X10;
	 TL0=(8192-1000)%32;
	 TH0=(8192-1000)/32;
	 EA=1; //总中断
	 ET0=1;//	定时、计数器T0允许
	 TR0=1;//TR0=1启动定时器工作


}


void main()
{
     u32 distance=0;
	 TMOD=0X01;
	 TL0=(8192-1000)%32;
	 TH0=(8192-1000)/32;
	 EA=1; //总中断
	 ET0=1;//	定时、计数器T0允许
	 TR0=1;//TR0=1启动定时器工作
	//timerinit();
	//Init_COM();   //串口初始化
	LCD1602_Init();
	
     Init_Supersonic();//超声波初始化
	while(1)
    {
           Trig_SuperSonic(); //开始发射超声波
		 distance=Measure_Distance();//计算脉宽并转换为距离,单位mm
		 sprintf(print,"%lu.%luCM",distance/10,distance%10);//输出到缓冲区
		// Print_str_COM(print);//输出到串口
		 
		 if(distance<100)
		 {			
			   Alarm(1);//当距离小于5cm时,启动报警响5秒
			// P1=0X00;
			  P1=~P1;
			 LCD1602_disstr(p,0,0);//从指定坐标开始显示英文字符串(长度不超过32)
			 LCD1602_disstr(print,1,0);//从指定坐标开始显示英文字符串(长度不超过32)
			 
		 }
		 
		   P1=0XFF;
		   delay_ms(10*distance); //延时,两次发射之间要至少有10ms间隔
		 //delay_ms(1000); //延时,两次发射之间要至少有10ms间隔		 
    }
}

void time0() interrupt 1   
{
	TL0=(8192-2000)%32;
	TH0=(8192-2000)/32;
	//beep=!beep;
	//Alarm(5);//当距离小于5cm时,启动报警响5秒
	

}

四、效果实现

实验现象:当程序下载到实验板上后,打开实验板,测试距离在试验所选超声波所能检测范围之内,基本实现了实验要求的现象:

①在显示屏上随时显示汽车与车后物体间的距离。

②一旦进入危险距离(<=1m)范围内,蜂鸣器将发出“嘀。。。嘀。。。”声音,LED灯开始闪烁,提示驾驶员;当距离越来越近是,提示声音越急促,LED灯闪烁越快(亮灭间隔越短)

本设计存在不足还请各位码友多多指教,旨在互相交流,共同进步,还请多多关注。

猜你喜欢

转载自blog.csdn.net/qq_37037348/article/details/86557979