HC-SR04超声波测距模块使用方法和例程(STM32)

这篇具有很好参考价值的文章主要介绍了HC-SR04超声波测距模块使用方法和例程(STM32)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于STM32和HC-SR04模块实现超声波测距功能

最近在学STM32做个简单的应用实践一下,顺便水一篇文章。

本文用的单片机是STM32F103C8T6,超声波测距模块是HC-SR04,显示测距结果用的是0.96寸OLED屏模块。

效果展示

下图中小于10cm时的显示结果有点问题,代码已修复并更新

hc-sr04引脚图,单片机/嵌入式,stm32,单片机,arm,嵌入式硬件,c++

修复后的结果:

hc-sr04引脚图,单片机/嵌入式,stm32,单片机,arm,嵌入式硬件,c++

视频演示:https://www.bilibili.com/video/BV1Sg411Z7ex/

基于STM32和HC-SR04模块实现超声波测距功能

HC-SR04硬件概述

HC-SR04超声波距离传感器的核心是两个超声波传感器。一个用作发射器,将电信号转换为40 KHz超声波脉冲。接收器监听发射的脉冲。如果接收到它们,它将产生一个输出脉冲,其宽度可用于确定脉冲传播的距离。就是如此简单!

该传感器体积小,易于在任何机器人项目中使用,并提供2厘米至400厘米(约1英寸至13英尺)之间出色的非接触范围检测,精度为3mm。

Operating Voltage工作电压 直流5V
Operating Current工作电流 15毫安
Operating Frequency运行频率 40K赫兹
Max Range最大范围 4m
Min Range最小范围 2厘米
Ranging Accuracy测距精度 3毫米
Measuring Angle测量角度 15度
Trigger Input Signal触发输入信号 10µS TTL脉冲
Dimension尺寸 45 x 20 x 15毫米

hc-sr04引脚图,单片机/嵌入式,stm32,单片机,arm,嵌入式硬件,c++

HC-SR04超声波传感器引脚

hc-sr04引脚图,单片机/嵌入式,stm32,单片机,arm,嵌入式硬件,c++

让我们看一下它的引脚排列。

VCC 是HC-SR04超声波距离传感器的电源,我们连接了5V的供电。

Trig (Trigger) 引脚用于触发超声波脉冲,下面例程中用的GPIOB5,所以连接STM32的GPIOB5。

Echo 回声当接收到反射信号时,引脚产生一个脉冲。脉冲的长度与检测发射信号所需的时间成正比,下面例程中用的GPIOB6,所以连接STM32的GPIOB6。

GND 应该连接到STM32的地。

HC-SR0如何工作?

当持续时间至少为10 µS(10微秒)的脉冲施加到触发引脚时,一切就开始了。响应于此,传感器以40 KHz发射八个脉冲的声音脉冲。这种8脉冲模式使设备的“超声特征”变得独一无二,从而使接收器能够将发射模式与环境超声噪声区分开。

八个超声波脉冲通过空气传播,远离发射器。同时,回声引脚变为高电平,开始形成回声信号的开始。

如果这些脉冲没有被反射回来,则回波信号将在38毫秒(38毫秒)后超时并返回低电平。因此38 ms的脉冲表示在传感器范围内没有阻塞。

hc-sr04引脚图,单片机/嵌入式,stm32,单片机,arm,嵌入式硬件,c++

如果这些脉冲被反射回去,则在收到信号后,Echo引脚就会变低。这会产生一个脉冲,其宽度在150 µS至25 mS之间变化,具体取决于接收信号所花费时间。

hc-sr04引脚图,单片机/嵌入式,stm32,单片机,arm,嵌入式硬件,c++

HC-SR04的时序图如下:

hc-sr04引脚图,单片机/嵌入式,stm32,单片机,arm,嵌入式硬件,c++

然后,将接收到的脉冲的宽度用于计算到反射物体的距离。这可以通过我们在初中学到的简单的距离-速度-时间方程来解决。

距离=速度x时间

接线

将HC-SR04和0.96寸OLED屏连接到STM32。

HC-SR04 STM32
VCC 5V
Trig GPIO PB5
Echo GPIO PB6
Gnd Gnd
OLED STM32
VCC 3.3V
GND GND
SCL GPIO PB12
SDA GPIO PB13

温度对距离测量的影响

尽管HC-SR04对于我们的大多数项目来说都相当准确,例如入侵者检测或接近警报;但是有时候您可能想设计一种要在户外或在异常炎热或寒冷的环境中使用的设备。在这种情况下,您可能要考虑到空气中的声速随温度,气压和湿度而变化的事实。

