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

HC-SR04超声波

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

Proteus仿真

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

下面附上代码

			/**************************************************************************
				*******************************超声波测距***************************
					** 按下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的时候测得的数值直接扩大了近两倍,**这个我不知道是不是仿真软件的问题,希望哪位大佬知道哪有问题的话,指教一下!这里就先谢谢了!

你可能感兴趣的:(单片机学习)