0
点赞
收藏
分享

微信扫一扫

基于STM32的HC-SR04超声波测距模块实验

硬件环境

STM32F407探索板(其他开发板皆可以)

HC-SR04超声波模块

软件环境

KEIL5

CUBEMX

串口调试助手(sscom或其他)

实验目标


  • 了解HC-SR04超声波模块工作原理
  • 实现超声波模块测距

1、超声波模块介绍

1.1 超声波测距原理及系统组成

超声波测距是借助于超声脉冲回波渡越时间法来实现的。设超声波脉冲由传感器发出到接收所经历的时间为t,超声波在空气中的传播速度为c,则从传感器到目标物体的距离D可用下式求出:D = ct/2,图 2是相应的系统框图。

基于STM32的HC-SR04超声波测距模块实验_串口

基本原理:经发射器发射出长约 6mm,频率为 40KHZ 的超声波信号。此信号被物 体反射回来由接收头接收,接收头实质上是一种压电效应的换能器。它接收到信号后产 生 mV 级的微弱电压信号。

1.2 HC-SR04模块原理

HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测 距精度可达高到3mm,模块包括超声波发射器、接收器与控制电路。基本工作原理:(1)采用 IO 口 TRIG 触发测距,给最少 10us 的高电平信呈。(2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;(3)有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声 波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2,下面是实物图。

基于STM32的HC-SR04超声波测距模块实验_串口_02

如上图接线,VCC供5V电源,GND为地线,TRIG触发控制信号输入,ECHO 回响信号输出等四个接口端。

1.3 超声波时序图

基于STM32的HC-SR04超声波测距模块实验_引脚_03

以上时序图表明你只需要提供一个10uS以上脉冲触发信号,该模块内部将发出8个40kHz周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。公式:uS/58=厘米或者uS/148=英寸;或是:距离=高电平时间*声速(340M/S)/2;建议测量周期为60ms以上,以防止发射信号对回响信号的影响。注:1、此模块不宜带电连接,若要带电连接,则先让模块的GND端先连接,否则会影响 模块的正常工作。2、测距时,被测物体的面积不少于0.5平方米且平面尽量要求平整,否则影响测量的 结果。

1.4 电气参数


电气参数

HC-SR04模块

工作电压

DC5V

工作电流

15mA

工作频率

40KHZ

最远射程

4M

最近射程

2CM

测量角度

15度

输入触发信号

10uS 的 TTL 脉冲

输出回响信号

输出 TTL 电平信号,与射程成比例

规格尺寸

45*20*15mm

2、软件实现

对程设计最重要的就是模块的时序图了,一切皆时序,看明白了时序,那么驱动自然也就不难写了,分析上面时序,首先模块需要触发信号,触发信号是不低于10us的TTL电平,也是就需要控制IO输出不低于10us的高电平脉冲,模块接收到此脉冲信号后,内部会输出8个40KHZ脉冲,然后模块会输出与检测距离相应时间的高电平作为回响信号,作为我们检测的依据。

2.1 硬件连接


单片机

HC-SR04模块

5V

VCC

Trig

PB14

Echo

PB15

GND

GND

2.2 cubemx配置

结合上面我们的分析,需要用到us延时,定时器计算超声波返回高电平时间,us延时在上一篇文章做了很详细的介绍,小伙伴们可以动动可爱的小手哈,​​上篇文章链接在这:Embeded​​。


时钟配置上篇文章也有介绍到,这里也贴出来,也可以使用内部RC高速时钟,本次主要介绍使用外部高速时钟,上图:

基于STM32的HC-SR04超声波测距模块实验_引脚_04

我板子上焊接的是8M的晶体,如果小伙伴们的板子上不是8M,根据自己的晶振频率配置即可,左侧圈1中,可以根据自己的晶体频率,输入相应的频率,经过分频、倍频后,系统时钟频率设置为最大,168MHZ,APB1的时钟频率为 84MHZ,也是后面用到的 TIM2 挂载的时钟源的频率。

基于STM32的HC-SR04超声波测距模块实验_串口_05

TIM2 基础配置,这个就比较简单了,分频系数 83,计数单位为 84MHZ/84 = 1uS,向上计数方式,周期 65535,由于没有使用到中断,不需要开启中断。

基于STM32的HC-SR04超声波测距模块实验_超声波测距_06

配置串口1作为我们调试输出串口,配置如下图

基于STM32的HC-SR04超声波测距模块实验_超声波测距_07

接下来,配置超声波模块用到的IO,PB14作为Trig引脚,配置为输出模式,PB15作为Echo引脚,配置为输入模式

基于STM32的HC-SR04超声波测距模块实验_引脚_08

此时IO的状态有个默认值,可能不是我们上电初始化希望保持的状态,比如Trig引脚是需要输出不低于10us的高电平脉冲,那么Trig初始引脚配置为低电平使我们希望的,为实现这个目的,需要再配置一下

基于STM32的HC-SR04超声波测距模块实验_串口_09

至此,我们的cubemx配置就完成了,下面进行软件逻辑的实现。

2.3 软件代码实现

首先将我们用到的两个IO进行宏定义,方便调用,代码如下:

#define HCSR_TRIG_HIGH() HAL_GPIO_WritePin(HC_SR04_Trig_GPIO_Port,HC_SR04_Trig_Pin,GPIO_PIN_SET)
#define HCSR_TRIG_LOW() HAL_GPIO_WritePin(HC_SR04_Trig_GPIO_Port,HC_SR04_Trig_Pin,GPIO_PIN_RESET)

#define HCSR_ECHO() HAL_GPIO_ReadPin(HC_SR04_ECHO_GPIO_Port,HC_SR04_ECHO_Pin)

根据上面的协议,先实现触发脉冲信号,不低于10us的TTL高电平脉冲信号,我延时了20us,也是上一张测试过的20us延时函数,如果小伙伴不知道怎么实现us延时,麻烦翻看上一张哈,代码如下,顺便用逻辑分析仪截了一下TRIG引脚信号,还是熟悉的20us:

void HCSR04StartTrigStart(void)
{
HCSR_TRIG_HIGH();
for_delay_us(20);
HCSR_TRIG_LOW();
}

基于STM32的HC-SR04超声波测距模块实验_串口_10

接下来是TIM2的配置函数,代码如下:

/* TIM2 init function */
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};

