前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于STM32的HC-SR04超声波测距模块实验

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

作者头像
用户8913398
发布2021-08-16 16:07:17
2.2K0
发布2021-08-16 16:07:17
举报

硬件环境

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

HC-SR04超声波模块

软件环境

KEIL5

CUBEMX

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

实验目标

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

1、超声波模块介绍

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

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

基本原理:经发射器发射出长约 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,下面是实物图。

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

1.3 超声波时序图

以上时序图表明你只需要提供一个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高速时钟,本次主要介绍使用外部高速时钟,上图:

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

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

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

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

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

至此,我们的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();
}

接下来是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,测量效果还是可以的:

本次要分享的内容就要结束啦,希望对能帮助到正在想使用HC-SR04超声波模块却不知道如何下手的小伙伴。

如果你觉得对自己有帮助的话,给个赞,点个关注,点个在看,感谢前进的道路上有你的陪伴!图片欢迎大家关注Embeded小飞哥,让我快点遇到优秀的你,然后一起变得更加优秀,加油!!!小飞哥微信号:w974762670,加好友进群一起交流呀!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小飞哥玩嵌入式 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 软件环境
  • 实验目标
  • 1、超声波模块介绍
    • 1.1 超声波测距原理及系统组成
      • 1.2 HC-SR04模块原理
        • 1.3 超声波时序图
          • 1.4 电气参数
          • 2、软件实现
            • 2.1 硬件连接
              • 2.2 cubemx配置
                • 2.3 软件代码实现
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档