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

文章目录


一、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
c 复制代码
/* 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.初始化配置代码如下(示例):

c 复制代码
/*******************************************************************************
 * 函数名:User_HCSR04_Init
 * 描述  :HCSR04初始化
 * 输入  :void
 * 输出  :void
 * 调用  :初始化
 * 备注  :
*******************************************************************************/
void User_HCSR04_Init(void)
{
	User_TIM1_Init();
    HCSR04_GPIO_Init();
}
引脚初始化
c 复制代码
/*******************************************************************************
 * 函数名: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);	
}
定时器初始化
c 复制代码
/*******************************************************************************
 * 函数名: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.引脚输入输出配置代码如下(示例):

c 复制代码
/*******************************************************************************
 * 函数名: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.定时器中断处理代码如下(示例):

c 复制代码
/*******************************************************************************
 * 函数名: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测距函数代码如下(示例):

c 复制代码
/*******************************************************************************
 * 函数名: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接口)显示屏的图像显示应用

c 复制代码
/*******************************************************************************
 * 函数名: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.变量定义如下(示例):

c 复制代码
/* 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//38ms

uint8_t ditance_flag = 0;//开始测量标志
uint32_t ditance_count = 0;//测量计数 10us/次
uint16_t MM_ditance = 0;//输出测量距离 单位毫米

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

图片

本来想录像的,但是一直录不好,有兴趣的自己测试下把。

串口打印

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


三、总结

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

相关推荐
2401_854151552 小时前
STM32 看门狗:IWDG 和 WWDG 怎么用
stm32·单片机·嵌入式硬件
我命由我123452 小时前
复利极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
AOwhisky3 小时前
Python 学习笔记(第三期)——流程控制核心知识点自测与详解
开发语言·笔记·python·学习·云原生·运维开发·流程控制
tyqtyq223 小时前
药品说明书解读 —— AI 安全用药助手,鸿蒙原生应用深度解析
人工智能·学习·华为·生活·harmonyos
zjxtxdy3 小时前
TIM编码器接口
stm32·单片机·嵌入式硬件
小心亦新4 小时前
STM32学习13 定时器1中断
stm32·嵌入式硬件·学习
我命由我123454 小时前
72 法则极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
qq_263_tohua5 小时前
第112期 CNN学习,不错的文章
学习
我想我不够好。5 小时前
满级的惩戒在范围
学习
LiaoWL1235 小时前
【SpringCloud合集-04】Sentinel 流量控制与熔断降级 学习笔记
学习·spring cloud·sentinel