HC-SR04驱动记录

1、工作原理

常用的HC-SR04模块如下所示:
在这里插入图片描述
引脚说明:

引脚 说明
VCC 电源,常用5v
Trig 控制端
Echo 接收端
GND

使用说明:
控制端发送一个10us的高电平脉冲,之后再接收口等待高电平输出,一有高电平输出就开始计时,直到低电平到来就可以结束计时,速度X时间,就是我们测量到的距离了。

时序图说明
在这里插入图片描述

其他说明:

  • 调节测距长短
    在这里插入图片描述
    图中标志的电阻可以调节最大探测距离。R3电阻为392,探测距离最大4.5M左右,探测角度小于15度;R3电阻为472,探测距离最大7M左右,探测角度小于30度;出厂默认392,即最大探测距离4.5M左右。R3电阻大,接收部分增益高,检测距离大,但检测角度会相应变大,容易检测到前方旁边的物体。
  • 提高测距有效性:
    测距时,被测物体的面积不少于0.5平方米且要尽量平整。否则会影响测试结果。

2、读取数据方式

说白了就是发脉冲然后计数,所以关键问题在于计数的方式上,可以选的方式如下:

  • 延时函数
  • 定时器计数
  • 输入捕获

这里用延时函数的方法肯定是会打断整个系统的进程的,虽然时间很短,但是也会有一定影响,使用定时器输入捕获应该是要配合中断来使用,缺点是要废掉一个定时器,采用输入捕获应该是最高精度的方法了,但是同样的也要废掉一个定时器!!!

关于定时器的使用可以看我之前的一篇文章,较全面的总结了定时器的使用方法:stm32外设总结-定时器使用

3、驱动记录

这里还是采用输入捕获的方法来测试,其他两个方法都比较直白,只是编写下逻辑函数就行的,就不做演示了

用的就是PWM输入的方式

在这里插入图片描述
CH1上升沿,CH2下降沿
在这里插入图片描述

打开中断
在这里插入图片描述

配置控制引脚
在这里插入图片描述

之后就可以生成代码了

编写测量函数
在这里插入图片描述
源代码:

#include "HC-SR04.h"
#include "tim.h"




#define fac_us 72   //时钟频率,单位MHZ

/*微秒级延时函数*/
void delay_us(uint32_t nus)
{
    
    
	uint32_t ticks;
	uint32_t told,tnow,tcnt=0;
	uint32_t reload=SysTick->LOAD;			//LOAD的值
	ticks=nus*fac_us; 						//需要的节拍数
	told=SysTick->VAL;        				//刚进入时的计数器值
	while(1)
	{
    
    
		tnow=SysTick->VAL;
		if(tnow!=told)
		{
    
    
			if(tnow<told)tcnt+=told-tnow;	//这里注意一下SYSTICK是一个递减的计数器就可以了.
			else tcnt+=reload-tnow+told;
			told=tnow;
			if(tcnt>=ticks)break;			//时间超过/等于要延迟的时间,则退出.
		}
	}
}

static void HC_SR04_Start()
{
    
    
	HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
	delay_us(10);
	HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
}

static uint16_t HCSR04_get_measure()
{
    
    
	HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2);

	measure_flag = 1;
	HC_SR04_Start();

	while(measure_flag);

	return pulse_time;
}

float HCSR04_get_distance_cm()
{
    
    
	float distance_cm;
	distance_cm = HCSR04_get_measure() / 58.0f;

	return distance_cm;
}

中断的数据处理函数
在这里插入图片描述
源代码

float dis = 0;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    
    
	if(htim == &htim1)
	{
    
    
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
    
    
			IC_RisingEdge = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_1);
			HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);

		}
		else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
		{
    
    
			pulse_time = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_2) - IC_RisingEdge;
			measure_flag = 0;
			HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2);
		}
	}
}

之后读数据就OK了
在这里插入图片描述
将程序下载到开发板,调试查看数据效果如下,基本OK 的
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_51220742/article/details/123596731