STM32驱动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();
}
}
总结
超声波模块的原理和使用就介绍到这里了,有什么问题的同学可以留言或者私信。需要源代码的同学可以关注微信公众号私信我。
- 点赞
- 收藏
- 关注作者
评论(0)