STM32驱动HC-SR04超声波模块

举报
yd_274589494 发表于 2023/07/27 17:47:10 2023/07/27
【摘要】 @TOC 前言本篇文章将带大家使用HAL库驱动HC-SR04超声波模块。超声波模块作为智能小车必备的模块,要学习智能小车的同学是必须掌握好这个模块的使用的。 一、HC-SR04超声波模块介绍HC-SR04是一种常用的超声波传感器模块,也被称为超声波测距模块,广泛应用于各种自动化控制和测距系统中。它通常由超声波发射器、接收器、控制电路和外壳组成,可以实现非接触式的距离测量。下面是HC-SR04...

@TOC


前言

本篇文章将带大家使用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超声波模块原理

下图是超声波模块驱动时序图:
在这里插入图片描述
驱动步骤:
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();
	}
}

总结

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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。