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

news2024/10/6 11:28:46

一、超声波测距概述

(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.coloradmin.cn/o/1573629.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

环形链表 - LeetCode 热题 25

大家好&#xff01;我是曾续缘&#x1f970; 今天是《LeetCode 热题 100》系列 发车第 25 天 链表第 4 题 ❤️点赞 &#x1f44d; 收藏 ⭐再看&#xff0c;养成习惯 环形链表 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可…

道路病害的检测与评估

基于yolov8道路病害的检测与评估 1 安装yolov8并使用 1.下载后: 2.选择为所有用户安装 3.选择一个合适的目录 4.第一个是自动添加环境变量,我们用默认的第二个后边手动添加 5.等待安装 1.1 安装anconda并配置环境变量 安装完成anconda之后,主要用的两个为Anaconda Prompt …

用树莓派获取传感器数据通过Onenet云平台(物模型)传输至微信小程序(上)

前言 为了传输传感器数据&#xff0c;在网上找了很多方法&#xff0c;但都因为各种各样的问题最终没能成功实现。最终找到这个既简单&#xff0c;又方便实现的方法。步骤有点多&#xff0c;希望大家可以跟着教程&#xff0c;一步步耐心的做下去&#xff0c;愿大家都能成功实现数…

ubuntu系统安装systemc-2.3.4流程

背景&#xff1a;systemC编程在linux下的基础环境配置 1&#xff0c;下载安装包&#xff0c;并解压 &#xff08;先下载了最新的3.0.0&#xff0c;安装时候显示sc_cmnhdr.h:115:5: error: #error **** SystemC requires a C compiler version of at least C17 **** &#xff…

idea开发 java web 高校学籍管理系统bootstrap框架web结构java编程计算机网页

一、源码特点 java 高校学籍管理系统是一套完善的完整信息系统&#xff0c;结合java web开发和bootstrap UI框架完成本系统 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 前段主要技术 css jq…

【云计算】云数据中心网络(一):VPC

云数据中心网络&#xff08;一&#xff09;&#xff1a;VPC 1.什么是 VPC2.VPC 的组成2.1 虚拟交换机2.2 虚拟路由器 3.VPC 网络规划3.1 VPC 数量规划3.2 交换机数量规划3.3 地址空间规划3.4 不同规模企业地址空间规划实践 4.VPC 网络高可靠设计4.1 单地域单可用区部署4.2 单地…

【鸿蒙 HarmonyOS】@ohos.promptAction (弹窗)

一、背景 创建并显示文本提示框、对话框和操作菜单。 文档地址&#x1f449;&#xff1a;文档中心 说明 本模块首批接口从API version 9开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 该模块不支持在UIAbility的文件声明处使用&#xff0c;即…

Premiere Pro 2024:赋予创意翅膀,让你的视频飞翔 mac/win版

Premiere Pro 2024&#xff0c;作为Adobe旗下的旗舰视频编辑软件&#xff0c;自推出以来&#xff0c;一直在视频制作领域占据着重要的地位。随着技术的不断进步和创新&#xff0c;Premiere Pro 2024为用户带来了前所未有的编辑体验&#xff0c;重新定义了视频制作的标准。 Pre…

爬虫 新闻网站 以湖南法治报为例(含详细注释) V1.0

目标网站&#xff1a;湖南法治报 爬取目的&#xff1a;为了获取某一地区更全面的在湖南法治报已发布的宣传新闻稿&#xff0c;同时也让自己的工作更便捷 环境&#xff1a;Pycharm2021&#xff0c;Python3.10&#xff0c; 安装的包&#xff1a;requests&#xff0c;csv&#xff…

刷题之Leetcode283题(超级详细)

283.移动零 283. 移动零https://leetcode.cn/problems/move-zeroes/ 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nu…

深度剖析鞋服品牌商品数字化管理的重要性

随着信息技术的迅猛发展与市场竞争的加剧&#xff0c;鞋服品牌商品数字化管理的重要性愈发凸显。数字化管理不仅关乎企业运营效率的提升&#xff0c;更是品牌实现差异化竞争、提升顾客体验、构建智慧零售生态的关键所在。对于鞋服品牌企业而言&#xff0c;提升商品数字化管理的…

P2089 烤鸡、P1706 全排列问题、P1157 组合的输出、P1036 [NOIP2002 普及组] 选数——Python代码实现(带注释)

P2089 烤鸡 题目背景 猪猪 Hanke 得到了一只鸡。 题目描述 猪猪 Hanke 特别喜欢吃烤鸡&#xff08;本是同畜牲&#xff0c;相煎何太急&#xff01;&#xff09;Hanke 吃鸡很特别&#xff0c;为什么特别呢&#xff1f;因为他有 1010 种配料&#xff08;芥末、孜然等&#xf…

面试经典150题——K 个一组翻转链表

1. 题目描述 2. 题目分析与解析 在这里推荐大家看一下这个解题思路&#xff1a; https://www.bilibili.com/video/BV11w411V7Ar/?spm_id_from333.337.search-card.all.click&vd_source7ea7c036902f5cb73c7f4781d1b0eaff 整体的算法思路如下&#xff1a; 初始化&#xff1a…

AWS入门实践-利用S3构建一个静态网站

使用Amazon S3托管静态网站是一个流行的选择&#xff0c;因为它简单、成本效益高&#xff0c;并且易于维护。静态网站由不含服务器端脚本的文件组成&#xff0c;如HTML、CSS和JavaScript文件。下面是使用S3托管静态网站的操作步骤&#xff1a; 如果大家没有AWS免费账号&#x…

【C++】背包问题

目录 背包问题01 背包背包不装满问题背包必须满问题 完全背包 背包问题 背包问题属于动态规划的一类题型 01 背包 背包不装满问题 背包必须满问题 #include <iostream> using namespace std; const int N 1010; #include <vector> int main() {int n , V;int v[…

AJAX —— 学习(三)(完结)

目录 一、jQuery 中的 AJAX &#xff08;一&#xff09;get 方法 1.语法介绍 2.结果实现 &#xff08;二&#xff09;post 方法 1.语法介绍 2.结果实现 &#xff08;三&#xff09;通用型的 AJAX 方法 1.语法介绍 2.结果实现 二、AJAX 工具库 axios &#xff08…

批量导入svg文件作为图标使用(vue3)vite-plugin-svg-icons插件的具体应用

目录 需求svg使用简述插件使用简述实现安装插件1、配置vite.config.ts2、src/main.ts引入注册脚本3、写个icon组件4、使用组件 需求 在vue3项目中&#xff0c;需要批量导入某个文件夹内数量不确定的svg文件用来作为图标&#xff0c;开发完成后能够通过增减文件夹内的svg文件&a…

C++高频面试知识总结 part2

C高频面试 1.sizeof是什么&#xff1f;sizeof一个class大小怎么确定&#xff1f;是在编译期还是在运行期确定?2.函数重载的机制&#xff0c;重载是在编译期还是在运行期确定&#xff0c;重载有额外开销吗3.函数重写在编译还是运行时确定&#xff1f;4.如何找到虚函数表&#x…

MySQL复制拓扑4

文章目录 主要内容一.启用GUID并配置循环复制1.其中&#xff0c;UUID用来唯一标识每一个服务器&#xff0c;事务的编号记录了在该服务器上执行的事务的顺序。使用SELECT server_uuid\G命令可以查看服务器的UUID&#xff0c;sever1的UUID值显示如下&#xff1a;代码如下&#xf…

架构图设计

我们了解了软件架构后&#xff0c;方便了我们理解软件各方面的解读&#xff0c;但是如果我们开发中有必要自己设计架构图吗&#xff1f;有&#xff0c;但是不会轮到你。这里浅浅讲一下软构图的设计&#xff0c;相信当你用一张或几张图来描述系统时&#xff0c;是不是经常遇到以…