STM32外设系列—HC-SR04(超声波)

news2024/7/6 21:12:09

文章目录

  • 一、超声波测距基本原理
  • 二、超声波传感器简介
  • 三、HC-SR04测距实现思路
  • 四、超声波测距程序实现
    • 4.1 HC-SR04初始化程序
    • 4.3 TIM开关程序
    • 4.4 获取定时时间
    • 4.5 计算测量距离
    • 4.6 宏定义
  • 五、应用实例
  • 六、拓展应用

一、超声波测距基本原理

超声波测距的原理非常简单,超声波发生器在某一时刻发出一个超声波信号,当这个超声波信号遇到被测物体后会反射回来,被超声波接收器接收到。这样只要计算出从发出超声波信号到接收到返回信号所用的时间,就可以计算出超声波发生器与反射物体的距离。

距离的计算公::d=s/2=(c*t)/2

其中 d 为被测物与测距器的距离,s 为声波的来回路程,c 为声波,t 为声波来回所用的时间。

由于超声波也是一种声波,其声速 c 与温度有关,在不同温度下的超声波声速不同。在使用时,如果温度变化不大,则可认为声速是基本不变的。如果测距精度要求很高,则应通过温度补偿的方法加以校正。声速校正后,只要测得超声波往返的时间,即可求得距离。不同外温度下的超声波声速表如下

不同温度下超声波声速表

二、超声波传感器简介

总体上讲,超声波发生器可以分为两大类:一类是用电气方式产生超声波类是用机械方式产生超声波。电气方式包括压电型、磁致伸缩型和电动型等:机械方式有加尔统笛、液哨和气流旋笛等。他们所产生的超声波的频率、功率和声波特性各不相同,因而用途也各不相同。目前较为常用的是压电式超声波发生。

压电式超声波发生器实际上是利用压电晶体的谐振来工作的。它有两个压电晶片和一个共振板。当它的两极外加脉冲信号,其频率等于压电晶片的固有振荡频率时,压电晶片将会发生共振,并带动共振板振动,便产生超声波。反之,如果两极间未外加电压,当共振板接收到超声波时,将压迫压电晶片作振动,将机械能转换为电信号,这时它就成为超声波接收器了。这里介绍的是一个超声波测距模块——HC-SR04。

HC-SR04

三、HC-SR04测距实现思路

这里就不再针对HC-SR04模块的原理和电路做详细介绍了,直接介绍利用该模块实现测距的思路。该模块有四个引脚。

  • VCC —— 通常是5V供电
  • GND —— 地
  • Trig —— 给该引脚大于10us的高电平,超声波发射头会发送一个超声波信号
  • Echo —— 该引脚在接收到返回的超声波信号后会变为高电平

Echo接收到的高电平持续时间即为超声波一个来回所用的时间,利用该时间除以2再乘上光速,即可得到测量距离。

四、超声波测距程序实现

4.1 HC-SR04初始化程序

HC-SR04初始化程序主要包括两部分,一部分是初始化HC-SR04的GPIO,Trig引脚设置为推挽式输出,Echo引脚设置为浮空输入。另一部分是初始化TIM2。初始化TIM2之后,没有立即使能,而是等到Echo接收到高电平的时刻,开启TIM2。

/*
 *==============================================================================
 *函数名称:Drv_Hcsr04_Init
 *函数功能:初始化HC-SR04
 *输入参数:无
 *返回值:无
 *备  注:初始化HC-SR04引脚的同时,初始化了TIM2,用来记录高电平持续时间
          初始化完TIM2后,没有使能,当Echo收到高电平后使能
 *==============================================================================
 */
