传感器系列(一)——超声波测距传感器 HC—SR04模块

目录标题

  • 1.前言(闲话)
  • 2.HC-SR04模块介绍
  • 3.硬件连接
  • 4.软件代码
  • 5.学习补充
  • 6.效果展示(可以先过来看效果)
  • 7.参考链接
  • 8.完整版代码链接

1.前言(闲话)

众所周知传感器(transducer/sensor)是一种检测装置,能感受到被测量的信息,并能将感受到的信息,按一定规律变换成为电信号或其他所需形式的信息输出,以满足信息的传输、处理、存储、显示、记录和控制等要求。传感器在生活中无处不在,小到温湿度传感器测量温湿度,大到当今最火热的领域——物联网IoT,传感器总是发挥着重要的作用。而学习传感器也尤为重要,特别是在电子设计中。

2.HC-SR04模块介绍

1.简介
HC-SR04模块性能稳定,测度距离精确,模块高精度,盲区小。在日常生活中,以下地方都可应用超声波测距模块:
(1)机器人避障
(2)物体测距
(3)液位检测
(4)公共安防
(5)停车场检测
(6)电子设计中的避障智能车也正是应用到了此模块,才能达到避开障碍的功能。
2.电气参数

电气参数HC-SR04超声波测距模块
工作电压DC 5V
工作电流15mA
工作频率40Hz
最远射程4米
最近射程2厘米
测量角度15度
输入触发信号10us的TTL脉冲
输出回响信号输出与射程成正比的TTL电平信号
规格尺寸40x20x15mm

3.工作原理
第一步:通过IO口给Trig接口周期不小于10us的脉冲信号。
第二步:HC-SR04接收到单片机发来的脉冲信号后自动发送8个频率为4KHz的方波,自动检测是否有信号返回。
第三步:若有信号返回,则通过Echo接口向单片机相连的IO口发送一个高电平,高电平持续时间就是超声波从发射到返回的总时间
假设高电平持续时间为T,声速为v(一般为340m/s),那么测到的距离S=(T*v)/2
4.换算单位
(1)us / 58 ——>cm
(2)cm / 148 ——>英寸

5.HC-SR04时序图
在这里插入图片描述结合HC-SR04的时序图,其工作原理可以更好地解释。
6.实物图
在这里插入图片描述

3.硬件连接

1.VCC —— 5V
2.GND——GND
3.Trig ——PA0(TIM2_CH1)
4.Echo ——PA1(TIM2_CH2)

4.软件代码

hcsr04.h

#ifndef __HCSR04_H
#define __HCSR04_H

#include "sys.h"

void Hcsr04Init(void);
void TIM2_RQHandler(void);  
u32 GetEchoTimer(void);
float Hcsr04GetLength(void);


#endif

hcsr04.c

#include "hcsr04.h"
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"


#define TRIG_Send  PAout(0)
#define ECHO_Reci  PAin(1)

u16 msHcCount = 0;//ms计数

/*  对应IO口初始化  */
void Hcsr04Init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;     
    GPIO_InitTypeDef GPIO_InitStructure;
	  NVIC_InitTypeDef NVIC_InitStructure;
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   //使能对应RCC时钟
	
    //PA0_CH1  Trig
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;       	  	 //发送电平引脚
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOA,GPIO_Pin_0);
	
		//PA1_CH2  Echo	
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;    		 			 //返回电平引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);    
    
		TIM_DeInit(TIM2);
		TIM_TimeBaseStructure.TIM_Period = (1000-1); 									//设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到1000为1ms
		TIM_TimeBaseStructure.TIM_Prescaler =(72-1);								  //设置用来作为TIMx时钟频率除数的预分频值  1M的计数频率 1US计数
		TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;					//不分频
		TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  	//TIM向上计数模式
		TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 				       
		
		TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);   									  //打开定时器更新中断
		
		NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;           	  //选择串口1中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     //抢占式中断优先级设置为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;            //响应式中断优先级设置为1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;               //使能中断
    NVIC_Init(&NVIC_InitStructure);

    TIM_Cmd(TIM2,DISABLE);     
}


static void OpenTimerForHc()        //打开定时器
{
        TIM_SetCounter(TIM2,0);			//清除计数
        msHcCount = 0;
        TIM_Cmd(TIM2, ENABLE);  		//使能TIM2外设
}
 
static void CloseTimerForHc()        //关闭定时器
{
        TIM_Cmd(TIM2, DISABLE);  //使能TIM2外设
}
 
 

//定时器1中断服务程序
void TIM2_IRQHandler(void)   //TIM2中断
{
        if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //检查TIM2更新中断发生与否
        {
                TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIM2更新中断标志 
                msHcCount++;
        }
}
 

