STM32--超声波模块(HC—SR04)(标准库+HAL库)

一、HC-SR04工作原理

1)采用IO触发测距,给至少10us的高电平信号。

2)模块自动发送8个40KHz的方波,自动检测是否有信号返回。

3)有信号返回,通过IO输出一高电平,高电平持续时间就是超声波从发射到返回的时间声波从发

射到返回的时间。

4)HC-SR04超声波测距模块提供2cm~400cm的测距功能,精度达3mm。

二、实物介绍

以下图片截取自深圳市捷深科技有限公司的《HC-SR04超声波测距模块说明书》:

VCC 3.3-5V供电(推荐5V供电)

GND 接地

Trig 外部触发信号输入,输入一个高于10μs的高电平即可触发模块测距

Echo回响信号输出,测距结束时此管脚输出一个低电平,电平宽度反映超声波往返时间之和

三、工作说明

1、触发信号Trig直接通过IO输出和延时给一个大于10us的高电平即可触发。

2、Echo引脚需要接收并记录高电平的持续时间。

3、在发送触发信号后,Echo响应后(上升沿)触发外部中断,开启定时器计时直到Echo变为低电

平,关闭定时器记录下计时时间。

4、实际应用,如果需要精确距离值,必需要考虑温度影响,做温度补偿。

distance = time * 0.017

距离=T*C/2(C 为声速)

声速温度公式:c=(330.45+0.61t/℃)m/s-1 (其中330.45是在0℃)

0℃声速:330.45m/s20℃声速:342. 62m/s40℃声速:354.85M/S

四、标准库工作代码

我一般使用标准库较少,使用代码时请注意检查

使用OLED显示,OLED使用可以看:

STM32--SPI&IIC使用OLED-CSDN博客

复制代码
uint32_t distance;
while(1)
{
   distance = 0;
   for(int i=0;i<10;++i)
   {  //每次取10次测距数据,取平均值减少误差
      GPIO_SetBits(GPIOA,GPIO_Pin_6);
      Delay_us(15);               //需要提供至少10us的高电平
      GPIO_ResetBits(GPIOA,GPIO_Pin_6);
      Delay_ms(70);              //每个周期至少需要等待60ms
      distance+=(times/5.8);     //获取单位为mm的距离
   }
   distance/=10;
   OLED_ShowNum(2,1,distance,4);    //使用OLED显示
}

//定时器中断函数
//72MHz/72/100=1000,每秒定时器计数1000个,因此每个计数为100us
void TIM2_IRQHandler(void)
{
   if(SET==TIM_GetITStatus(TIM2,TIM_FLAG_Update))
   {
      number++; //每次中断将次数++
      TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
   }
}
 
//外部中断函数,利用外部中断检测高低电平变化来控制定时器开关
void EXTI9_5_IRQHandler(void)
{
   if(SET==EXTI_GetITStatus(EXTI_Line7))
   {
      if(flag==0)
      {	
         //上升沿即回响电平开始,打开计数器
         number=0;flag=1;
         TIM_SetCounter(TIM2,0);
         TIM_Cmd(TIM2,ENABLE);
      }
      else
      {	
         //下降沿即回响电平结束,统计高电平持续时长
         TIM_Cmd(TIM2,DISABLE);
         flag=0;
         times=number*100+TIM_GetCounter(TIM2);  //得到回响的高电平持续的us
      }
      EXTI_ClearITPendingBit(EXTI_Line7);
   }
}

五(1)、HAL--CubeMX配置

GPIO配置(Trig端口):设置PA1为触发端(可更改为其他GPIO口)。单击芯片的PA1引脚会跳

出选择项,选择GPIO_Output,即为GPIO输出。

****定时器配置(Echo端口)********:****为方便计算定时器的分频系数和定时周期,将APB1设置为50MHz。

先设置TIM2的通道1位直接模式输入捕获,在参数设置中设置预分频为71,通过计算分频器输出的

时钟信号频率为1000kHz,通过换算得到1us,极性为上升沿触发。设置完成后自动引出PA0引

脚,即为接收端引脚Echo,使能NVIC中断。

USART1配置:串口输出显示结果,设置为异步模式,波特率为115200Bits/s,

RX--PA10//TX--PA9

五(2)、HAL库工作代码

1、HCSR04.h

复制代码
#ifndef __HCSR04_H
#define __HCSR04_H

#include "main.h"
//#include "tim.h"
#include "stdio.h"
 
#define TRIG_H  HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_SET)
#define TRIG_L  HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_RESET)
 
void delay_us(uint32_t us);
void HCSR04_GetData(void);
 
#endif

2、HCSR04.c

复制代码
#include "HCSR04.h"
 
float distance;      //测量距离
uint32_t Buf[3] = {0};   //存放定时器计数值的数组
uint8_t  Cnt = 0;    //状态标志位
uint32_t high_time;   //超声波模块返回的高电平时间

//读取距离
void HCSR04_GetData(void)
{
   switch(Cnt)
   {
      case 0:
         TRIG_H;    //发送信号
         delay_us(30);
         TRIG_L;
       
         Cnt++;    //标志位为1
         __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
         HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);    //开启TIM2    
         //启动输入捕获或者:__HAL_TIM_ENABLE(&htim5);                                                                                    		
      break;
      case 3:
         high_time = Buf[1]- Buf[0];    //计算高电平时间
         printf("
----高电平时间-%d-us----
",high_time);    //串口打印时间						
         distance=(high_time*0.034)/2;  //计算距离单位cm
         printf("
-检测距离为-%.2f-cm-
",distance);         //串口打印距离     
         Cnt = 0;  //清空标志位
         TIM2->CNT=0;     //清空计时器计数
      break;	
	}
}

//中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(TIM2 == htim->Instance)// 判断触发的中断的定时器为TIM2
	{
		switch(Cnt)
        {
			case 1:
                //获取当前的捕获值
				Buf[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
                //设置为下降沿捕获!!!
              __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);  													
				Cnt++;                                            
			break;              
			case 2:
                //获取当前的捕获值
				Buf[1] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
				HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1); 
                //停止捕获或者: __HAL_TIM_DISABLE(&htim5);
				Cnt++;      //此时标志位为3
        break;
		}
	}
}
相关推荐
-Springer-2 小时前
STM32 学习 —— 个人学习笔记5(EXTI 外部中断 & 对射式红外传感器及旋转编码器计数)
笔记·stm32·学习
LS_learner2 小时前
树莓派(ARM64 架构)Ubuntu 24.04 (Noble) 系统 `apt update` 报错解决方案
嵌入式硬件
来自晴朗的明天3 小时前
16、电压跟随器(缓冲器)电路
单片机·嵌入式硬件·硬件工程
钰珠AIOT3 小时前
在同一块电路板上同时存在 0805 0603 不同的封装有什么利弊?
嵌入式硬件
代码游侠3 小时前
复习——Linux设备驱动开发笔记
linux·arm开发·驱动开发·笔记·嵌入式硬件·架构
代码游侠14 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
xuxg200516 小时前
4G 模组 AT 命令解析框架课程正式发布
stm32·嵌入式·at命令解析框架
CODECOLLECT18 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen18 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制