超声波测距HC-SR04模块的简单应用

文章目录

  • 一、HC-SR04
    • HC-SR04是什么?
    • HC-SR04测距的原理
  • 二、使用步骤
    • 1.硬件
      • 最远探测距离调节
      • 硬件连接
    • 2.软件
      • 1.初始化配置代码如下(示例):
        • 引脚初始化
        • 定时器初始化
      • 2.引脚输入输出配置代码如下(示例):
      • 3.定时器中断处理代码如下(示例):
      • 4.HCSR04测距函数代码如下(示例):
      • 5.显示函数代码如下(示例):
      • 6.变量定义如下(示例):
      • 7.显示结果如下(示例):
        • 图片
        • 串口打印
  • 三、总结


一、HC-SR04

HC-SR04是什么?

HC-SR04是一种常见的超声波测距模块,它可以用于测量物体与传感器之间的距离,在机器人导航、智能家居和安防系统等领域得到了广泛的应用。

HC-SR04超声波测距模块包含一个发射器和一个接收器,它们通过超声波信号实现测距。当发射器发出超声波信号后,它会被目标物体反射回来,并被接收器接收。根据超声波从发射到接收的时间差,就可以计算出物体与传感器之间的距离。

正面
在这里插入图片描述
背面:
在这里插入图片描述

HC-SR04测距的原理

工作原理:
HC-SR04超声波测距模块由发射器和接收器组成。它通过发射超声波信号并接收反射回来的信号,利用信号的往返时间差来计算距离。

(1)采用 IO 触发测距,给至少 10us 的高电平信号;
(2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
(3)有信号返回,通过 IO 输出一高电平,高电平持续的时间就是超声波从发射到返回的时间.测试距离=(高电平时间*声速(340M/S))/2;

在这里插入图片描述
模块使用注意事项:
1:此模块不宜带电连接,如果要带电连接,则先让模块的 Gnd 端先连接。否则会影响
模块工作。
2:测距时,被测物体的面积不少于 0.5 平方米且要尽量平整。否则会影响测试结果。

二、使用步骤

1.硬件

最远探测距离调节

在这里插入图片描述
上图标志电阻即 R3,可以调节最大探测距离。R3 电阻为 392,探测距离最大 4.5M 左右,探测角度小于 15 度;R3 电阻为 472,探测距离最大 7M 左右,探测角度小于 30 度;出厂默认 392,即最大探测距离 4.5M 左右。R3 电阻大,接收部分增益高,检测距离大,但检测角度会相应变大,容易检测到前方旁边的物体。当然,在不要求很高的测试距离的条件下,
可以改小 R3 来减小探测角度,这时最大测距会减小。

硬件连接

VCC电源5V接5V
Trig控制端接PB12
Echo接收端接PB13
GND电源地接GND
/* Defines ------------------------------------------------------------------*/
#define HCSR04_GPIO_RCC    RCC_APB2Periph_GPIOB
#define HCSR04_GPIO_Port   GPIOB
#define Trig_Pin           GPIO_Pin_12
#define Echo_Pin           GPIO_Pin_13//根据实际的引脚修改

2.软件

1.初始化配置代码如下(示例):

/******************************************************************************** 函数名:User_HCSR04_Init* 描述  :HCSR04初始化* 输入  :void* 输出  :void* 调用  :初始化* 备注  :
*******************************************************************************/
void User_HCSR04_Init(void)
{User_TIM1_Init();HCSR04_GPIO_Init();
}
引脚初始化
/******************************************************************************** 函数名:HCSR04_GPIO_Init* 描述  :HCSR04引脚初始化* 输入  :void* 输出  :void* 调用  :初始化* 备注  :
*******************************************************************************/
void HCSR04_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = Trig_Pin;//控制脚 Trig	GPIO_Init(HCSR04_GPIO_Port, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//下拉输入 GPIO_InitStructure.GPIO_Pin = Echo_Pin;//接收脚 Echo	GPIO_Init(HCSR04_GPIO_Port, &GPIO_InitStructure);	
}
定时器初始化

