资讯详情

基于STM32的超声波HC-SR04和红外测距模块测量距离的实验对比(HAL库)

本文主要是为了下测距做的,本实验主要包括(HC-SR04)和(SHARP GP2Y0A21YK0F)。两个模块的测距原理和编程实验方法不同,测距效果也大不相同。有兴趣的读者可以看看这篇文章。文章末尾有实验

STM32F103C8T6;OLED;超声模块:HC-SR04及红外测距模块:SHARP GP2Y0A21YK0F

VCC --> VCC

GND --> GND

Trig --> PA5

Echo --> PA0

VCC --> VCC

GND --> GND

Vo(数据) --> PA1

超声波是振动频率机械波。它具有频率高、波长短、绕射现象小、方向性好等特点适用于大学生、工程师、技术人员和电子爱好者。

,性能远超老版HC-SRO4、US-015测距精度高于旧版HC-SRO4和US-在015的情况下,测距范围更远,,远超一般超声波测距模块。CS-100A超声波测距SOC芯片,高性能,工业级,宽电压,低价格,只有普通超声波测距模块的一半,性能远远超过普通超声波测距模块。US-均采用025相同

CS100A

DC 3V-5.5V

5.3mA

-40℃-85℃

GPI0

小于15度

2cm~600cm

0.1cm 1%

1、采用测量距离个测量距离us的高电平;

自动发送模块,自动检测是否有信号返回;

3.信号返回,通过、高电平就是,测试距离=();

该模块有一个接口:。为2.54mm如图所示:从左到右依次编号,它们的定义如下∶

接VCC电源(直流3V-5.5V)。

连接外部电路,输入一个管脚模块测距可触发高电平。

连接外部电路,当测距结束时,管脚将输出高电平超声波往返

连接外部电路的地面。

上面的时序图表明你只需要提供模块内部触发信号

输出回波信号

回响信号的与所测的。距离可以通过发射信号到收到的回响信号的时间间隔来计算。

us/58-厘米或者uS/148-英寸;或:

1.该模块不应带电连接。如果要带电连接,请先让模块连接GND先连接,否则会影响模块的正常工作。

2.测距时,被测物体的面积不小于0.平面应尽可能平整,否则会影响测量结果。

/span>是测距传感器单元的集成组合构成(位置敏感探测器),IRED((红外发光二极管)和信号处理电路的各种物体的反射率,对受到影响的距离检测由于采用,这个装置输出对应于该电压检测距离,所以这种传感器还可以来作为

4.5~5.5V DC

典型30mA

-10~60℃

-40~70℃

10~80cm

①Vo:模拟电压输出        

②GND:地

③VCC:电源正

         从上图就可以明显看出,该模块不成单调关系,故一般该传感器的有效值在

篇幅有限,如果这方面不熟悉的朋友可以去看看本人的另一篇文章,十分相近,希望对您有所帮助。【强烈推荐】基于stm32的OLED各种显示实现(含动态图)_混分巨兽龙某某的博客-CSDN博客https://blog.csdn.net/black_sneak/article/details/125418537?spm=1001.2014.3001.5501

四、CubexMX配置

晶振(精度更高)——HSE;

          );

        

设置定时器为上升沿捕获并连接到超声波模块的,记得(涉及到捕获中断+定时器溢出中断)。

       

       

ADC的时钟频率,否则会影响精度(8~12Mhz)

五、代码

5.1 超声波

        其实,超声波HC-SR04的驱动就是。同时,由于超声波测距模块是基于的物理性质,去进行距离测量,故此其精度受到

温度,传播介质及其物理属性等

        本次实验就不进行超声波模块的精度补偿了,后面有空可以给大家出一个相关的文章。

#ifndef HCSR04_H_
#define HCSR04_H_

#include "main.h"
#include "delay.h"

typedef struct
{
	uint8_t  edge_state;
	uint16_t tim_overflow_counter;
	uint32_t prescaler;
	uint32_t period;
	uint32_t t1;	//	上升沿时间
	uint32_t t2;	//	下降沿时间
	uint32_t high_level_us;	//	高电平持续时间
	float    distance;
	TIM_TypeDef* instance;
    uint32_t ic_tim_ch;
	HAL_TIM_ActiveChannel active_channel;
}Hcsr04InfoTypeDef;

extern Hcsr04InfoTypeDef Hcsr04Info;

/**
 * @description: 超声波模块的输入捕获定时器通道初始化
 * @param {TIM_HandleTypeDef} *htim
 * @param {uint32_t} Channel
 * @return {*}
 */
void Hcsr04Init(TIM_HandleTypeDef *htim, uint32_t Channel);

/**
 * @description: HC-SR04触发
 * @param {*}
 * @return {*}
 */
void Hcsr04Start();

/**
 * @description: 定时器计数溢出中断处理函数
 * @param {*}    main.c中重定义void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
 * @return {*}
 */
void Hcsr04TimOverflowIsr(TIM_HandleTypeDef *htim);