void Drv_Hcsr04_Init (void)   // Hc-sr04初始化
{    
	// 结构体定义
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;   // 生成用于定时器设置的结构体  
	GPIO_InitTypeDef GPIO_InitStructure;   // GPIO结构体
	NVIC_InitTypeDef NVIC_InitStructure;   // NVIC结构体
	RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);   // 使能GPIO时钟

	// GPIO初始化  
	GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;   // 发送电平引脚  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   // 推挽式输出  
	GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);  
	GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);  
		 
	GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO;   // 返回电平引脚  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   // 浮空输入  
	GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);    
	GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);      
		 
	// 定时器初始化 使用基本定时器TIM2  
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   // 使能对应RCC时钟  
	// 配置定时器基础结构体  
	TIM_DeInit(TIM2);  
	TIM_TimeBaseStructure.TIM_Period = (1000-1);   // 设置在下一个更新事件装入活动的自动重装载寄存器周期的值(计数到1000为1ms ) 
	TIM_TimeBaseStructure.TIM_Prescaler =(72-1);   // 设置用来作为TIMx时钟频率除数的预分频值  1M的计数频率 1US计数  
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;   // 不分频  
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   // TIM向上计数模式  
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);   // 根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位         
				
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);   // 清除更新中断,免得一打开中断立即产生中断  
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);   // 打开定时器更新中断  

	// NVIC配置	     
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);   // 设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 
		
	NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn;   // 选择定时器2中断  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   // 抢占式中断优先级设置为0  
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;   // 响应式中断优先级设置为0  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   // 使能中断  
	NVIC_Init(&NVIC_InitStructure);  
	
	TIM_Cmd(TIM2,DISABLE);       
}

4.3 TIM开关程序

/*
 *==============================================================================
 *函数名称:Drv_Hcsr04_OpenTimerForHc
 *函数功能:打开定时器
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Drv_Hcsr04_OpenTimerForHc (void)   // 打开定时器  
{  
	TIM_SetCounter(TIM2,0);   // 清除计数  
	gMsHcCount = 0;  
	TIM_Cmd(TIM2, ENABLE);   // 使能TIMx外设  
}
/*
 *==============================================================================
 *函数名称:Drv_Hcsr04_CloseTimerForHc
 *函数功能:关闭定时器
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Drv_Hcsr04_CloseTimerForHc (void)   // 关闭定时器  
{  
	TIM_Cmd(TIM2, DISABLE);   // 使能TIMx外设  
}  

定时器中断服务函数如下

/*
 *==============================================================================
 *函数名称:TIM2_IRQHandler
 *函数功能:定时器2中断服务程序 
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void TIM2_IRQHandler (void)   // TIM2中断  
{  
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)   // 检查TIM2更新中断发生与否  
	{  
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);  // 清除TIMx更新中断标志   
		gMsHcCount++;  
	}  
}   

4.4 获取定时时间

/*
 *==============================================================================
 *函数名称:Drv_Hcsr04_GetEchoTimer
 *函数功能:获取定时器定时时间 
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
u32 Drv_Hcsr04_GetEchoTimer (void)  
{  
	u32 t = 0;  
	t = gMsHcCount * 1000;   // 得到MS  
	t += TIM_GetCounter(TIM2);   // 得到US  
	TIM2 -> CNT = 0;   // 将TIM2计数寄存器的计数值清零  
	delay_ms(50);
	return t;  
}

4.5 计算测量距离

/*
 *==============================================================================
 *函数名称:Med_Hcsr04_GetLength
 *函数功能:获取测量距离
 *输入参数:无
 *返回值:无
 *备  注:一次获取超声波测距数据 两次测距之间需要相隔一段时间,隔断回响信号
					为了消除余震的影响,取五次数据的平均值进行加权滤波
 *==============================================================================
 */
float Med_Hcsr04_GetLength (void )  
{  
	u32 t = 0;  
	int i = 0;  
	float lengthTemp = 0;  
	float sum = 0;  
	while(i!=5)  
	{  
		TRIG_Send = 1;   // 发送口高电平输出  
		delay_us(20);
		TRIG_Send = 0;  
		while(ECHO_Reci == 0)   // 等待接收口高电平输出  
		Drv_Hcsr04_OpenTimerForHc();   //打开定时器  
		i = i + 1;  
		while(ECHO_Reci == 1);  
		Drv_Hcsr04_CloseTimerForHc();   // 关闭定时器  
		t = Drv_Hcsr04_GetEchoTimer();   // 获取时间,分辨率为1us
		lengthTemp = ((float)t/58.0);   // cm  
		sum = lengthTemp + sum ;        
		}  
	lengthTemp = sum/5.0;  
	return lengthTemp;  
}

4.6 宏定义