/******************************************************************************** 函数名:User_TIM1_Init* 描述  :定时器1初始化* 输入  :void* 输出  :void* 调用  :初始化* 备注  :
*******************************************************************************/
void User_TIM1_Init(void)
{RCC_APB2PeriphClockCmd(HCSR04_TIM_CLK_ENABLE, ENABLE); // 启用TIM1时钟TIM_InternalClockConfig(HCSR04_TIM);// 设置TIM1使用内部时钟TIM_TimeBaseInitTypeDef TIM1_TimeBaseInitStructure;// 定义结构体,配置定时器TIM1_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置1分频(不分频)TIM1_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;// 设置计数模式为向上计数TIM1_TimeBaseInitStructure.TIM_Period = PERIOD_COUNT - 1;    // 设置最大计数值,达到最大值触发更新事件TIM1_TimeBaseInitStructure.TIM_Prescaler = PRESCALER_COUNT - 1;    // 设置时钟预分频TIM1_TimeBaseInitStructure.TIM_RepetitionCounter = 0;    // 重复计数器TIM_TimeBaseInit(HCSR04_TIM, &TIM1_TimeBaseInitStructure);    // 初始化TIM1定时器TIM_ClearFlag(HCSR04_TIM, TIM_FLAG_Update);    // 清除更新中断标志位TIM_ITConfig(HCSR04_TIM, TIM_IT_Update, ENABLE);    // 开启更新中断TIM1_NVIC_Init();TIM_Cmd(HCSR04_TIM, ENABLE);    // 开启定时器
}/******************************************************************************** 函数名:TIM1_NVIC_Init* 描述  :定时器1中断配置初始化* 输入  :void* 输出  :void* 调用  :初始化* 备注  :
*******************************************************************************/
void TIM1_NVIC_Init(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);    // 设置中断优先级分组NVIC_InitTypeDef NVIC_InitStructure;    // 定义结构体,配置中断优先级NVIC_InitStructure.NVIC_IRQChannel = HCSR04_TIM_IRQn; // 指定中断通道NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    // 中断使能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    // 设置抢占优先级为最高NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    // 设置响应优先级为最高NVIC_Init(&NVIC_InitStructure);
}

2.引脚输入输出配置代码如下(示例):

/******************************************************************************** 函数名:Trig_out_High* 描述  :Trig输出高电平* 输入  :void* 输出  :void* 调用  :内部调用* 备注  :*******************************************************************************/
void Trig_Out_High(void)
{GPIO_SetBits(HCSR04_GPIO_Port,Trig_Pin);//Trig= 1
}/******************************************************************************** 函数名:Trig_Out_Low* 描述  :Trig输出低电平* 输入  :void* 输出  :void* 调用  :内部调用* 备注  :*******************************************************************************/
void Trig_Out_Low(void)
{GPIO_ResetBits(HCSR04_GPIO_Port,Trig_Pin);//Trig= 0		
}/******************************************************************************** 函数名:Read_Echo_Level* 描述  :读取Echo引脚电平* 输入  :void* 输出  :void* 调用  :内部调用* 备注  :*******************************************************************************/
uint8_t Read_Echo_Level(void)
{return GPIO_ReadInputDataBit(HCSR04_GPIO_Port,Echo_Pin);
}

3.定时器中断处理代码如下(示例):


