【STM32F1基础例程13】HC-SR04超声波传感器测距实验

实验简介

     这个实验呢算是这几个实验中稍微稍微“复杂”一点的(当然,对于看到这篇文章的大家来说肯定是超级无敌简单了),关于HC-SR04传感器呢,其实网上有很多很多的资料,但是还是给大家叨叨一些吧稍微。

    HC-SR04是一款广泛使用的超声波测距传感器模块,它能够提供2cm至400cm的非接触式距离测量功能,测量精度可达到3mm 1。该模块包括一个超声波发射器和一个接收器,它们通过超声波信号实现距离测量。当发射器发出超声波信号后,信号会被目标物体反射回来,并由接收器接收。根据超声波从发射到接收的时间差,可以计算出物体与传感器之间的距离 2。

    HC-SR04模块的工作原理基于发送和接收超声波脉冲。模块通过IO口TRIG触发测距,给至少10us的高电平信号后,自动发送8个40kHz的方波并检测是否有信号返回。若有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间即为超声波从发射到返回的时间。根据公式:测试距离 = (高电平时间 × 声速(340m/s)) / 2,可以计算出距离 1。

    模块的电气参数包括工作电压5V、工作电流15mA、工作频率40Hz 5。在使用时,需要注意模块不宜带电连接,测距时被测物体的面积不少于0.5平方米且平面尽量要求平整,以确保测量结果的准确性 2。

    HC-SR04的应用领域包括机器人避障、物体测距、液位检测、公共安防和停车场检测等 13。它的接口包括TRIG触发脉冲输入和ECHO脉冲宽度输出,且支持5V和3.3V功率接口,易于微控制器或Arduino控制 8。

    在实际应用中,可以通过编写程序来控制Trig引脚发送触发信号,并读取Echo引脚的回波时间,从而实现距离测量。例如,在使用Arduino Uno板进行测距时,可以通过定义Trig和Echo引脚,发送一个高电平信号触发测距,并通过pulseIn函数读取Echo引脚的高电平时间,再根据公式计算出距离 8。

    此外,HC-SR04虽然性能稳定且易于使用,但也存在一些局限性,比如声波速度受温度影响、对反射面积和材料有要求、可能受到其他超声波传感器的干扰以及存在2cm的最小测量距离限制 8。尽管如此,HC-SR04因其性价比较高、使用方便,仍然是许多项目中首选的超声波传感器模块。

主要代码

main.c

#include "delay.h"
#include "sys.h"
#include "oled.h"

uint32_t Distance_Calculate(uint32_t count)//传入时间单位10us
{
    uint32_t Distance = 0;
    Distance = (uint32_t)(((float)count *17)/100);//距离单位cm,声速340M/S,时间*速度/2=距离
    return Distance;
}
//1us等待
void Delay_us(uint32_t nus)
{
  uint32_t tickStart, tickCur, tickCnt;
  uint32_t tickMax = SysTick->LOAD;
  uint32_t udelay_value = (SysTick->LOAD/1000)*nus;

  tickStart = SysTick->VAL;
  while(1)
  {
    tickCur = SysTick->VAL;
    tickCnt = (tickStart < tickCur) ? (tickMax+tickStart-tickCur) : (tickStart-tickCur);
    if (tickCnt > udelay_value)
      break;
  }
}
uint32_t Distance;//距离
uint32_t HalTime1,HalTime2;//时间临时变量
extern volatile uint32_t TimeCounter;//时间计数,单位10us


void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM2 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);
}

void RCC_Configuration(void)
{
  /* TIM2 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
void TIM2_Config_Init(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  /* ---------------------------------------------------------------
    72M主频,72分频就是1us,计数到10就是10us中断一次
  --------------------------------------------------------------- */
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 9;//计数到10,产生中断一次
  TIM_TimeBaseStructure.TIM_Prescaler = 71;//72分频
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  /* TIM IT enable */
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  /* TIM2 enable counter */
  TIM_Cmd(TIM2, ENABLE);
}
//PA0配置成输出,PA1配置成输入
void GPIO_Config_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PA端口时钟使能
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;				 //PA0端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//IO口速度为50MHz
 GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;				 //PA0端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 		//下拉输入
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//IO口速度为50MHz
 GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA
 
	
}
//主函数,采用外部8M晶振,72M系统主频,可以在void SetSysClock(void)函数中选择主频率设置
int main(void)
 {	
	
	delay_init();	//延时函数初始化,通过Systick中断实现1ms延时功能  
	GPIO_Config_Init();//PA0配置成输出,PA1配置成下拉输入
	RCC_Configuration();//定时器2时钟使能
	TIM2_Config_Init();//定时器2配置,10us中断一次进入TIM2_IRQHandler
	NVIC_Configuration();//中断使能
	OLED_Init();	//初始化OLED  
	OLED_Clear(); //清屏
	while(1) 
	{		
		GPIO_ResetBits(GPIOA, GPIO_Pin_0);//预先拉低Trig引脚
		delay_ms(5);
		GPIO_SetBits(GPIOA, GPIO_Pin_0);//拉高Trig引脚
		delay_ms(20);
		GPIO_ResetBits(GPIOA, GPIO_Pin_0);//拉低Trig引脚
		Delay_us(20);//等待20us
		while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0);//如果是低电平,一直等
		HalTime1= TimeCounter;
		while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 1);//如果是高电平,一直等
		if(TimeCounter>HalTime1)
		{
			HalTime2 = TimeCounter-HalTime1;
			if(HalTime2<0x300)
			{
					 Distance = Distance_Calculate(HalTime2);//计算距离
			}
		}
	  OLED_Clear();
    OLED_ShowCHinese(18,0,0);//光
		OLED_ShowCHinese(36,0,1);//子
		OLED_ShowCHinese(54,0,2);//物
		OLED_ShowCHinese(72,0,3);//联
		OLED_ShowCHinese(90,0,4);//网
		OLED_ShowString(24,3,"SR04 TEST");
		OLED_ShowString(0,6,"Dis: ");  
		OLED_ShowNum(30,6,Distance,3,16);//显示距离值,单位cm	   
		OLED_ShowString(60,6,"cm"); 
    delay_ms(1000);		
	

	}	  
	
 }

