欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

51单片机超声波测距数码管显示并报警(Proteus 仿真)

程序员文章站 2022-06-08 21:44:16
...

HC-SR04超声波

实物图
51单片机超声波测距数码管显示并报警(Proteus 仿真)
使用方法
1、给TRIG端口至少10us 的高电平信号
2、模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回
3、有信号返回,ECHO端口会输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间
计算的话这里就不考虑温度的影响直接用声速340m/s

Proteus仿真

HC-SR04可以用Proteus中的SRF04代替
51单片机超声波测距数码管显示并报警(Proteus 仿真)

下面附上代码

			/**************************************************************************
				*******************************超声波测距***************************
					** 按下K1后进行距离测量,当测得的距离超过预设的距离就进行报警 **
							****	当按下K2后增加预设距离,当按下K3后减小预设距离	****  
								*****    若超过测量距离进行报警并显示“ERR”			******
									*******					初始预设距离为100cm        *******
			**************************************************************************/

#include"reg51.h"
#include"intrins.h"

#define uchar unsigned char
#define uint unsigned int
#define LED P0//数码管段选

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

sbit TR = P3^0; //超声波发射端
sbit EC = P3^2; //超声波接收端

sbit K1 = P1^0;//开始测量按钮
sbit K2 = P1^1;//预设值增加按钮
sbit K3 = P1^2;//预设值减小按钮

sbit buzzer = P1^5;//嗡鸣器控制按钮

uint biao = 0x64;//预设值定为100
uint S;//保存超声波距离
bit flag1;//开始按钮启动标志
bit flag2;//距离计算完成标志

//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
uchar led_wei[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
								 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};							 
								 
void delay(uint i)//延时函数
{
	while(i--);
}	

void init()//定时器初始化
{
	TMOD = 0X01;//16位定时器
	TH0 = TL0 =0x00;//装载初值 12MHZ晶振
	TR0 = 0; //先关闭定时器0
	TR = 0;//拉低超声波发射端
}	
								 
void 	key()//按钮功能
{
	if(K1 == 0)
	{
		delay(1000);//按键消抖
		if(K1 == 0)
		{
			flag1 = 1;//开启标志
			flag2 = 0;//等待下次计算完成
			while(~K1);//等待松开按键
		}
	}
	
		if(K2 == 0)
		{
			delay(1000);//按键消抖
			if(K2 == 0)
			{
				biao++;//增加预设值
				if(biao == 400)  biao = 399;//防止超过量程
				while(~K2);//等待松开按键
			}
		}
		
		if(K3 == 0)
		{
			delay(1000);
			if(K3 ==  0)
			{
				biao--;//减少预设值
				if(biao == 2) biao = 3;//防止超过量程
				while(~K3);//等待松开按键
			}
		}
}	

void error()
{
		uchar i;
	for(i = 0; i<8; i++)//八个数码管依次显示
	{
		switch(i)
		{
			case 0 : LSA = 0;LSB = 0;LSC = 0; 
				LED=led_wei[biao/100];  		break;//设定值取百位
			
			case 1 : LSA = 1;LSB = 0;LSC = 0;
				LED=led_wei[biao/10%10]; 		break;//设定值取十位
			
			case 2 : LSA = 0;LSB = 1;LSC = 0;
				LED = led_wei[biao%10]; 	break;//设定值取个位
				
			case 3 : LSA = 1; LSB = 1; LSC = 0; 
						LED = 0x40;		break;				//显示“-”
			
			case 4 : LSA = 0; LSB = 0; LSC = 1; 
						LED = 0x40;		break;				//显示“-”
			
			case 5 : LSA = 1; LSB = 0; LSC = 1;
						LED = 0x79;			break;//显示“E”
			
			case 6 : LSA = 0; LSB = 1; LSC = 1;
						LED = 0X77;		break;//显示“R”
			
			case 7 : LSA = 1; LSB = 1; LSC = 1; 
						LED = 0X77;			break;//显示“R”
		}
		delay(100);//延时
		LED = 0X00;//清除数码管
	}
}

void Led_Light()//数码管显示
{
	uchar i;
	for(i = 0; i<8; i++)//八个数码管依次显示
	{
		switch(i)
		{
			case 0 : LSA = 0;LSB = 0;LSC = 0; 
				LED=led_wei[biao/100];  		break;//设定值取百位
			
			case 1 : LSA = 1;LSB = 0;LSC = 0;
				LED=led_wei[biao/10%10]; 		break;//设定值取十位
			
			case 2 : LSA = 0;LSB = 1;LSC = 0;
				LED = led_wei[biao%10]; 	break;//设定值取个位
				
			case 3 : LSA = 1; LSB = 1; LSC = 0; 
						LED = 0x40;		break;				//显示“-”
			
			case 4 : LSA = 0; LSB = 0; LSC = 1; 
						LED = 0x40;		break;				//显示“-”
			
			case 5 : LSA = 1; LSB = 0; LSC = 1;
				LED = led_wei[S/100];			break;//取测量值百位
			
			case 6 : LSA = 0; LSB = 1; LSC = 1;
				LED = led_wei[S/10%10];		break;//取测量值十位
			
			case 7 : LSA = 1; LSB = 1; LSC = 1; 
				LED = led_wei[S%10];			break;//取测量值个位
		}
		delay(100);//延时
		LED = 0X00;//清除数码管
	}
}	

void buzzer_sound()//嗡鸣器
{
	buzzer = ~buzzer;
}
								 
void ce_ju()//超声波测距
{
	uint time;//计时
	float temp;//转换
	TR=1;//打开发射端
	delay(1);//延时大于10us
	TR=0;//关闭发射端
	
	while(!EC);//等待EC拉高
	TR0=1;//开启定时器0
	while(EC);//等待EC拉低
	TR0=0;//关闭定时器0
	
	time = TH0*256+TL0;//计算时间单位us
	TH0 = TL0 = 0;//装载定时器0初值
	temp = time;
	temp /= 1000;//转换单位ms
	temp *= 17;//计算距离(cm) (声速=34cm/ms 结果/2)
	S = temp + 0.5;//进行四舍五入
	
	flag2 = 1;//计算完成标志
	flag1 = 0;//等待下次测量
}

void bi_jiao()//比较设定值和测得值
{
	if(S < biao) buzzer_sound();//打开嗡鸣器
}

void main()
{
	init();//定时器初始化
	while(1)
	{
		key();//判断哪个按键按下
		if(flag1 == 1) ce_ju();//开始按钮按下开始测量
		if(flag2 == 1) bi_jiao();//测量完成开始比较
		
		if((S < 2 || S > 400) && flag2)  //判断是否超过量程 
		{		
			error();//显示“ERR”
			buzzer_sound();//打开嗡鸣器
		}
		else
					Led_Light();//数码管进行显示
	}
}


总结

这个程序仿真出来呢,有1~5cm误差,数值越高误差越大,**并且有一个问题就是在测量距离大于330cm的时候测得的数值直接扩大了近两倍,**这个我不知道是不是仿真软件的问题,希望哪位大佬知道哪有问题的话,指教一下!这里就先谢谢了!