stm32f103之HC_SR04超声波测距

2023-05-16

参考资料:
stm32与HC-SR04超声波传感器测距
HC-SR04超声波测距注意事项
STM32—驱动HC-SR04超声波测距模块
HC-SR04初识
HC-SR04 超声波原理图讲解与时序分析与arduino使用
HC-SR04超声波原理,波速与温度的关系

用Trig和Echo引脚实现测距的流程:
1.通过Trig输出一段至少10us的高电平(脉冲),触发一次测距,超声波在传输的过程中Echo一直输出高电平。
2.在Trig脉冲输出后,立即检测Echo引脚的电平,测出Echo高电平持续的时间t,t就是超声波在所测距离一个来回所需时间。
感应角度:不大于15度
探测距离:2cm-450cm
高精度可达0.2cm

在这里插入图片描述

利用定时器3的TIM_IT_Update中断来计数,stm32f103时钟是72M, TIM3_Int_Init(1000-1,72-1);//1Mhz的计数频率,1us计数一次,计数到1000为1ms,产生一次溢出中断 ,超声波的速度取344m/s=344mm/ms,具体可更据温度设置,以毫秒为单位乘以速度,当前counter值补足1ms时,把us换算成ms:如图
在这里插入图片描述
计数距离就是用上面的函数得到来回时间(ms为单位),除以2得到单程时间,再乘以速度344mm/ms,得到距离ms为单位)
在这里插入图片描述
2种处理数据的方法(前面两个函数实质一样)
GetLength_Hc()
GetLength2_Hc()
GetLength3_Hc()

主要代码
“timer.h”

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
extern u16 HcCountMs;

void TIM3_Int_Init(u16 arr,u16 psc); 
 
#endif

“timer.c”

#include "timer.h"

u16 HcCountMs=0;
void TIM3_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3, TIM_IT_Update,ENABLE);//使能更新中断,当溢出时产生中断
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设						 
}

void TIM3_IRQHandler(void)   //TIM3中断,一个节拍1us,共1000个节拍,即1ms中断一次
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:溢出中断(更新中断) 
		{
			TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
			HcCountMs++;
		}
}

“hc_sr04.c”

#include "hc_sr04.h"
#include "timer.h"
#include "delay.h"
#include "usart.h"

//#define HCSR04_PORT     GPIOB
//#define HCSR04_CLK      RCC_APB2Periph_GPIOB
//#define HCSR04_TRIG     GPIO_Pin_5
//#define HCSR04_ECHO     GPIO_Pin_6

//#define TRIG_Send  PBout(5) 
//#define ECHO_Reci  PBin(6)
#define N 7
double data[N];
void HC_Init(void)
{ 
 GPIO_InitTypeDef  GPIO_InitStructure;	
 RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);	 //使能时钟
	//触发引脚,推挽输出
 GPIO_InitStructure.GPIO_Pin = HCSR04_TRIG;		 //端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	 //IO口速度为50MHz
 GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);			//
 GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);		 //默认拉低
   //回应引脚,浮空输入
 GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO;	   	//
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //
 GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);	  				 //IO口速度为50MHz
 GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO); 		//默认拉低
	
 TIM3_Int_Init(1000-1,72-1);//1Mhz的计数频率,1us计数一次,计数到1000为1ms,产生一次溢出中断  
}
 
void OpenTimer_Hc(void)
{//每次开始的时候清空
	TIM_SetCounter(TIM3,0);//Counter值清零
	HcCountMs=0;//溢出次数清零
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3外设	
}

void CloseTimer_Hc(void)
{
	TIM_Cmd(TIM3, DISABLE);  //使能TIM3外设	
}