这段主程序的代码用于初始化并使用HC-SR04超声波传感器模块来测量距离。

  1. 头文件包含

    • "delay.h":可能包含延时相关的函数声明。
    • "sys.h":可能包含系统初始化和配置相关的函数。
    • "oled.h":包含OLED显示屏接口的函数。
  2. 距离计算函数

    • Distance_Calculate:根据传入的时间(单位为10us),计算并返回距离(单位为厘米)。
  3. 微秒级延时函数

    • Delay_us:实现微秒级延时功能,使用SysTick定时器来实现。
  4. 全局变量

    • Distance:存储计算出的距离。
    • HalTime1HalTime2:存储时间的临时变量。
    • TimeCounter(外部定义):存储时间计数,单位为10us。
  5. 中断和时钟配置函数

    • NVIC_Configuration:配置NVIC(嵌套向量中断控制器),使能TIM2中断。
    • RCC_Configuration:使能TIM2定时器的时钟。
    • TIM2_Config_Init:初始化TIM2定时器,设置为每10us产生一次中断。
  6. GPIO配置函数

    • GPIO_Config_Init:配置GPIO端口,将PA0设置为输出,PA1设置为输入。
  7. 主函数 main

    • 进行延时、GPIO、定时器和中断的初始化。
    • 进入一个无限循环,周期性地触发HC-SR04传感器进行测量:
      • 将PA0置为低电平,然后置为高电平20ms,再拉低,触发HC-SR04发送超声波。
      • 等待PA1变为高电平,使用TimeCounter记录开始时间HalTime1
      • 再次等待PA1变为低电平,计算两次的时间差HalTime2
      • 如果HalTime2小于0x300(即距离不是很近),调用Distance_Calculate计算距离。
    • 清除OLED屏幕,并显示固定文本和测量的距离值。
    • 每次测量后延时1秒再次测量。

代码中使用了一些外设和中断,以及对GPIO的操作来控制HC-SR04模块发送和接收超声波。通过定时器中断来精确测量超声波的往返时间,并据此计算距离。OLED显示屏用于实时显示测量结果。这个程序就是一个典型的嵌入式系统应用,涉及到硬件控制和用户界面的基本操作。

我收集到的比较完整的代码大家也可以直接下载去试试!!!

  • 13
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好,以下是使用STM32单片机控制HC-SR04超声波避障的例程: #include "stm32f10x.h" #include "delay.h" #include "usart.h" #include "stdio.h" #define TRIG_PIN GPIO_Pin_0 #define ECHO_PIN GPIO_Pin_1 #define TRIG_PORT GPIOA #define ECHO_PORT GPIOA void HC_SR04_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = TRIG_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(TRIG_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ECHO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(ECHO_PORT, &GPIO_InitStructure); } float HC_SR04_GetDistance(void) { uint32_t time; float distance; GPIO_ResetBits(TRIG_PORT, TRIG_PIN); delay_us(2); GPIO_SetBits(TRIG_PORT, TRIG_PIN); delay_us(10); GPIO_ResetBits(TRIG_PORT, TRIG_PIN); while(GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == RESET); time = 0; while(GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == SET) { time++; delay_us(1); } distance = (float)time * 0.017; return distance; } int main(void) { float distance; HC_SR04_Init(); USART1_Init(); while(1) { distance = HC_SR04_GetDistance(); printf("Distance: %.2f cm\r\n", distance); delay_ms(500); } } 这个例程中,我们使用了STM32的GPIO口来控制HC-SR04超声波模块的触发和接收引脚,并通过计算超声波的回波时间来计算距离。在主函数中,我们不断地获取距离并通过串口输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值