htim2.Instance = TIM2;
htim2.Init.Prescaler = 84-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 65535;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}

}

定时器开启与关闭函数体如下面,由于没用中断,屏蔽了定时器中断部分:

//mode=1-->open timer 
//mode=0-->close timer
void HCSR04_TimerFunc(uint8_t mode)
{
if(mode)
{
__HAL_TIM_SetCounter(&htim2,0);
HAL_TIM_Base_Start(&htim2);
//HAL_TIM_Base_Start_IT(&htim2);
msHcCount = 0;
}
else
{
HAL_TIM_Base_Stop(&htim2);
//HAL_TIM_Base_Stop_IT(&htim2);
}
}

接下来就是我们的核心时间采集及距离换算部分了,代码如下,设计两个函数,一个是单次获取距离,另一个是对采集结果做了均值滤波处理,减少误差:

//单次获取测量距离
float HCSR04_Get_Distant(void)
{
HCSR04StartTrigStart();
while(!HCSR_ECHO());
HCSR04_TimerFunc(1);//start timer
while(HCSR_ECHO());
HCSR04_TimerFunc(0);//stop timer

return (__HAL_TIM_GetCounter(&htim2))/58.0;
}

//均值滤波减小测量误差
float Distance(uint8_t cnt)
{
float sum = 0;
for(int i =0;i<cnt;i++)
{
sum+=HCSR04_Get_Distant();
}
return sum/cnt;
}

主函数部分没什么,每隔100ms读取一次,并通过串口打印出来:

distant =  Distance(5);
t++;
if(t%5==0)
{
t=0;
printf("\r\n\r\n---------------start--------------------\r\n\r\n");
printf("The Mesure Distant is:%.2f cm\r\n",distant);
printf("\r\n\r\n----------------stop--------------------\r\n\r\n");
HAL_GPIO_TogglePin(led_run_GPIO_Port,led_run_Pin);
}
HAL_Delay(100);

最终测试效果,手机支架高度,大概16CM,测量效果还是可以的:

基于STM32的HC-SR04超声波测距模块实验_串口_11

基于STM32的HC-SR04超声波测距模块实验_引脚_12

基于STM32的HC-SR04超声波测距模块实验_引脚_12本次要分享的内容就要结束啦,希望对能帮助到正在想使用HC-SR04超声波模块却不知道如何下手的小伙伴。如果你觉得对自己有帮助的话,给个赞,点个关注,感谢前进的道路上有你的陪伴!图片欢迎大家关注Embeded小飞哥,让我快点遇到优秀的你,然后一起变得更加优秀,加油!!!


源码gitee地址:https://gitee.com/MR_Wyf/WeChatOfficialAccounts


公众号二维码:

基于STM32的HC-SR04超声波测距模块实验_超声波测距_14

举报

相关推荐

0 条评论