double GetEchoTimeMs_Hc(void)
{
	double t=0;
	t=TIM_GetCounter(TIM3)/1000.0; //us换算成ms
	t+=HcCountMs;//直接用ms计算,算出总的时间,单位ms
	//delay_us(50);
	return t;
}
//通过Trig输出一段至少10us的高电平(脉冲),触发一次测距
void Trig_Hc(void)
{
	TRIG_Send=1;
	delay_us(15);//15us
	TRIG_Send=0;
}
//采集数据
void adoptData_Hc(void)
{
	u8 i;
	double t=0;
	double lengthTemp=0;
	for(i=0;i<N;i++)
	{
		Trig_Hc();//触发超声波模块测距
		while(ECHO_Reci!=1);//等待高电平(低电平就执行,高电平退出)
		OpenTimer_Hc();//此时进入高电平,开启定时器计数
		while(ECHO_Reci==1);//等待低电平(高电平就执行,低电平退出)
		CloseTimer_Hc();//关闭定时器,停止计数
		t=GetEchoTimeMs_Hc();//单位ms
		lengthTemp=(t/2.0)*334;//单位mm,344m/s=344*1000mm/1000ms=344mm/ms
		data[i]=lengthTemp;
	}
}
double GetLength2_Hc(void)
{
	u8 i;
	double sum=0;		
	double average=0;	
	adoptData_Hc();//采集数据
	for(i=0;i<N;i++)
	{
	  sum+=data[i];
	}
	average=sum/N;
	return average;
}
double GetLength3_Hc(void)
{
	u8 i;
	double min=4000;//因为是比最小,0比任何正数小,最大测距是4m,所以选用4000mm
	double max=0;
	double sum=0;		
	double average=0;	
	adoptData_Hc();//采集数据
	//取出最小
	for(i=0;i<N;i++)
	{
	  min=data[i]<min?data[i]:min;
		printf("\r\ndata:%.2fmm\t",data[i]);
	}
	//取出最大
	for(i=0;i<N;i++)
	{
	  max=data[i]>max?data[i]:max;
	}
	printf("\r\nmin:%.2fmm\t",min);
	printf("\r\nmax:%.2fmm\t",max);
	//去掉最大最小,取平均
	for(i=0;i<N;i++)
	{
	  sum+=data[i];	
	}
	sum=sum-min-max;
	average=sum/(N-2);
	return average;
}
double GetLength_Hc(void)
{
	double t=0;
	int i=0;
	double lengthTemp=0;
	double sum=0;	
	while(i!=N)//循环N次
	{
		Trig_Hc();//触发超声波模块测距
		while(ECHO_Reci!=1);//等待高电平(低电平就执行,高电平退出)
		OpenTimer_Hc();//此时进入高电平,开启定时器计数
		while(ECHO_Reci==1);//等待低电平(高电平就执行,低电平退出)
		CloseTimer_Hc();//关闭定时器,停止计数
		t=GetEchoTimeMs_Hc();//单位ms
		lengthTemp=(t/2.0)*334;//单位mm,344m/s=344*1000mm/1000ms=344mm/ms
		sum+=lengthTemp;			
		i=i+1;
	}
	lengthTemp=sum/N;//单位mm
	return lengthTemp;	
}

“main.c”

#include "led.h"
#include "usart.h"
#include "hc_sr04.h"
#include "delay.h"
#include "sys.h"
#include "timer.h"

 int main(void)
 {	
	delay_init();	    	 //延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组2
    uart_init(9600);
	LED_Init();		  	//初始化与LED连接的硬件接口
    HC_Init();
	printf("超声波初始化成功!\r\n"); 
	 
 while(1)
	{
		printf("\r\n平均值:%.2fmm\r\n",GetLength_Hc()); //单位毫米
		//printf("\r\n平均值:%.2fmm\r\n",GetLength2_Hc()); //单位毫米
	    //printf("\r\n平均值:%.2fmm\r\n",GetLength3_Hc()); //单位毫米
		delay_ms(500);//每半秒采集N次
	}
}

测试实验:
在这里插入图片描述

1,当使用GetLength_Hc()获取长度,求和再取平均
在这里插入图片描述
串口现象:第一个值刚开始测距,不准确,理所应当
在这里插入图片描述
2,当使用GetLength2_Hc()获取长度,实际和1一样,求和再取平均
在这里插入图片描述

串口现象:
在这里插入图片描述
3,当使用GetLength3_Hc()获取长度,去掉最大最小,剩下的取平均
在这里插入图片描述

串口现象:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

结论:最后的算法更接近真实距离。
距离大概是272-278mm,可能由于单手改代码测试,另一种手抖也造成了稍微移动,误差多少?起始距离在哪?我也不知道咋参考,请读者赐教,需要源文件的可以私信。
在这里插入图片描述

编程犯的几个错误:
1,比较大小时,采用min=0去比较大小,正数都比0大,请问谁能抢到min这个宝座??
2,double GetLength3_Hc(void)函数中,计算平均值时,忘了打括号写成average=sum/N-2,正确应为average=sum/(N-2);

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