由于声音因素进入HC-SR04距离计算的速度,因此可能会影响我们的读数。如果已知温度(°C)和湿度,请考虑以下公式:

声速 m/s = 331.4 +(0.606 * 温度)+(0.0124 * 湿度)

购买地址

本文所用到的模块购买地址如下:

STM32F103C8T6开发板:https://s.click.taobao.com/8SoQMVu
ST-LINK V2仿真器:https://s.click.taobao.com/FEuPMVu
HC-SR04模块:https://s.click.taobao.com/Ing88Vu
0.96寸OLED模块:https://s.click.taobao.com/o4fPMVu
面包板:https://s.click.taobao.com/dBjPMVu
面包板专用跳线:https://s.click.taobao.com/7eG88Vu

程序

我是用的的ST标准库写的程序,文章中放出主要的程序,完整的工程文件请点下面链接下载。

完整工程文件下载:https://url.zeruns.tech/HCSR04

提取码:d9xr

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "HCSR04.h"

uint64_t numlen(uint64_t num)//计算数字的长度
{
    uint64_t len = 1;        // 初始长度为1
    for(; num > 9; ++len)    // 判断num是否大于9,否则长度+1
        num /= 10;	         // 使用除法进行运算,直到num小于1
    return len;              // 返回长度的值
}

int main(void)
{	
	OLED_Init();		//初始化OLED屏
	Timer_Init();		//初始化定时器
	HC_SR04_Init();		//初始化超声波测距模块
	
	OLED_ShowString(1, 1, "Distance:");		//OLED屏输出字符串
	
	while (1)
	{
		int Distance_mm=sonar_mm();			//获取距离测量结果,单位毫米(mm)		
		int Distance_m=Distance_mm/1000;	//转换为米(m)为单位,将整数部分放入Distance_m
		int Distance_m_p=Distance_mm%1000;	//转换为米(m)为单位,将小数部分放入Distance_m_p
		OLED_Clear_Part(2,1,16);			//将OLDE屏第2行清屏
		OLED_ShowNum(2, 1,Distance_m,numlen(Distance_m));	//显示测量结果的整数部分
		OLED_ShowChar(2, 1+numlen(Distance_m), '.');		//显示小数点
		if(Distance_m_p<100){								//判断是否小于100毫米
			OLED_ShowChar(2, 1+numlen(Distance_m)+1,'0');								//因为单位是米,所以小于10cm时要加0
			OLED_ShowNum(2, 1+numlen(Distance_m)+2,Distance_m_p,numlen(Distance_m_p));	//显示测量结果的小数部分
			OLED_ShowChar(2, 1+numlen(Distance_m)+2+numlen(Distance_m_p), 'm');			//显示单位
		}else																			// https://blog.zeruns.tech
		{
			OLED_ShowNum(2, 1+numlen(Distance_m)+1,Distance_m_p,numlen(Distance_m_p));	//显示测量结果的小数部分
			OLED_ShowChar(2, 1+numlen(Distance_m)+1+numlen(Distance_m_p), 'm');			//显示单位
		}
		OLED_Clear_Part(3,1,16);			//将OLDE屏第3行清屏
		OLED_ShowNum(3, 1,Distance_mm,numlen(Distance_mm));		//显示单位为毫米的距离结果
		OLED_ShowString(3, 1 + numlen(Distance_mm), "mm");
		Delay_ms(300);						//延时300毫秒
		
	}
}

Timer.c

#include "stm32f10x.h"                  // Device header
//blog.zeruns.tech
void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);		//启用TIM3时钟

	TIM_InternalClockConfig(TIM3);								//设置TIM3使用内部时钟
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;			//定义结构体,配置定时器
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;	//设置1分频(不分频)
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;	//设置计数模式为向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;			//设置最大计数值,达到最大值触发更新事件,因为从0开始计数,所以计数10次是10-1,每10微秒触发一次
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;			//设置时钟预分频,72-1就是每 时钟频率(72Mhz)/72=1000000 个时钟周期计数器加1,每1微秒+1
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;		//重复计数器(高级定时器才有,所以设置0)
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);			//初始化TIM3定时器
	
	TIM_ClearFlag(TIM3, TIM_FLAG_Update);			//清除更新中断标志位
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);		//开启更新中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);				//设置中断优先级分组
	
	NVIC_InitTypeDef NVIC_InitStructure;						//定义结构体,配置中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;				//指定中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//中断使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	//设置抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;			//设置响应优先级
	NVIC_Init(&NVIC_InitStructure);								// https://blog.zeruns.tech
	
	TIM_Cmd(TIM3, ENABLE);							//开启定时器
}

