STM32驱动HC-SR04超声波模块

简介: STM32驱动HC-SR04超声波模块

前言

本篇文章将带大家使用HAL库驱动HC-SR04超声波模块。超声波模块作为智能小车必备的模块,要学习智能小车的同学是必须掌握好这个模块的使用的。


一、HC-SR04超声波模块介绍

HC-SR04是一种常用的超声波传感器模块,也被称为超声波测距模块,广泛应用于各种自动化控制和测距系统中。它通常由超声波发射器、接收器、控制电路和外壳组成,可以实现非接触式的距离测量。


下面是HC-SR04超声波模块的一些特性和技术参数:


距离测量范围:2cm ~ 400cm(可调)。


测量精度:0.3cm。


工作电压:DC 5V。


工作电流:15mA。


频率:40kHz。


传播速度:340 m/s。


工作温度:-20℃ ~ 70℃。


HC-SR04超声波模块的工作原理与常规的超声波测距器类似,主要分为发送信号和接收信号两个部分。当模块接收到控制电路传输的触发信号时,超声波发射器就会向测距目标物体发送一定频率的超声波脉冲,然后超声波接收器会接收到反射回来的超声波信号。根据超声波从发射器到目标物体再返回接收器需要的时间,可以计算出目标物体与传感器之间的距离。

超声波模块有4个引脚,接线方法如下:

VCC--5V

GND--GND

Trig--板子上的输出引脚(用来发射超声波信号)

Echo--板子上的输入引脚(用来接收返回的超声波信号)


二、HC-SR04超声波模块原理

下图是超声波模块驱动时序图:

image.png


驱动步骤:

1.首先需要发送一个至少10us的TTL电平信号用来触发超声波模块。

2.发送完触发信号后模块内部会自动循环发出8个40KHZ的脉冲。

3.接收回响信号,根据高电平的时间来计算出距离。

计算公式:T(s) * 340(m/s) / 2

这里的计算需要除2,因为超声波发出的信号是需要往返的。


三、代码编写

创建HC-R04.c和HC-R04.h两个文件:


HC-R04.h

#ifndef _HC_SR04_H
#define _HC_SR04_H
#include "sys.h"
#include "delay.h"
#include "stm32f4xx_hal.h"
void HCSR04_Init(void);
#define Trig_ON   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET)
#define Trig_OFF  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET)
void SR04_Trigger(void);
uint32_t Get_Distance(void);
#endif

HC-R04.c

这里我们把Trig引脚配置为输出引脚,Echo配置为外部中断引脚,触发方式设置为双边沿触发。


这里需要配置一个定时器来计算高电平的时间。

在外部中断回调函数中进行判断是上身沿还是下降沿。

当上身沿到达时清空定时器计数值开始计数,当下降沿达到时取出定时器的计数值作为往返的时间,根据公式即可计算出距离。

#include "HC-SR04.h"
/*
  PC8:Trig(发射引脚)
  PC9:Echo(接收引脚)
*/
TIM_HandleTypeDef TIM4_Handler;
uint32_t pulse_width_us = 0;
uint32_t distance_cm = 0;
void HCSR04_Init(void)
{
    // 定义GPIO的结构体变量
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOC_CLK_ENABLE();     // 使能超声波的GPIO对应的时钟
    /*Trig引脚*/
    GPIO_InitStruct.Pin = GPIO_PIN_8;               // 选择超声波的引脚
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;     //推挽输出
    GPIO_InitStruct.Pull = GPIO_PULLUP;             //上拉
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;   // 引脚输出速度设置为快 
    // 初始化引脚配置
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    /*Echo引脚*/
    GPIO_InitStruct.Pin = GPIO_PIN_9;                           // 选择超声波的引脚
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;         // 设置为双边沿触发外部中断
    GPIO_InitStruct.Pull = GPIO_PULLUP;                         // 上拉
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;               // 引脚输出速度设置为快 
    // 初始化引脚配置
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);// 设置外部中断优先级
    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);       // 使能外部中断
    /*配置定时器4为us级定时器*/
    __HAL_RCC_TIM4_CLK_ENABLE();            //使能TIM4时钟
    TIM4_Handler.Instance = TIM4;                          //通用定时器4
    TIM4_Handler.Init.Prescaler = 83;                     //分频系数
    TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
    TIM4_Handler.Init.Period = 0xffff;                        //自动装载值
    TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
    HAL_TIM_Base_Init(&TIM4_Handler);
}
//外部中断中断处理函数
void EXTI9_5_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);
}
void SR04_Trigger(void)
{
    // 发送10us的高电平脉冲
    Trig_ON;
    delay_us(10);
    Trig_OFF;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    static int count = 0;
    if(GPIO_Pin == GPIO_PIN_9)
    {
      if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9))
      {
        HAL_TIM_Base_Start(&TIM4_Handler);                   // 启动定时器
        __HAL_TIM_SetCounter(&TIM4_Handler, 0);              //清空定时器的值
      }
      else if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) == 0)
      {
        HAL_TIM_Base_Stop(&TIM4_Handler);                   // 停止定时器
        count = __HAL_TIM_GetCounter(&TIM4_Handler);        //获取当前计数值
        distance_cm = count * 340/2*0.000001*100;
        printf("distance_cm is %d\r\n", distance_cm);               
        count = 0;
      }
    }
}
/*返回距离*/
uint32_t Get_Distance(void)
{
  return distance_cm;
}

四、程序测试

在while1循环中每隔50ms发射一次超声波信号,在外部中断中使用printf函数来打印出距离到串口中。

while(1)
{
  int SR04_tick = 0;  
  /*50ms发射一次超声波*/
  if(HAL_GetTick() - SR04_tick > 50)
  {
    SR04_tick = HAL_GetTick();
    SR04_Trigger();
  }
}

总结

超声波模块的原理和使用就介绍到这里了,有什么问题的同学可以留言或者私信。需要源代码的同学可以关注微信公众号私信我。

相关文章
|
3月前
|
传感器
手把手在STM32F103C8T6上构建可扩展可移植的DHT11驱动
【8月更文挑战第29天】本文详细介绍在STM32F103C8T6上构建可扩展且可移植的DHT11温湿度传感器驱动的步骤,包括硬件与软件准备、硬件连接、驱动代码编写及测试。通过这些步骤,可根据实际项目需求优化和扩展代码。
102 0
|
4月前
STM32Cubemx PWM驱动加湿器模拟火山喷发效果
STM32Cubemx PWM驱动加湿器模拟火山喷发效果
69 14
|
4月前
STM32Cubemx PWM驱动SG90舵机
STM32Cubemx PWM驱动SG90舵机
162 13
|
4月前
STM32CubeMX mpu6050驱动
STM32CubeMX mpu6050驱动
72 10
|
4月前
STM32CubeMX WS2812B灯驱动
STM32CubeMX WS2812B灯驱动
201 1
|
4月前
STM32CubeMX ULN2003步进电机驱动
STM32CubeMX ULN2003步进电机驱动
62 0
|
4月前
STM32Cubemx TB6612直流电机驱动
STM32Cubemx TB6612直流电机驱动
145 0
|
5月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
428 2
|
4月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
694 0
|
5月前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
503 4