/**
 * @description: 输入捕获计算高电平时间->距离
 * @param {*}    main.c中重定义void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
 * @return {*}
 */
void Hcsr04TimIcIsr(TIM_HandleTypeDef* htim);

/**
 * @description: 读取距离 
 * @param {*}
 * @return {*}
 */
float Hcsr04Read();

#endif /* HCSR04_H_ */

#include "hc-sr04.h"

Hcsr04InfoTypeDef Hcsr04Info;

/**
 * @description: 超声波模块的输入捕获定时器通道初始化
 * @param {TIM_HandleTypeDef} *htim
 * @param {uint32_t} Channel
 * @return {*}
 */
void Hcsr04Init(TIM_HandleTypeDef *htim, uint32_t Channel)
{
  /*--------[ Configure The HCSR04 IC Timer Channel ] */
  // MX_TIM2_Init();  // cubemx中配置
  Hcsr04Info.prescaler = htim->Init.Prescaler; //  72-1
  Hcsr04Info.period = htim->Init.Period;       //  65535

  Hcsr04Info.instance = htim->Instance;        //  TIM2
  Hcsr04Info.ic_tim_ch = Channel;
  if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_1)
  {
    Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_1;             //  TIM_CHANNEL_4
  }
  else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_2)
  {
    Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_2;             //  TIM_CHANNEL_4
  }
  else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_3)
  {
    Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_3;             //  TIM_CHANNEL_4
  }
  else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_4)
  {
    Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_4;             //  TIM_CHANNEL_4
  }
  else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_4)
  {
    Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_4;             //  TIM_CHANNEL_4
  }
  /*--------[ Start The ICU Channel ]-------*/
  HAL_TIM_Base_Start_IT(htim);
  HAL_TIM_IC_Start_IT(htim, Channel);
}

/**
 * @description: HC-SR04触发
 * @param {*}
 * @return {*}
 */
void Hcsr04Start()
{
  HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
  DelayUs(10);  //  10us以上
  HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
}

/**
 * @description: 定时器计数溢出中断处理函数
 * @param {*}    main.c中重定义void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
 * @return {*}
 */
void Hcsr04TimOverflowIsr(TIM_HandleTypeDef *htim)
{
  if(htim->Instance == Hcsr04Info.instance) //  TIM2
  {
    Hcsr04Info.tim_overflow_counter++;
  }
}

/**
 * @description: 输入捕获计算高电平时间->距离
 * @param {*}    main.c中重定义void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
 * @return {*}
 */
void Hcsr04TimIcIsr(TIM_HandleTypeDef* htim)
{
  if((htim->Instance == Hcsr04Info.instance) && (htim->Channel == Hcsr04Info.active_channel))
  {
    if(Hcsr04Info.edge_state == 0)      //  捕获上升沿
    {
      // 得到上升沿开始时间T1,并更改输入捕获为下降沿
      Hcsr04Info.t1 = HAL_TIM_ReadCapturedValue(htim, Hcsr04Info.ic_tim_ch);
      __HAL_TIM_SET_CAPTUREPOLARITY(htim, Hcsr04Info.ic_tim_ch, TIM_INPUTCHANNELPOLARITY_FALLING);
      Hcsr04Info.tim_overflow_counter = 0;  //  定时器溢出计数器清零
      Hcsr04Info.edge_state = 1;        //  上升沿、下降沿捕获标志位
    }
    else if(Hcsr04Info.edge_state == 1) //  捕获下降沿
    {
      // 捕获下降沿时间T2,并计算高电平时间
      Hcsr04Info.t2 = HAL_TIM_ReadCapturedValue(htim, Hcsr04Info.ic_tim_ch);
      Hcsr04Info.t2 += Hcsr04Info.tim_overflow_counter * Hcsr04Info.period; //  需要考虑定时器溢出中断
      Hcsr04Info.high_level_us = Hcsr04Info.t2 - Hcsr04Info.t1; //  高电平持续时间 = 下降沿时间点 - 上升沿时间点
      // 计算距离
      Hcsr04Info.distance = (Hcsr04Info.high_level_us / 1000000.0) * 340.0 / 2.0 * 100.0;
      // 重新开启上升沿捕获
      Hcsr04Info.edge_state = 0;  //  一次采集完毕,清零
      __HAL_TIM_SET_CAPTUREPOLARITY(htim, Hcsr04Info.ic_tim_ch, TIM_INPUTCHANNELPOLARITY_RISING);
    }
  }
}

/**
 * @description: 读取距离 
 * @param {*}
 * @return {*}
 */
float Hcsr04Read()
{
  // 测距结果限幅
  if(Hcsr04Info.distance >= 500)
  {
    Hcsr04Info.distance = 500;        //元器件资料说是600cm最高距离,这里保守一点
  }
  return Hcsr04Info.distance;
}

        由于利用中断去读取定时测算的脉冲距离,所以这里需要重写

