HC-SR04驱动记录

news/2024/7/16 7:16:10 标签: stm32, 单片机, ide, 嵌入式硬件, arm

文章目录

    • 1、工作原理
    • 2、读取数据方式
    • 3、驱动记录

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 的
在这里插入图片描述


http://www.niftyadmin.cn/n/980315.html

相关文章

51Nod-1134 最长递增子序列

1134 最长递增子序列 基准时间限制&#xff1a;1 秒 空间限制&#xff1a;131072 KB 分值: 0 难度&#xff1a;基础题 收藏 关注 给出长度为N的数组&#xff0c;找出这个数组的最长递增子序列。(递增子序列是指&#xff0c;子序列的元素是递增的&#xff09; 例如&#xff1…

归并排序与快速排序

归并 #include<cstdio> #include<cstring> void merge_sort(int a[],int p,int q); void merge (int a[],int p,int r,int q); int main() {int n;scanf("%d",&n);int a[n];for (int i0;i<n;i)scanf("%d",&a[i]);merge_sort(a,0,n…

Shell 中的 if 流程判断语句:

文章目录1、if 语句的格式&#xff1a;2、综合实例&#xff1a;此链接通往 Bash Shell 编程学习的目录导航 &#xff0c;从入门到放弃&#xff0c;感兴趣的可以去看看&#xff1a; 1、if 语句的格式&#xff1a; if 语句很简单&#xff0c;就是满足条件&#xff0c;则执行... …

SPI写OLED(软硬件切换)

文章目录1、SPI读写原理2、模拟SPI驱动3、硬件SPI驱动4、源码1、SPI读写原理 还是一样的&#xff0c;关于屏幕资料&#xff0c;这里有个比较好的网站方便我们进行查阅 0.96inch SPI OLED Module 打开就可以看到我们需要的屏幕资料了 引脚说明 查看数据手册 写数据说明 翻译…

Bash Shell 中的 case 选择语句:

文章目录1、case 语句介绍&#xff1a;2、case 语法格式&#xff1a;3、case 使用例子&#xff1a;此链接通往 Bash Shell 编程学习的目录导航 &#xff0c;从入门到放弃&#xff0c;感兴趣的可以去看看&#xff1a; 1、case 语句介绍&#xff1a; case 选择语句&#xff0c;主…

步进电机驱动控制总结(一)

文章目录1、步进电机驱动原理2、步进电机驱动设计3、步进电机驱动编写4、源码本文驱动的步进电机为较基础的28BYJ-48步进电机&#xff0c;属于入门级水平&#xff0c;比较好驱动&#xff0c;价格也是相对便宜的&#xff0c;因而步进电机驱动开篇就讲他了&#xff01; 1、步进电…

一文教你学会 for循环 的嵌套模式:

文章目录1、for 循环 语法格式&#xff1a;2、for循环嵌套的执行过程&#xff1a;3、利用for基础打印一个矩形&#xff1a;4、使用 for循环嵌套 打印矩形&#xff1a;解释&#xff1a;此链接通往 Bash Shell 编程学习的目录导航 &#xff0c;从入门到放弃&#xff0c;感兴趣的可…

步进电机驱动控制总结(二)

文章目录1、驱动器介绍2、PWM方波直接驱动3、PWMDMA精准控制4、补充说明本次驱动较常见的42步进电机&#xff0c;就是比较标准的那种电机&#xff0c;应该是有一定代表性的&#xff0c;基本可以应付一些大学生比赛什么的了 这里用的两个电机如下所示 1、驱动器介绍 本次实验我…