STM32-笔记23-超声波传感器HC-SR04

一、简介

HC-SR04 工作参数:

• 探测距离:2~600cm

• 探测精度:0.1cm±1%

• 感应角度:<15°

• 输出方式:GPIO

• 工作电压:DC 3~5.5V

• 工作电流:5.3mA

• 工作温度:-40~85℃

  • 怎么让它发送波 Trig?

给Trig端口至少10us的高电平

  • 怎么知道它开始发了波 Echo引脚?

由低电平跳转到高电平,表示开始发送波

  • 怎么知道接收了返回波 Echo?

由高电平跳转回低电平,表示波回来了

  • 怎么算时间 ?

Echo引脚维持高电平的时间,波发出去的那一下,开始启动定时器 波回来的那一下,我们开始停止定时器,计算出中间经过多少时间

  • 怎么算距离?

距离 = 速度(343m/s) * 时间 / 2

二、实验前期准备

因为想把测出来的距离打印在串口上,所以复制项目文件19-串口打印功能,重命名25-超声波传感器,新建文件夹hc-sr04

打开工程文件

加载文件

引脚接线

三、代码:

main.c

cpp 复制代码
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "hcsr04.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    led_init();//初始化led灯
    hcsr04_init();
    uart1_init(115200);
    while(1)
    { 
        printf("距离是:%.2f\r\n",hcsr04_get_lenght());
        delay_ms(1000);
    }
}

hcsr04.c

cpp 复制代码
#include "hcsr04.h"
#include "delay.h"

TIM_HandleTypeDef tim2_handle = {0};//定义结构体

//定时器初始化函数
void timer_init()//把ARR和PSC当作参数传进来
{
    tim2_handle.Instance = TIM2; //选择使用的定时器
    tim2_handle.Init.Prescaler = 72-1; //PSC:使其读一个数用1us
    tim2_handle.Init.Period = 65536-1; //ARR
    tim2_handle.Init.CounterMode = TIM_COUNTERMODE_UP;//配置成向上的,默认向上的
    tim2_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;  //自动重装载,默认自动重装载
    
    HAL_TIM_Base_Init(&tim2_handle);
//    HAL_TIM_Base_Start_IT(&tim2_handle);//设置使能更新中断,和启动计数器
}

//msp函数
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM2)
    {
        __HAL_RCC_TIM2_CLK_ENABLE();
//        HAL_NVIC_SetPriority(TIM2_IRQn,2,2);//设置优先级
//        HAL_NVIC_EnableIRQ(TIM2_IRQn);//设置使能中断
    }
}
//定时器启动的函数
void tim2_start(void) 
{
    HAL_TIM_Base_Start(&tim2_handle);
}
//定时器关闭的函数
void tim2_stop(void) 
{
    HAL_TIM_Base_Stop(&tim2_handle);
}
//读CNT计数器的值
uint16_t tim2_get_cnt(void) 
{
    return __HAL_TIM_GetCounter(&tim2_handle);
}
//将CNT计数器的值传递进来
void tim2_set_cnt(uint16_t val) 
{
    __HAL_TIM_SetCounter(&tim2_handle,val);
}
//初始化gpio口引脚
void hcsr04_gpio_init(void)
{   
    GPIO_InitTypeDef gpio_initstruct;//定义一个结构体gpio_initstruct
    //打开trig和echo时钟
    TRIG_GPIO_CLK_ENABLE();
    ECHO_GPIO_CLK_ENABLE();
    
    //调用TRIG的GPIO初始化函数
    gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出
    gpio_initstruct.Pin = TRIG_PIN;//trig对应的引脚
    gpio_initstruct.Pull = GPIO_NOPULL;//引脚不拉
    gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;//高速
    
    HAL_GPIO_Init(TRIG_PORT,&gpio_initstruct);
    
    //调用echo的GPIO初始化函数
    gpio_initstruct.Mode = GPIO_MODE_INPUT;//作为输入引脚
    gpio_initstruct.Pin = ECHO_PIN;//echo对应的引脚
    
    HAL_GPIO_Init(ECHO_PORT,&gpio_initstruct);
}
//初始化超声波
void hcsr04_init(void)
{
    timer_init();//初始化定时器
    hcsr04_gpio_init();//初始化GPIO引脚
    
}
//读取超声波测出来的距离
float hcsr04_get_lenght(void)
{
    uint16_t total_time = 0;  //定义一个变量用于接收CNT的值
    float distance = 0;
    //1、Trig,给Trig端口至少10us的高电平
    TRIG_HIGH();
    delay_us(15);
    TRIG_LOW();
    
    //2、Echo引脚,由低电平跳转到高电平,表示开始发送波
        //波发出去的那一下,开始启动定时器
    while(ECHO_STATUS() == GPIO_PIN_RESET);//用echo引脚是否从低电平变成高电平来决定波是否发出去了
    tim2_start(); //启动定时器2
    tim2_set_cnt(0);//将定时器初始值置0
    //3、Echo,由高电平跳转回低电平,表示波回来了
        //波回来的那一下,我们开始停止定时器
    while(ECHO_STATUS() == GPIO_PIN_SET);//用echo引脚是否从高电平变成低电平来决定波是否接到
    tim2_stop();//关掉定时器
    
    //4、Echo引脚维持高电平的时间=计算出中间经过多少时间
    total_time = tim2_get_cnt();//用total_time接收CNT定时器里面的值
    
    //距离 = 速度(343m/s) * 时间 / 2
    //343m/s = 34300cm/s,因为距离是一个来回,所以要/2(这里速度除2下面路程就不用除2了)
    // = 34300/2 = 17150cm/s = 0.017150cm/us
    distance = total_time * 0.01715;
    return distance;
}