/* USER CODE BEGIN 4 */
/**
 * @description: 定时器输出捕获中断
 * @param {TIM_HandleTypeDef} *htim
 * @return {*}
 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)    //捕获回调函数
{
  Hcsr04TimIcIsr(htim);
}

/**
 * @description: 定时器溢出中断
 * @param {*}
 * @return {*}
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)    //在中断回调函数中添加用户代码
{
  Hcsr04TimOverflowIsr(htim);
}
/* USER CODE END 4 */

其实,红外测距模块就是,通过电压结合手册中电压与距离的得到计算的距离。

#ifndef __SHARP2Y0A21_H
#define __SHARP2Y0A21_H	

#include "main.h"


#define Adc1IN1Distance_READ_TIMES	10		//定义红外传感器读取次数,以便取平均值
 
void DistanceSensor_Init(void); 				//初始化红外传感器
float DistanceSensor_Get_Val(void);				//读取红外传感器的值


#endif 

#include "sharp.h"
#include "adc.h"
#include "main.h"
#include "stdio.h"

//初始化ADC,不用修改
//这里我们仅以规则通道为例														   
		  
//初始化传感器,需要修改端口和引脚号,这里是c出口,c1引脚,ADC1的IN1
void DistanceSensor_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA时钟
	
  //先初始化ADC1通道11 IO口
  GPIO_InitStructure.Pin = GPIO_PIN_1;//PA1
  GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;//模拟输入
  GPIO_InitStructure.Pull = GPIO_NOPULL ;//不带上下拉
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化  
	
 
	MX_ADC1_Init();//初始化ADC1
}
//PA1=IN1
float DistanceSensor_Get_Val(void)
{
	uint32_t temp_val=0;
	float distemp=0.0;
	uint8_t t;
	for(t=0;t<Adc1IN1Distance_READ_TIMES;t++)
	{
		temp_val+=HAL_ADC_GetValue(&hadc1);	//读取ADC值,通道1
		HAL_Delay(5);
	}
	temp_val/=Adc1IN1Distance_READ_TIMES;//得到平均值,这个是平均的ADC,
	distemp=temp_val*3.3/4095;

	//电压对应距离
	distemp=(-13.2*distemp*distemp*distemp)+72.84*distemp*distemp-140*distemp+107.12;
  return distemp;

}

5.3 OLED显示代码

        OLED模块作为常用的数据输出显示模块,应该是必须要掌握的。如果有朋友不是很熟悉,可以去参考本人上面提到的那篇文章,十分详尽!!!

        本实验的目的是需要对比一下的效果怎么样。其精度最高越好,这里就需要考虑到

//z_len为整数显示位数,f_len为小数显示位数,size2为字体大小
void OLED_Showdecimal(u8 x,u8 y,float num,u8 z_len,u8 f_len,u8 size2)
{         	
	u8 t,temp;
	u8 enshow;
	int z_temp,f_temp;      
	z_temp=(int)num;
	//整数部分
	for(t=0;t<z_len;t++)
	{
		temp=(z_temp/oled_pow(10,z_len-t-1))%10;
		if(enshow==0 && t<(z_len-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
				continue;
			}
			else
			enshow=1;
		}
		OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); 
	}
	//小数点
	OLED_ShowChar(x+(size2/2)*(z_len),y,'.',size2); 
	
	f_temp=(int)((num-z_temp)*(oled_pow(10,f_len)));
  //小数部分
	for(t=0;t<f_len;t++)
	{
		temp=(f_temp/oled_pow(10,f_len-t-1))%10;
		OLED_ShowChar(x+(size2/2)*(t+z_len)+5,y,temp+'0',size2); 
	}
}

5.4 main函数

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C2_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  OLED_Init();
  OLED_CLS();
  Hcsr04Init(&htim2, TIM_CHANNEL_1);  // 通道选择
  Hcsr04Start();  //  启动超声波
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		//显示实验对比
		OLED_ShowCN_STR(30,0,0,4);
		
		//红外测距显示
		HAL_ADC_Start(&hadc1);
        adcx=HAL_ADC_GetValue(&hadc1);
		distance=DistanceSensor_Get_Val();
		OLED_ShowCN_STR(0,2,4,5);
		OLED_Showdecimal(80,2,distance,3,2,16);
		
		
		//超声波测距显示
		Hcsr04Start();
		OLED_ShowCN_STR(0,4,9,5);
		OLED_Showdecimal(80,4,Hcsr04Read(),3,2,16);

		//显示单位
		OLED_ShowCN_STR(30,6,14,5);
				
  }
  /* USER CODE END 3 */
}

六、实验效果

测距模块对比实验

        经过本人由于拍摄不方便,但是效果还是很明显的。经过笔者反复标定测试发现,测距的效果从等都略优于。而且,超声波模块比红外测距模块便宜很多,emmm,不是很理解其意义所作。当然,超声波模块在很多情况下是需要的。

代码开源

        https://pan.baidu.com/s/1ouwFLF8ru9DROIFSZnEITg dktp

标签: 二极管能不能通过三角波gp集成电路sr204二极管参数二极管sr3100参数二极管sr845sharp红外线传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台