/******************************************************************************** 函数名:HCSR04_TIM_IRQHandler* 描述  :定时器1中断服务程序* 输入  :void* 输出  :void* 调用  :初始化* 备注  :
*******************************************************************************/
void HCSR04_TIM_IRQHandler(void)
{if(TIM_GetITStatus(HCSR04_TIM, TIM_IT_Update) != RESET){if(ditance_flag){ditance_count++;}TIM_ClearITPendingBit(HCSR04_TIM, TIM_IT_Update); //清除中断挂起位}
}

4.HCSR04测距函数代码如下(示例):

/******************************************************************************** 函数名:Measurement_function* 描述  :HCSR04测距函数* 输入  :void* 输出  :void* 调用  :内部调用* 备注  :*******************************************************************************/
void Measurement_function(void)
{Trig_Out_High();Delay_20us();Trig_Out_Low();	while(Read_Echo_Level()==0);//等待低电平结束ditance_count = 0;	while(Read_Echo_Level()==1);//等待高电平结束	ditance_flag = 1;	if(ditance_count < Overtime)//小于超时时间 38ms{MM_ditance = ((ditance_count * 340)/2)/100;//单位毫米MM}
}

5.显示函数代码如下(示例):

对OLED有疑问的可以参考我的另外一篇博客0.96寸OLED(IIC接口)显示屏的图像显示应用

/******************************************************************************** 函数名:OLED_Rfresh* 描述  :OLED实时显示数据刷新* 输入  :void* 输出  :void* 调用  :1s* 备注  :*******************************************************************************/
void OLED_Rfresh(void)
{OLED_ShowString(1, 1, "Distance:");	//1行1列显示字符串Distance:OLED_Part_Clear(2,1,16);if(MM_ditance < 10){OLED_ShowNum(2,10,MM_ditance,1);	OLED_ShowString(2, 12, "MM");	//2行12列显示单位MM}else if(MM_ditance < 100){OLED_ShowNum(2,10,MM_ditance,2);	OLED_ShowString(2, 13, "MM");	//2行13列显示单位MM		}else if(MM_ditance < 1000){OLED_ShowNum(2,10,MM_ditance,3);	OLED_ShowString(2, 14, "MM");	//2行14列显示单位MM		}	
}

6.变量定义如下(示例):

/* Defines ------------------------------------------------------------------*/
#define HCSR04_GPIO_RCC    RCC_APB2Periph_GPIOB
#define HCSR04_GPIO_Port   GPIOB
#define Trig_Pin           GPIO_Pin_12
#define Echo_Pin           GPIO_Pin_13//根据实际的引脚修改#define HCSR04_TIM                TIM1
#define HCSR04_TIM_CLK_ENABLE  	  RCC_APB2Periph_TIM1
#define PERIOD_COUNT              10
#define PRESCALER_COUNT           72
#define HCSR04_TIM_IRQn			  TIM1_UP_IRQn
#define HCSR04_TIM_IRQHandler     TIM1_UP_IRQHandler#define Overtime                  3800//38msuint8_t ditance_flag = 0;//开始测量标志
uint32_t ditance_count = 0;//测量计数 10us/次
uint16_t MM_ditance = 0;//输出测量距离 单位毫米

7.显示结果如下(示例):

图片

本来想录像的,但是一直录不好,有兴趣的自己测试下把。
在这里插入图片描述

串口打印

截取部分,测试内容:我是拿一个黑色本子立起来从近距离到远距离。

在这里插入图片描述


三、总结

超声波测距模块使用起来比较简单,但是发现环境条件对测量结果也存在一定影响,温度湿度我也没考虑进去,多次测量取平均值我也没用,还是存在诸多问题的,后面有时间在改进下,感谢你的观看,谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/219278.shtml

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

相关文章

【linux系统】用户功能与权限详细总结

前言 菜某的笔记总结&#xff0c;有错误还请指正。 linux用户的概念与root用户 这么理解&#xff1a;一台电脑有多个操作者&#xff0c;每个操作者只能无限制操作自己文件夹中的东西&#xff0c;其他地方的操作需要给与相应权限才能操作。 root用户&#xff1a;就是最高级的…

【Java系列】详解多线程(二)——Thread类及常见方法(上篇)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习Java的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一…

Proxmox创建CentOS虚拟机

文章目录 下载ISO安装文件上传创建虚拟机启动虚拟机设置DNS CentOS配置国内安装源备份原有安装源下载更新国内源清理yum缓存制作新配置文件缓存 下载ISO安装文件 下载地址&#xff1a;https://www.xitongzhijia.net/ 也可去官网进行下载 上传 下面介绍直接通过页面上传&…

【论文阅读笔记】M3Care: Learning with Missing Modalities in Multimodal Healthcare Data

本文介绍了一种名为“MCare”的模型&#xff0c;旨在处理多模态医疗保健数据中的缺失模态问题。这个模型是端到端的&#xff0c;能够补偿病人缺失模态的信息&#xff0c;以执行临床分析。MCare不是生成原始缺失数据&#xff0c;而是在潜在空间中估计缺失模态的任务相关信息&…

idea一些报错

java: 非法字符: \ufeff 使用IDEA修改文件编码 在IDEA右下角&#xff0c;将编码改为GBK&#xff0c;再转为UTF-8&#xff0c;重新启动项目。具体步骤如下&#xff1a; 在IDEA右下角找到UTF-8字样的编码格式设计项&#xff0c;点击选择第一项GBK&#xff0c;然后Convert&#xf…

JVM虚拟机系统性学习-对象的创建流程及对象的访问定位

对象的创建流程与内存分配 对象创建流程如下&#xff1a; Java 中新创建的对象如何分配空间呢&#xff1f; new 的对象先放 Eden 区&#xff08;如果是大对象&#xff0c;直接放入老年代&#xff09;当 Eden 区满了之后&#xff0c;程序还需要创建对象&#xff0c;则垃圾回收…

设计模式——原型模式代码示例

引言 原型是一种创建型设计模式&#xff0c; 使你能够复制对象&#xff0c; 甚至是复杂对象&#xff0c; 而又无需使代码依赖它们所属的类。 所有的原型类都必须有一个通用的接口&#xff0c; 使得即使在对象所属的具体类未知的情况下也能复制对象。 原型对象可以生成自身的完…

C 标准库 - <time.h>

简介 time.h 头文件定义了四个变量类型、两个宏和各种操作日期和时间的函数。 库变量 下面是头文件 time.h 中定义的变量类型&#xff1a; 序号变量 & 描述1size_t是无符号整数类型&#xff0c;它是 sizeof 关键字的结果。2clock_t这是一个适合存储处理器时间的类型。3…

Linux的五种IO模型

众所周知&#xff0c;出于对 OS 安全性的考虑&#xff0c;用户进程是不能直接操作 I/O 设备的。必须通过系统调用请求操作系统内核来协助完成 I/O 动作。 下图展示了 Linux I/O 的过程。 操作系统内核收到用户进程发起的请求后&#xff0c;从 I/O 设备读取数据到 kernel buff…

【超详细】创建vue3+ts项目(引入ElementPlus、Axios)

目录 前言1、使用vue脚手架创建项目1.1检查vue版本1.2 使用vue脚手架创建项目 2、删除项目多余文件&#xff0c;修改配置项目2.1、删除以下文件2.1、在views下创建index文件2.2、修改router/index.ts路由文件&#xff1a;2.3、修改App.vue文件&#xff1a;2.4、初始化页面样式以…

LeetCode141. Linked List Cycle

文章目录 一、题目二、题解 一、题目 Given head, the head of a linked list, determine if the linked list has a cycle in it. There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next poi…

windows上抓包出现大包未分片以及关闭tso方法

wireshark抓包中会有大数据包&#xff08;未分片包&#xff09;和ip校验和不对的包&#xff0c;问题根因在目前很多电脑网卡支持TSO和将校验和计算到网卡上&#xff0c;导致抓出数据包未分片 详细文章看: https://www.cnblogs.com/charlieroro/p/11363336.html 目前很多网卡已…

业务代码-整合框架-存储-缓存常见错误详解一

一. java空指针和异常&#xff1a; 1.什么是空指针异常&#xff08;java.lang.NullPointException)&#xff1a; 1.1常见的空指针异常案例&#xff1a; public class WhatIsNpe {public static class User {private String name;private String[] address;public void print…

项目一 分析并设计学生管理数据库

项目一 分析并设计学生管理数据库 1&#xff0c;做好管理数据库的知识准备 1.1&#xff0c;初识数据库 **1&#xff0c;DBMS&#xff1a;**数据库管理系统(Database Management System)。数据库 是通过DBMS创建和操作的 容器。 **2&#xff0c;DB&#xff1a;**数据库(data…

Python入门第2篇(pip、字符串、方法、json、io操作)

目录 pip包管理器 字符串 方法 json 文件操作 pip包管理器 包管理器类似.NET下的nuget&#xff0c;主要用于管理引用依赖项。 安装Python的时候&#xff0c;已经默认安装了pip包管理器&#xff0c;因此无需单独安装 cmd&#xff0c;输入&#xff1a;pip --version 显示…

C语言:高精度加法

P1601 AB Problem&#xff08;高精&#xff09; - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 过大的数计算就无法用变量定义计算&#xff0c;但可以用数组巧妙的化解这个问题。 #include<stdio.h> #include<stdlib.h> #include<string.h> char x[10005];…

004 Windows NTFS文件夹权限

一、NTFS文件权限&#xff1a; NTFS&#xff08;New Technology File System&#xff09;是Windows NT内核的系列操作系统支持的、一个特别为网络和磁盘配额、文件加密等管理安全特性设计的磁盘格式&#xff0c;提供长文件名、数据保护和恢复&#xff0c;能通过目录和文件许可…

ffmpeg编解码——数据包(packet)概念(如何正确处理数据包中的显示时间戳pts与解码时间戳dts关系?)

文章目录 FFmpeg编解码——数据包&#xff08;Packet&#xff09;概念1. 数据包&#xff08;Packet&#xff09;简介2. 数据包&#xff08;Packet&#xff09;在FFmpeg中的应用2.1 从媒体文件读取数据包2.2 向媒体文件写入数据包 3. 数据包&#xff08;Packet&#xff09;相关问…

【Docker】学习笔记(三)三剑客之 docker-compose文件书写项目多服务容器运行

简介 引言&#xff08;需求&#xff09; 为了完成一个完整项目势必用到N多个容器配合完成项目中的业务开发&#xff0c;一旦引入N多个容器&#xff0c;N个容器之间就会形成某种依赖&#xff0c;也就意味着某个容器的运行需要其他容器优先启动之后才能正常运行&#xff1b; 容…

策略模式实现

策略模式: 策略模式是一种行为型设计模式&#xff0c;它允许你定义一系列算法&#xff0c;把它们封装起来&#xff0c;并且使它们可以互相替换。这样&#xff0c;使用算法的客户端代码可以独立于具体的算法实现方式。 就好像是你要去旅行&#xff0c;你可以选择多种不同的交通…