【51单片机学习记录】超声波测距

news/2024/7/23 23:49:31 标签: 51单片机, 学习, 嵌入式硬件, 蓝桥杯, 单片机

一、超声波测距概述

(1)超声波时间差测距原理

  • 超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。
  • 超声波在空气中的传播速度为340m/s,根据计时器记录的时间t,就可以计算出发射点距障碍物的距离(s),即:s=340*t/2。这就是所谓的时间差测距法。
  • 超声波测距的原理是利用超声波在空气中的传播速度为已知,测量声波在发射后遇到障碍物反射回来的时间,根据发射和接收的时间差计算出发射点到障碍物的实际距离。由此可见,超声波测距原理与雷达原理是一样的。测距的公式表示为:L=C✖️T(式中L为测量的距离长度;C为超声波在空气中的传播速度;T为测量距离传播的时间差(T为发射到接收时间数值的一半))

(2)超声波应用

  • 超声波测距主要应用于倒车提醒、机器人、建筑工地、工业现场等的距离测量,虽然目前的测距量程上能达到百米,但测量的精度往往只能达到厘米数量级。
  • 超声波易于定向发射、方向性好、强度易控制、与被测量物体不需要直接接触的优点,是作为液体高度测量的理想手段。

二、超声波测距原理

(1)超声波发射电路

(2)超声波接收电路

(3)超声波/红外选择跳线

  • N A1-P10 N B1-P11可以使用P10和P11操作超声波发射模块
  • N A2-P10 N B2-P11使用的红外

三、超声波测距应用

(0)编写逻辑

  1. 产生8个40KHz的超声波信号,通过TX引脚发射出去。
  2. 启动定时器,开始计时。
  3. 等待超声波信号返回,如果接收到反射回来的信号,RX引脚变为低电平
  4. 停止定时器,读取脉冲个数,即获得时间T.
  5. 根据公式,L=V*T/2 m,进行距离的计算。

(1)变量

(2)函数

(每14us发射一次,发射八次)

(3)主函数

(4)完整代码

#include<STC15.H>
#include<intrins.H>

sbit TX = P1^0 ;//超声波发射引脚
sbit RX = P1^1 ;
	
unsigned char LED_Bit=0XFF;
unsigned char Actuator_Bit=0X00;

#define LEDx_ON(n) 	{ LED_Bit&=_crol_(0XFE,n-1); P0=LED_Bit; P2|=0X80;	P2&=0X9F;	P2&=0X1F;}
#define LEDx_OFF(n) { LED_Bit|=_crol_(0X01,n-1); P0=LED_Bit; P2|=0X80;	P2&=0X9F;	P2&=0X1F;}

#define Buzzer_ON 	Actuator_Bit|=0x40; P0=Actuator_Bit;	P2|=0XA0;	P2&=0XBF; P2&=0X1F;		
#define Buzzer_OFF 	Actuator_Bit&=0XBF; P0=Actuator_Bit;	P2|=0XA0;	P2&=0XBF;	P2&=0X1F;
#define Relay_ON 		Actuator_Bit|=0x10; P0=Actuator_Bit;	P2|=0XA0;	P2&=0XBF;	P2&=0X1F;
#define Relay_OFF 	Actuator_Bit&=0XEF; P0=Actuator_Bit;	P2|=0XA0;	P2&=0XBF;	P2&=0X1F;

unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
unsigned char KEY_Value = 0 ;
unsigned char DigCom=0;
unsigned char DigBuf[8] = {10,10,10,10,10,10,10,10};

unsigned char LED = 1 ;
unsigned int LED_tt =0;
bit LED_Ref = 0 ;

unsigned int SEG_tt =0;		//定义一个数码管计数时间标识位
bit SEG_Ref = 0 ;					//定义一个数码管刷新标识位
bit SEG_Run = 0 ;					//定义一个控制数码管运行标识位
unsigned int Num = 999 ;

unsigned int LCM_tt = 0 ;//超声波计数时间标识位
bit LCM_Ref = 0 ;				 //超声波刷新标识位
unsigned int LCM = 0 ;	 //存储超声波测距
unsigned int LCM_Time = 0 ;//定时器计时超声波从发出到返回的时间

void ALL_Init(void);
void Delay_MS(unsigned int MS);
void KeyScan(void);
void ArrKeyScan(void);
void Timer0Init(void);		//1毫秒@11.0592MHz
void Send_wave(void);
void Timer1Init(void);

