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;
		}
	}
}
相关推荐
嵌入式科普1 小时前
嵌入式科普(24)从SPI和CAN通信重新理解“全双工”
c语言·stm32·can·spi·全双工·ra6m5
重生之我是数学王子2 小时前
点亮核心板小灯 STM32U575
stm32·单片机·嵌入式硬件
end_SJ2 小时前
初学stm32 --- 定时器中断
stm32·单片机·嵌入式硬件
南城花随雪。2 小时前
单片机:实现数码管动态显示(0~99999999)74hc138驱动(附带源码)
单片机·嵌入式硬件
南城花随雪。4 小时前
单片机:实现信号发生器(附带源码)
单片机·嵌入式硬件
灵槐梦5 小时前
【速成51单片机】2.点亮LED
c语言·开发语言·经验分享·笔记·单片机·51单片机
三月七(爱看动漫的程序员)6 小时前
HiQA: A Hierarchical Contextual Augmentation RAG for Multi-Documents QA---附录
人工智能·单片机·嵌入式硬件·物联网·机器学习·语言模型·自然语言处理
新晨单片机设计7 小时前
【087】基于51单片机智能宠物喂食器【Proteus仿真+Keil程序+报告+原理图】
嵌入式硬件·51单片机·proteus·宠物·ad原理图
大风起兮128 小时前
STM32HAL库中RTC闹钟设置时分秒,年月日
stm32·嵌入式硬件
超能力MAX8 小时前
IIC驱动EEPROM
单片机·嵌入式硬件·fpga开发