hcsr04.h

cpp 复制代码
#ifndef __HCSR04_H__
#define __HCSR04_H__

#include "sys.h"

#define TRIG_PORT                 GPIOB                                             //trig对应gpio的哪一组
#define TRIG_PIN                  GPIO_PIN_6                                        //trig对应gpio的哪个引脚
#define TRIG_GPIO_CLK_ENABLE()    __HAL_RCC_GPIOB_CLK_ENABLE()                      //gpio口时钟打开
#define TRIG_HIGH()               HAL_GPIO_WritePin(TRIG_PORT,TRIG_PIN,GPIO_PIN_SET)//trig对应的引脚拉高
#define TRIG_LOW()                HAL_GPIO_WritePin(TRIG_PORT,TRIG_PIN,GPIO_PIN_RESET)//trig对应的引脚拉低

#define ECHO_PORT                 GPIOB                                             //echo对应gpio的哪一组
#define ECHO_PIN                  GPIO_PIN_7                                        //echo对应gpio的哪个引脚
#define ECHO_GPIO_CLK_ENABLE()    __HAL_RCC_GPIOB_CLK_ENABLE()                      //gpio口时钟打开
#define ECHO_STATUS()             HAL_GPIO_ReadPin(ECHO_PORT,ECHO_PIN)              //读取echo对应的引脚电平

void hcsr04_init(void);
float hcsr04_get_lenght(void);

#endif

打开串口助手,每一秒超声波都在测距

相关推荐
jjddzyh2 分钟前
单片机串口控制
单片机·嵌入式硬件
heater4042 分钟前
【STM32】I2C为什么要开漏输出和上拉电阻
stm32·单片机·嵌入式硬件
沐欣工作室_lvyiyi33 分钟前
数字PWM直流调速系统设计(论文+源码)
stm32·单片机·嵌入式硬件·物联网·毕业设计
嵌入式小杨2 小时前
阻抗(Impedance)、容抗(Capacitive Reactance)、感抗(Inductive Reactance)
单片机·嵌入式硬件·物联网·学习·面试·硬件工程
霜雪殇璃2 小时前
2025.01.02(数据库)
笔记·学习
Wang Niewei2 小时前
将simpletex 识别的公式 复制到ppt 中
笔记·powerpoint
小鱼做毕设2 小时前
单片机实物成品-010 智能宠物喂食系统(代码+硬件+论文)
单片机·嵌入式硬件·宠物
qq_工控_小白3 小时前
eplan如何导出可跳转的PDF
笔记·pdf·eplan
逝灮4 小时前
Keil5报错:Error: L6218E: Undefined symbol __initial_sp (referred from entry2.o).
stm32·单片机·嵌入式硬件·keil5·keil5报错
黑果果的思考5 小时前
STM32 NOR FLASH(SPI FLASH)驱动移植(2)
stm32·嵌入式硬件