stm32f103之HC_SR04超声波测距 的相关文章

  • STM32F103控制两个步进电机按照一定转速比运动

    这个暑假没有回家 xff0c 在学校准备九月份的电子设计竞赛 今天想给大家分享一下STM32定时器控制两个步进电机按照一定速度比转动的问题 这次做的05年的电子设计竞赛题目 xff0c 运动悬挂系统 本实验是控制两个步进电机通过一个定滑轮用
  • STM32F103笔记(二)——GPIO原理

    GPIO的工作原理与两个实验实例 一 STM32F103 GPIO说明1 stm32 GPIO引脚的主要功能2 GPIO相关配置寄存器的简介3 STM32F103 GPIO的8种工作方式4种输入模式4种输出模式 二 点亮LED实例 xff0
  • STM32F103学习(ADC)

    1 定义 ADC Analog to Digital Converter 模数转换器 是指将连续变化的模拟信号转换为离散的数字信号的器件 2 原理 stm32上的ADC外设采用逐次比较的方式 逐次比较型ADC工作原理可以类比天平称物体 比如
  • stm32f103-gpio源码理解

    提要 xff1a 参照野火的stm32f103开发指南 xff0c 对标准库的构造进行理解 xff1a xff08 1 xff09 使用结构体 xff0c 使用宏 xff0c 使用枚举 xff08 2 xff09 因为参数是可变的 xff0
  • 基于STM32F103与FreeRTOS的自平衡小车实现

    首先移植FreeRTOS到STM32F103上 xff0c 接着就是实现MPU6050的初始化 xff0c 这里移植了正点原子的参考例程 xff0c 基本实现是IIC初始化的 xff0c 读写IIC xff0c 接着就可以配置MPU6050
  • stm32f103最小系统板详细介绍

    一 什么是单片机最小系统 常见的单片机最小系统为单片机能独立运行程序及控制外围电路的最简单电路 xff0c 主要由单片机 晶振电路 复位电路三部分构成 Stm32f103c8t6也不例外 xff0c 构成最小的运行电路也需要以上三部分 St
  • STM32F103 KEIL 标准库直接添加DSP库

    前言 近期由于比赛需要 xff0c 想要在STM32上移植DSP库进行FFT变换 xff0c 找了很多资料都是利用CUBEMX进行导入的方法 xff0c 本人使用的是标准库 xff0c 对HAL库并不熟悉 xff0c 所以考虑到移植的方便采
  • STM32F103笔记(二)——GPIO原理

    GPIO的工作原理与两个实验实例 一 STM32F103 GPIO说明1 stm32 GPIO引脚的主要功能2 GPIO相关配置寄存器的简介3 STM32F103 GPIO的8种工作方式4种输入模式4种输出模式 二 点亮LED实例 xff0
  • STM32F103移植FreeRTOS警告记录

    1 xff1a 新建MDK工程 xff0c 选择文件存放路径 xff0c 选择芯片型号 xff0c 创建一个USER文件 xff0c 复制自动创建的文件到USER文件中 xff0c 关闭程序 创建一个OBJ目标文件夹 xff0c 打开软件选
  • 基于STM32的高精度超声波模块HC-SR04测距

    准备材料 超声波模块 H C S R 04 HC SR04 H C
  • 基于STM32F103的智能门禁系统

    0 前言 本人大二软工菜鸟一枚 xff0c 大神不喜勿喷 1 功能演示 点这里功能演示 2 硬件选型 序号名称备注1STM32F103C8T6开发板用于主控2AS608指纹模块指纹解锁3RFID RC522射频模块刷卡解锁40 96寸四针O
  • RT-Thread Stm32f103开启UART2(中断接收及轮询发送) 使用RT-Thread Studio

    RT Thread Stm32f103开启UART2 使用RT Thread Studio 1 使用RT Thread Studio新建RT Thread项目 2 修改dricer gt doard h 增加UART2的宏定义设置gpio接
  • 机器人技术-HC-SR04超声波传感器数据及机器人避障的应用

    比较详细的HC SR04超声波传感器数据及机器人避障的应用方法 言 超声波传感器概述 超声波传感器型号繁多 价格从几元钱到几百元不等 主要用于检测距离 同时根据声速计算出物体的距离 但超声波传感器有四个缺点 1 声音速度易受温度和风向等环境
  • IMX6ULL与STM32F103的CAN通信实现

    IMX6ULL与STM32F103的CAN通信实现 硬件连接驱动层实现IMX6ULLSTM32F103ZET6 应用层实现IMX6ULLSTM32F103ZET6 结果 在上一篇博文中 xff0c 我们利用USBCAN设备及其上位机软件 x
  • si4438使用stm32f103配置调试成功!

    刚拿到si4438时候在网上找了一大波资源 xff0c 发现能使用的并没有多少 xff0c 于是自己配置一发 经过不懈努力配置成功 xff0c 现在将一些配置过程分享给大家 xff01 源码已上传 尽情下载 xff01 1 首先打开工程文件
  • 使用STM32F103做CAN的收发通信

    下面也是搭建嵌入式系统所必须的一个部分 参考网站 xff1a https www cnblogs com craigtao p 3645148 html https blog csdn net qq 29413829 article det
  • STM32F103 UART4串口使用DMA接收不定长数据和DMA中断发送

    一 前言 使用DMA通信的好处是 不占用单片机资源 不像普通串口中断 发送一个字节触发一次中断 发送100个字节触发100次中断 接收一个字节触发一次中断 接收200个字节触发200次中断 数据接收完毕触发一次DMA中断 发送数据完毕触发一
  • 如何根据芯片手册时序图编写驱动程序

    如何根据芯片手册时序图编写驱动程序 对于电子开发者来说 刚刚拿到一个芯片 常用的芯片可以参考网上的例程来做深入了解 对于一个不常用的芯片来说 Datasheet几乎是使用芯片的唯一的资料 所以根据Datasheet时序图写出对应的驱动程序就
  • STM32进入STOP模式并唤醒实验总结

    项目需求 需要实现设备低功耗功能 实现过程中遇到几个问题 以此记录总结 stm32f103ret6 问题一 执行PWR EnterSTOPMode PWR Regulator LowPower PWR STOPEntry WFI 后 程序继
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系

随机推荐