void main(void)
{
	IO_Init();
	ALL_Init();
	Timer0Init();
	Timer1Init();
	EA=1;ET0=1;
	
	while(1)
	{
		KeyScan();
//		ArrKeyScan();
		if(KEY_Value==7){KEY_Value=0;SEG_Run = 1 ;}
		if(KEY_Value==6){KEY_Value=0;SEG_Run = 0 ;}
		if(KEY_Value==5){KEY_Value=0;LEDx_ON(1);Buzzer_ON;}
		if(KEY_Value==4){KEY_Value=0;LEDx_OFF(1);Buzzer_OFF;}	
		
		if(LCM_Ref==1)//timer0计时达到300ms
		{
			LCM_Ref = 0 ;
			Send_wave();
			TR1 = 1; //发送超声波之后定时器开始计时
			while((RX == 1)&&(TF1 == 0));//没有接收到信号 没有产生溢出中断 当无论是采集到数据或者定时器1溢出 开始执行
			TR1 = 0;//清楚定时器的计时值
			if(TF1 == 1) //产生中断 溢出
			{
				TF1 = 0 ;//清除中断、溢出
				LCM = 9999 ;//表示没有采集到数据
			}
			else 
			{
				LCM_Time = TH1 ;//读出定时器中的高八位数据
				LCM_Time <<= 8 ;
				LCM_Time |= TL1 ;//读出十六位数据
				LCM = (unsigned int)(LCM_Time*17/921.6); //  1/11059200HZ/12分频=  1/921600(计一个数的时间)    LCM_Time*17000(cm) * (1/921600)
				//LCM = (unsigned int)(LCM_Time*0.017); 如果比赛要求使用12MHZ
			}
			TL1 = 0x00;		//设置定时初始值 清零便于下次计时
			TH1 = 0x00;		//设置定时初始值
		}
		DigBuf[5] = LCM/100;
		DigBuf[6] = LCM%100/10;
		DigBuf[7] = LCM%10;  
	}
}



void Timer1Init(void)		//0毫秒@11.0592MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x00;		//设置定时初始值
	TH1 = 0x00;		//设置定时初始值
	TF1 = 0;		//清除TF1标志
//	TR1 = 1;		//定时器1开始计时
}


void Delay14us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 45;
	while (--i);
}

void Send_wave(void)
{
	unsigned char i = 8 ;
	do
	{
		TX = 1 ;  Delay14us();
		TX = 0 ;  Delay14us();
	}
	while(i--);
}

void KeyScan(void)
{
	if(P30==0)
	{
		Delay_MS(10);
		if(P30==0)KEY_Value = 7 ;		
		while(!P30);
	}
	else if(P31==0)
	{
		Delay_MS(10);
		if(P31==0)KEY_Value = 6 ;		
		while(!P31);
	}	
	else if(P32==0)
	{
		Delay_MS(10);
		if(P32==0)KEY_Value = 5 ;		
		while(!P32);
	}	
	else if(P33==0)
	{
		Delay_MS(10);
		if(P33==0)KEY_Value = 4 ;		
		while(!P33);
	}	
}

void Timer0(void) interrupt 1
{
	P0=0X00;
	P2|=0XC0;  // P2=P2|0XC0;   XXXX XXXX | 1100 0000 = 11XX XXXX
	P2&=0XDF;	 // P2=P2&0XDF;   11XX XXXX & 1101 1111 = 110X XXXX	
	P2&=0X1F;		//关闭所有的74HC573锁存器	
	
	P0=tab[DigBuf[DigCom]];	
	P2|=0XE0;			//	P2=P2|0XE0;   XXXX XXXX | 1110 0000 = 111X XXXX
	P2&=0XFF;		 	// P2=P2&0XDF;   11XX XXXX & 1101 1111 = 110X XXXX	
	P2&=0X1F;			//关闭所有的74HC573锁存器
	
	P0=(0X01<<DigCom); 	//然后选中第一个数码管
	P2|=0XC0;  // P2=P2|0XC0;   XXXX XXXX | 1100 0000 = 11XX XXXX
	P2&=0XDF;	 // P2=P2&0XDF;   11XX XXXX & 1101 1111 = 110X XXXX	
	P2&=0X1F;		//关闭所有的74HC573锁存器

	if(++DigCom == 8)DigCom = 0 ;
	
	LED_tt++;
	if(LED_tt == 999) {LED_tt = 0 ; LED_Ref = 1 ;}

	if(++SEG_tt==1000){SEG_tt=0;SEG_Ref=1;}
	if(++LCM_tt==300){LCM_tt = 0 ; LCM_Ref = 1 ;}//假设每300ms进行一次测量
}