#define HCSR04_PORT   GPIOB   // 定义IO口
#define HCSR04_CLK    RCC_APB2Periph_GPIOB   // 开启GPIO时钟  
#define HCSR04_TRIG   GPIO_Pin_8   // 定义Trig对应引脚
#define HCSR04_ECHO   GPIO_Pin_9   // 定义Echo对应引脚
  
#define TRIG_Send  PBout(8)   // 将TRIG_Send映射到PB8
#define ECHO_Reci  PBin(9)   // 将ECHO_Reci映射到PB9

void Drv_Hcsr04_Init(void);   // Hc-sr04初始化
void Drv_Hcsr04_OpenTimerForHc (void);   //打开定时器
void Drv_Hcsr04_CloseTimerForHc (void);   //关闭定时器
u32 Drv_Hcsr04_GetEchoTimer(void);   // 获取定时器时间

五、应用实例

利用串口打印距离信息,main函数如下

float gDistance = 0;   //定义获取返回距离变量

int main(void)
{
	Med_Mcu_Iint();   // 系统初始化
	
	while(1)
  {
		gDistance = Med_Hcsr04_GetLength();   //获取返回距离
	 	printf ("距离为:%.3f cm\n",gDistance);   //串口打印返回距离
		
		delay_ms(500);   //延时500ms = 0.5s
	}
}

六、拓展应用

超声波测距比较常用的,比如利用超声波测距模块实现智能车的自动避障,这个在后续实战项目系列中会有,在此就不再详细介绍了。主要思路就是根据HC-SR04测得的与障碍物的距离,来决定是否要停止或转弯,以及往那边转弯。

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

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

相关文章

高压放大器在压电陶瓷驱动器中的应用

高压放大器是一种将低电压信号放大成高电压信号的电子设备。它广泛运用于各种领域,如医疗、工业、军事以及科学研究。压电陶瓷驱动器是一种利用压电效应来驱动机械运动的装置。这两种设备经常被用于控制和操作许多不同类型的系统。 压电陶瓷是一种能够将电能转化为机…

监控摄像头的像素200万,400万,800万都是什么意思,200万像素、400万像素、800万像素是如何换算出来的?

一、像素 像素(Pixel)是用来表示图像分辨率的单位,数字越大,表示图像中的细节可以更精细地展现。当我们谈论监控摄像头的像素时,通常指的是摄像头图像传感器上的像素数量。像素的数量可以通过传感器上的横向像素数乘以…

win如何使用OpenSSL生成自签名证书,使 http 升级为 https

win如何使用OpenSSL生成自签名证书,使 http 升级为 https 前言 HTTPS其实就是HTTP over SSL,也就是让HTTP连接建立在SSL安全连接之上。 创建自签名证书需要安装openssl。参考本文安装OpenSSL部分。 使用OpenSSL生成自签名证书的步骤:参考…

python spider 爬虫 之 Selenium 系列 (-) Selenium

京东的 seckill 秒杀 专区 用 urllib 是获取不到的 回顾一下urllib 爬虫 # urllib 爬虫 from urllib import request headers {} url # 请求定制 req request(urlurl, headers headers) # 模拟请求 response request(req) content response.read().decode(utf-…

windows下安装Visual Studio + CMake+OpenCV + OpenCV contrib

目录 1 安装visual studio 2 安装CMake 3 OpenCV源码安装 3.1 OpenCV源码下载 3.2 OpenCV contrib源码下载 3.3 安装OpenCV 3.4 安装OpenCV-crontrib 3.5 VS生成代码 4 环境配置 最近在研究windows系统上部署安装目标检测算法,需要用到OpenCV软件&#xff…

智能指针+拷贝构造+vector容器+多态引起的bug

今天在调试一段代码的时候,VC编译提示: error C2280: “T485CommCtrlPara::T485CommCtrlPara(const T485CommCtrlPara &)”: 尝试引用已删除的函数 函数执行部分如下: 看意思是这个pComm485Pro已经消亡了,后续push_back到ve…

高速电路设计系列分享-信号链精度分析(中)