//获取定时器时间
u32 GetEchoTimer(void)
{
        u32 t = 0;
        t = msHcCount*1000;					//得到us
        t += TIM_GetCounter(TIM2);  //得到us
        TIM2->CNT = 0;  					  //将TIM2计数寄存器的计数值清零
        delay_ms(50);
        return t;
}
 

//一次获取超声波测距数据 两次测距之间需要相隔一段时间,隔断回响信号
//为了消除余震的影响,取五次数据的平均值进行加权滤波。
float Hcsr04GetLength(void)
{
        u32 t = 0;
        int i = 0;
        float lengthTemp = 0;
        float sum = 0;
        while(i!=5)
        {
					TRIG_Send = 1;      					//发送口高电平输出
					delay_us(20);									//20us脉冲
					TRIG_Send = 0;								//脉冲发送完成
					/*等待接收口高电平输出*/
					while(ECHO_Reci == 0);      	
					OpenTimerForHc();        			//打开定时器
					i = i + 1;
					/*等待高电平输出结束*/
					while(ECHO_Reci == 1);
					CloseTimerForHc();        		//关闭定时器
					t = GetEchoTimer();        		//获取时间,分辨率为1US
					lengthTemp = ((float)t/58.0);	//cm
					sum = lengthTemp + sum ;	
				}
        lengthTemp = sum/5.0; 				  //平均滤波
        return lengthTemp;
}

main.c

#include "stm32f10x.h"
#include "uart.h"
#include "delay.h"
#include "hcsr04.h"
#include "usart.h"
#include "stdio.h"


int main()
{
	  float length = 0;
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
		
	  delay_init();
		uart_init(115200);
		printf("串口初始化成功!\r\n");
		Hcsr04Init();
		printf("HcSr04初始化成功!\r\n");
		while(1)
		{
			length = Hcsr04GetLength();
			printf("距离为 %f cm\r\n",length);
		}
	
}

5.学习补充

补充1:利用正点原子官方模板中system中的usart.c文件里面的uart_init函数来进行串口打印距离。
在这里插入图片描述
但是注意,如果要想使用printf函数打印数据,必须要加入以下语句(正点原子的模板默认是加入了的),否则将无法打印数据:

//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

补充2:静态局部函数不需要在头文件中声明
在hcsr04.c中,使用了static void OpenTimerForHc()static void CloseTimerForHc()两个局部函数,这两个局部函数只服务于hcsr04.c该文件,不需要在hcsr04.h中加以声明。
补充3.us/58——>cm换算原理
声音在干燥、摄氏 20度的空气中的传播速度大约为343米/秒,合34,300厘米/秒。或者,我们作一下单位换算,34,300除以1,000,000厘米/微秒。即为:0.0343厘米/微秒再换一个角度,1/(0.0343 厘米/微秒)即:29.15 微秒/厘米。这就意味着,每291.5微秒表示10CM的距离1厘米就是29.15微秒。但是发送后到接收到回波,声音走过的是2倍的距离。所以实际距离就是1厘米,对应58.3微秒。实际上整个测距过程是测的发出声波到收到回波的时间,你的程序里的第一个distance实际上是时间us。所以换成距离cm,要除以58。当然除以58.3可能更精确。
该补充的参考链接

6.效果展示(可以先过来看效果)

在这里插入图片描述

7.参考链接

[1]百度百科 传感器
[2]博客:us/58——>cm换算原理

8.完整版代码链接

完整版代码下载链接

往期博客:
《OpenMv与Stm32单片机通信》
欢迎大家来访!

  • 41
    点赞
  • 450
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
HC-SR04超声波测距模块是一种常用的测距传感器,可以通过发送超声波脉冲并接收回波信号来测量距离。在STM32库函数版,可以通过以下步骤来使用HC-SR04超声波测距模块: 1. 首先,需要包含"sys.h"头文件,并初始化HC_SR04超声波模块,可以使用HC_SR04_Init()函数进行初始化。\[1\] 2. 在测距之前,需要向Trig控制端输入至少10us的高电平触发信号,可以使用HC_SR04_start()函数发送20us的脉冲触发信号。\[1\] 3. HC-SR04模块内部会发送8个40KHz的方波并检测回波信号,一旦检测到回波信号,Echo接收端会输出高电平回响信号,高电平的持续时间就是超声波从发射到返回的时间。根据公式:距离=高电平时间*声速(340M/S)/2,可以计算出测得的距离。\[2\] 总结来说,使用STM32库函数版的HC-SR04超声波测距模块,需要初始化模块并发送触发信号,然后根据回响信号的高电平时间计算出距离。 #### 引用[.reference_title] - *1* *2* [STM32——库函数版——超声波测距模块](https://blog.csdn.net/qq_45844792/article/details/111215858)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [STM32连接HC-SR04超声波测距(结合STM32CubeMX和HAL库函数)](https://blog.csdn.net/wuwenbin12/article/details/118575989)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wu__La

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值