void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}




void Delay_MS(unsigned int MS)
{
	unsigned i,j;
	for(i=0;i<MS;i++)
		for(j=853;j>0;j--); 
}

void ALL_Init(void)
{
	P0 =0X00;		//先设置关闭蜂鸣器继电器的P0输出值(全关)
	P2|=0XA0;		// 将P27 P25 设置为1 其他位保持不变
	P2&=0XBF; 	// 将P26设置为0 其他位保持不变
	P2&=0X1F;		//关闭所有的74HC573锁存器

	P0 =0XFF;		//先设置关闭所有的LED的P0输出值(全关)
	P2|=0X80;		// 将P27设置为1 其他位保持不变
	P2&=0X9F;		// 将P26 P25设置为0 其他位保持不变
	P2&=0X1F;		//关闭所有的74HC573锁存器
	
	P0 =0X00;		//先设置选择数码管位选的P0输出值(全不选)
	P2|=0XC0;		// 将P27 P26 设置为1 其他位保持不变
	P2&=0XDF;		// 将P26设置为0 其他位保持不变
	P2&=0X1F;		//关闭所有的74HC573锁存器
}


http://www.niftyadmin.cn/n/5473577.html

相关文章

经典机器学习算法:线性回归。逻辑回归。决策树。支持向量机(SVM)。朴素贝叶斯(Naive Bayes)。

目录 经典机器学习算法 分别举例说明这些算法的应用,并对比优劣以及实际应用场景。

C#操作MySQL从入门到精通(6)——对查询数据进行排序

前言 在和MySql数据库交互的过程中,查询数据是使用最频繁的操作,并且我们经常需要对查询到的数据进行排序后输出,比如我想查询1列数据的最小值,那么我可以将查询到的数据进行升序(从小到大)排列,然后取第一个数据就是最小值。本文详细介绍了对查询数据进行排序的各种操…

4.2.k8s的pod-标签管理、镜像拉取策略、容器重启策略、资源限制、优雅终止

一、标签管理 1.标签在k8s中极其重要&#xff0c;大多数资源的相互关联就需要使用标签&#xff1b;也就是说&#xff0c;资源的相互关联大多数时候&#xff0c;是使用标签进行关联的&#xff1b; 2.其他作用&#xff0c;在k8s集群中&#xff0c;node节点的一些操作比如污点及污…

JS文件上传的分析

Tutorial1 source code1 <!--* Author: 夏2同学* Date: 2020-07-15 22:06:32* LastEditTime: 2020-07-18 13:17:27* LastEditors: 夏2同学* FilePath: \学习JavaScript\index.html* Description: --> <!DOCTYPE html> <html><head><meta charset…

【多模态融合】MetaBEV 解决传感器故障 3D检测、BEV分割任务

前言 本文介绍多模态融合中&#xff0c;如何解决传感器故障问题&#xff1b;基于激光雷达和相机&#xff0c;融合为BEV特征&#xff0c;实现3D检测和BEV分割&#xff0c;提高系统容错性和稳定性。 会讲解论文整体思路、模型框架、论文核心点、损失函数、实验与测试效果等。 …

域控报错:Windows无法创建对象 XX,因为目录服务无法分配相对标识符。

当域控制器报告错误“Windows无法创建对象&#xff0c;因为目录服务无法分配相对标识符”时&#xff0c;这通常是指在Active Directory环境中尝试创建新用户、计算机或其他安全主体时&#xff0c;域控制器无法从预先分配给每个域的RID&#xff08;Relative Identifier&#xff…

3.2.k8s搭建-kubeadm

目录 一、虚拟机准备 二、所有节点环境准备 1.所有节点做hosts解析 2.所有节点重新命名 3.所有节点安装docker 4.所有节点为docker做linux内核转发 5.所有节点配置docker 6.所有节点关闭swap分区 7.所有节点验证网卡硬件编号是否冲突 8.所有节点配置允许iptables桥接…

考研总计划篇

政治 九月份开始听徐涛老师的课&#xff0c;只需要听哲学&#xff0c;政治&#xff0c;经济学即可&#xff0c;然后用仓盾小程序刷题&#xff0c;刷题就吃饭的时候刷就是了。 工具书—苏一的提分手册&#xff0c;每天抽一个小时刷刷上面的知识点。 英语&#xff08;现在到九…