目录 概要 整体架构流程 技术名词解释 技术细节 1.直流无源误差 小结 概要 提示:这里可以添加技术概要 在任何设计中,信号链精度分析都可能是一项非常重要的任务,必须充分了解。之前, 我们讨论了在整个信号链累积起来并且最终会…

统一日志处理----AOP/面向切面编程

AOP Aspect Oriented Programing:面向切面编程 AOP是对OOP的补充,进一步提高编程的效率 AOP的常见使用场景有:权限检查、记录日志、事务管理等 如下图所示结构,每个模块都含有相同的系统需求,而这些需求和模块本身的功…

Flutter进阶-动画详解

目录 动画类别 一、隐式(全自动)动画 二、显式动画(手动控制) 三、其他动画(CustomPainter) 动画类别 Flutter 中有多种类型的动画: 隐式动画:通过更改部件属性自动触发的预定义动画,例如 …

什么是cookie

1、cookie是什么 Cookie,有时也用其复数形式Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存…

Python强类型编程

Python是一门强类型的动态类型语言,具体如下特性: 可以动态构造脚本执行、修改函数、对象类型结构、变量类型但不允许类型不匹配的操作 第一个例子体现动态性:用字符串直接执行代码,动态构建了一个函数并执行,甚至给…

力扣744.寻找比目标字母大的最小字符(java暴力查找法,二分查找法)

题目描述: 给你一个字符数组 letters,该数组按非递减顺序排序,以及一个字符 target。letters 里至少有两个不同的字符。 返回 letters 中大于 target 的最小的字符。如果不存在这样的字符,则返回 letters 的第一个字符。 [外链…

岭回归(Ridge)不同alpha值对归回结果的影响

对于有些矩阵,矩阵中某个元素的一个很小的变动,会引起最后计算结果误差很大,这种矩阵称为“病态矩阵”。有些时候不正确的计算方法也会使一个正常的矩阵在运算中表现出病态。对于高斯消去法来说,如果主元(即对角线上的…

亚马逊测评:如何有效使用IP和养号设备环境

随着网络科技的崛起,越来越多的本土企业入驻亚马逊电子商务平台上,这导致了对产品评价需求的激增。然而,评价并非随意进行,它需要多方面的资源,并需要密切注意一些重要环节。以下是我分享给大家一些宝贵的知识&#xf…

如何实现敏捷交付中的自动化测试优化

在提及自动化测试的时候,很多人会把工具的使用等同于自动化测试。自动化测试应该是一个策略性的系统化工程,不只有自动化工具。自动化测试要发挥其频繁快速的质量反馈作用,还需要团队从文化和技术上去建设和学习。 提到敏捷交付,…

数据库监控与调优【十二】—— JOIN语句优化

JOIN语句优化-JOIN种类、算法与原理 JOIN的种类 笛卡尔连接(cross join) -- 举例:通过笛卡尔连接查询两张表的结果集和单查两张表的结果集对比 SELECT count( * ) FROM users a CROSS JOIN orders b; SELECT ( SELECT count( * ) FROM user…

SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现

系列文章: SpringBoot Vue前后端分离项目实战 || 一:Vue前端设计 SpringBoot Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接 SpringBoot Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接 文章目录 前端…

微服务: sleuth和zipkin的用处与zipkin安装使用(下)

目录 0. 上篇传送门: 1. 前言简介 mq安装传送门: 微服务: 01-rabbitmq的应用场景及安装(docker) 1.1 Sleuth是一款分布式跟踪解决方案。 1.2 Zipkin是一个开源的分布式跟踪系统。 2. zipkin安装方式 2.1 windows下安装zipkin: 2.1.0 下载jar包位置 2.1.1 下载后,找…

数值计算例题整理

数值计算 一、误差的来源和分类二、有效数字第一个大题(非线性方程组的迭代法)第二个大题(LU分解)第三个大题(牛顿插值法)第四个大题(直线拟合) 一、误差的来源和分类 误差是描述数…

Git 原理和使用

Git 安装 Git是开放源代码的代码托管⼯具,最早是在Linux下开发的。开始也只能应⽤于Linux平台,后⾯慢慢的被移植到windows下,现在,Git可以在Linux、Unix、Mac和Windows这⼏⼤平台上正常运⾏了。 Linux-centos 安装git sudo yu…