/*
void TIM3_IRQHandler(void)			//更新中断函数
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)		//获取TIM3定时器的更新中断标志位
	{
		
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);			//清除更新中断标志位
	}
}*/

Timer.h

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);

#endif

HCSR04.c

#include "stm32f10x.h"
#include "Delay.h"

/*
我的博客:blog.zeruns.tech
具体使用说明请到我博客看
*/


#define Echo GPIO_Pin_6		//HC-SR04模块的Echo脚接GPIOB6
#define Trig GPIO_Pin_5		//HC-SR04模块的Trig脚接GPIOB5

uint64_t time=0;			//声明变量,用来计时
uint64_t time_end=0;		//声明变量,存储回波信号时间

void HC_SR04_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);	//启用GPIOB的外设时钟	
	GPIO_InitTypeDef GPIO_InitStructure;					//定义结构体
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		//设置GPIO口为推挽输出
	GPIO_InitStructure.GPIO_Pin = Trig;						//设置GPIO口5
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//设置GPIO口速度50Mhz
	GPIO_Init(GPIOB,&GPIO_InitStructure);					//初始化GPIOB
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;			//设置GPIO口为下拉输入模式
	GPIO_InitStructure.GPIO_Pin = Echo;						//设置GPIO口6
	GPIO_Init(GPIOB,&GPIO_InitStructure);					//初始化GPIOB
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,0);						//输出低电平
	Delay_us(15);											//延时15微秒
}

int16_t sonar_mm(void)									//测距并返回单位为毫米的距离结果
{
	uint32_t Distance,Distance_mm = 0;
	GPIO_WriteBit(GPIOB,Trig,1);						//输出高电平
	Delay_us(15);										//延时15微秒
	GPIO_WriteBit(GPIOB,Trig,0);						//输出低电平
	while(GPIO_ReadInputDataBit(GPIOB,Echo)==0);		//等待低电平结束
	time=0;												//计时清零
	while(GPIO_ReadInputDataBit(GPIOB,Echo)==1);		//等待高电平结束
	time_end=time;										//记录结束时的时间
	if(time_end/100<38)									//判断是否小于38毫秒,大于38毫秒的就是超时,直接调到下面返回0
	{
		Distance=(time_end*346)/2;						//计算距离,25°C空气中的音速为346m/s
		Distance_mm=Distance/100;						//因为上面的time_end的单位是10微秒,所以要得出单位为毫米的距离结果,还得除以100
	}
	return Distance_mm;									//返回测距结果
}

float sonar(void)										//测距并返回单位为米的距离结果
{
	uint32_t Distance,Distance_mm = 0;
	float Distance_m=0;
	GPIO_WriteBit(GPIOB,Trig,1);					//输出高电平
	Delay_us(15);
	GPIO_WriteBit(GPIOB,Trig,0);					//输出低电平
	while(GPIO_ReadInputDataBit(GPIOB,Echo)==0);
	time=0;
	while(GPIO_ReadInputDataBit(GPIOB,Echo)==1);
	time_end=time;
	if(time_end/100<38)
	{
		Distance=(time_end*346)/2;
		Distance_mm=Distance/100;
		Distance_m=Distance_mm/1000;
	}
	return Distance_m;
}

void TIM3_IRQHandler(void)			//更新中断函数,用来计时,每10微秒变量time加1
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)		//获取TIM3定时器的更新中断标志位
	{
		time++;
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);			//清除更新中断标志位
	}
}

HCSR04.h文章来源地址https://www.toymoban.com/news/detail-779120.html

#ifndef __HCSR04_H
#define __HCSR04_H

void HC_SR04_Init(void);
int16_t sonar_mm(void);
float sonar(void);

#endif

推荐阅读

  • 高性价比和便宜的VPS/云服务器推荐:https://blog.zeruns.tech/archives/383.html
  • ESP8266开发环境搭建及项目演示:https://blog.zeruns.tech/archives/526.html
  • Arduino读取DHT11,DHT22,SHTC3温湿度数据:https://blog.zeruns.tech/archives/527.html
  • 学生专属优惠权益大全,教育优惠:https://blog.zeruns.tech/archives/557.html
  • 怎样搭建个人博客:https://blog.zeruns.tech/archives/218.html
  • 使用NPS搭建内网穿透服务器,带Web面板:https://blog.zeruns.tech/archives/660.html

到了这里,关于HC-SR04超声波测距模块使用方法和例程(STM32)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 树莓派使用HC-SR04超声波测距

      超声波测距原理很简单:   1、通过记录发送超声波的时间、记录超声波返回的时间,返回时间与发送时间相减得到超声波的持续时间。   2、通过公式:( 超声波持续时间 * 声波速度 ) / 2 就可以得出距离;   HC-SR04参数:   工作电压: 5V   工作电流:15mA   

    2024年02月06日
    浏览(21)
  • 基于STM32的超声波HC-SR04和红外测距模块测量距离的实验对比(HAL库)

            前言: 本文主要是为了 日常普通场合 下测距做的 对比实验 ,本实验主要包含 2种模块 : 超声波测距模块 (HC-SR04)和 红外测距模块 (SHARP GP2Y0A21YK0F)。两种模块不管是测距原理和编程实验方式都是不相同的,其测距效果也存在很大差异。感兴趣的读者朋友,

    2023年04月27日
    浏览(34)
  • STM32系列(HAL库)——F103C8T6通过HC-SR04超声波模块实现测距

    (1)编程平台:Keil5 (2)CubeMX (3)XCOM(串口调试助手) (1)某宝买的超声波模块   (2)F1的板子,本例使用经典F103C8T6 (3)ST-link 下载器 (4)USB-TTL模块 (5)杜邦线若干 (1)模块简介:         超声波是振动频率高于20kHz的机械波。它具有频率高、波长短、绕射现象小、方向性好、能够成为射

    2024年02月02日
    浏览(23)
  • 【嵌入式系统应用开发】FPGA——基于HC-SR04超声波测距

    硬件 DE2-115 HC-SR04超声波传感器 软件 Quartus 18.1 使用DE2-115开发板驱动HC-SR04模块,并将所测得数据显示到开发板上的数码管。 HC-SR04 超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。图1为 HC-SR04 外观,

    2024年02月08日
    浏览(26)
  • Linux驱动基础(HC-SR04超声波模块)

    本篇文章将讲解HC-SR04超声波模块的驱动程序编写,有了上篇SR501模块驱动程序编写的基础后这篇文章大家将会学的非常轻松。 HC-SR04超声波模块是一种常用于距离测量和障碍物检测的模块。它通过发射超声波信号并接收回波来计算所测量物体与传感器之间的距离。 HC-SR04超声波

    2024年02月05日
    浏览(20)
  • STM32驱动HC-SR04超声波模块

    本篇文章将带大家使用HAL库驱动HC-SR04超声波模块。超声波模块作为智能小车必备的模块,要学习智能小车的同学是必须掌握好这个模块的使用的。 HC-SR04是一种常用的超声波传感器模块,也被称为超声波测距模块,广泛应用于各种自动化控制和测距系统中。它通常由超声波发

    2024年02月09日
    浏览(21)
  • 【CubeMX配置STM32驱动超声波模块(HC-SR04)】

    一、CubeMX配置STM32 1、选择定时器 选择 输入捕获模式 预分频设置为71,向上计数,自动重装值65535 然后将名字改为 ECHO 2、配置TRIG口 这里的端口使用其它空闲的IO口是可以的,设置为输出模式,其它配置不需要改变,最主要的是 User Label 那儿,需要设置为 TRIG ,因为驱动函数里

    2024年02月02日
    浏览(27)
  • 基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距

    一、基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁 二、基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发 三、实战小例程 基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方 四、基于STM32F103C8T6最小系统板HAL库CubeMX驱动HC-SR501红外人体传感模块 五、基于STM32F103C8

    2023年04月17日
    浏览(41)
  • 基于51单片机驱动HC-SR04超声波模块(LCD1602显示)

    点击图片购买 HC- SR04+是一款宽电压工作的超声波测距模块。模块外形尺寸及软件与老版本 HC- SR04完全兼容;可以与老版本HC SR04无缝切换。低至3V的低工作电压, 使其与3.3V供电的MCU可以直接连接。 特点 探测角度: 15° 采用工业级MCU,工作温度:-20C~80C 探测距离:5V:2cm-- 450cm;3.3V: 2c

    2024年02月02日
    浏览(25)
  • 【STM32篇】驱动HC_SR04超声波测距模块

    CH_SR04 HC_SR04超声波测距模块可提供 2cm-400cm 的非接触式测距感测功能,测距精度高达3mm;模块包括超声波发射器,接收器与控制电路。 基本工作原理: (1)采用IO口TRIG触发测距,需要给最少10us的高电平。 (2)模块自动发送8个40kHz的方波,自动检测是否有信号返回。 (3)有

    2024年02月17日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包