【STM32】超声波传感器HC-SR04知识

7 篇文章 4 订阅
6 篇文章 4 订阅

一、超声波HC_SR04简介

        超声波传感器模块上面通常有两个超声波元器件,一个用于发射,一个用于接收。

        电路板上有四个引脚:VCC、GND、Trig(触发)、Echo(回应)。

        工作电压与电流:5V,15mA

        感应距离:2~400cm

        感测角度:不小于15度

        被测物体的面积不要小于50平方厘米并且尽量平整

        具备温度补偿电路

二、超声波原理

        距离公式:

        高电平持续时间*声速(340m/s)/2

三、超声波测距步骤

  1. 配置GPIO引脚结构体(Trig,Echo)
  2. 配置定时器4结构体
  3. 配置定时器4中断结构体
  4. 开启时钟(定时器、GPIO)
  5. Trig引脚输出高电平(10us以上),然后关闭
  6. 等待Echo引脚输出高电平开始,定时器打开->开启计数器计数
  7. 等待Echo引脚输出高电平结束,定时器关闭->停止计数器计数

四、硬件接线

  1. GND——GND
  2. VCC——5V
  3. Trig——PB11
  4. Echo——PB10

五、模块化程序

#ifndef __SYS_H
#define __SYS_H	
#include "stm32f10x.h"


#define SYSTEM_SUPPORT_UCOS		0		

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 

#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 


#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //Êä³ö 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //ÊäÈë 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //Êä³ö 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //ÊäÈë 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //Êä³ö 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //ÊäÈë 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //Êä³ö 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //ÊäÈë 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //Êä³ö 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //ÊäÈë

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //Êä³ö 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //ÊäÈë

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //Êä³ö 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //ÊäÈë



void NVIC_Configuration(void);



#endif
#include "sys.h"
#include "stm32f10x.h" 

void NVIC_Configuration(void)
{

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	

}
#include "hc.h"
#include "Delay.h"

#define HCSR04_PORT     GPIOB
#define HCSR04_CLK      RCC_APB2Periph_GPIOB
#define HCSR04_TRIG     GPIO_Pin_11
#define HCSR04_ECHO     GPIO_Pin_10

u16 msHcCount = 0; 

void HC_Init(void)
{  
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;   
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);

    GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;      
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    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);  
    GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);    


    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   

    TIM_DeInit(TIM2);
    TIM_TimeBaseStructure.TIM_Period = (1000-1); 
    TIM_TimeBaseStructure.TIM_Prescaler =(72-1); 
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);          

    TIM_ClearFlag(TIM4, TIM_FLAG_Update);  
    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);    

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;             
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;       
    NVIC_Init(&NVIC_InitStructure);

    TIM_Cmd(TIM4,DISABLE);     
}



static void OpenTimerForHc()  
{
    TIM_SetCounter(TIM4,0);
    msHcCount = 0;
    TIM_Cmd(TIM4, ENABLE); 
}


static void CloseTimerForHc()    
{
    TIM_Cmd(TIM4, DISABLE); 
}


void TIM4_IRQHandler(void)  
{
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)  
   {
       TIM_ClearITPendingBit(TIM4, TIM_IT_Update  ); 
       msHcCount++;
   }
}



  u32 GetEchoTimer(void)
{
    u32 t = 0;
    t = msHcCount*1000;
    t += TIM_GetCounter(TIM4);
    TIM4->CNT = 0;  
    Delay_ms(50);
    return t;
}

  float HC_Get(void )
{
    int t = 0;
    int i = 0;
    float lengthTemp = 0;
    float sum = 0;
    while(i!=5)
   {
       TRIG_Send = 1;      
       Delay_us(20);
       TRIG_Send = 0;
       while(ECHO_Reci == 0);      
       OpenTimerForHc();        
       i = i + 1;
       while(ECHO_Reci == 1);
       CloseTimerForHc();        
       t = GetEchoTimer();        
       lengthTemp = ((float)t/58.0);//cm
       sum = lengthTemp + sum ;

   }
    lengthTemp = sum/5.0;
    return lengthTemp;
}
#ifndef __HC_H
#define __HC_H	
#include "sys.h"

void HC_Init(void);
static void OpenTimerForHc(void);
static void CloseTimerForHc(void);
void TIM4_IRQHandler(void);
u32 GetEchoTimer(void);
float HC_Get(void );

#define TRIG_Send  PBout(11)
#define ECHO_Reci  PBin(10)
#endif
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "HC.h"

uint32_t Length;
float length;


int main(void)
{
	
  OLED_Init();
  OLED_ShowString(1,1,"Length:");
  OLED_ShowString(2,10,"cm");
  HC_Init();

while(1)
	{
		length =HC_Get(); 
		Length = length*100; //eg:54.25->5425
		OLED_ShowNum(2,4,Length/1000,1);  // 千
		OLED_ShowNum(2,5,Length%1000/100,1); //百
		OLED_ShowString(2,6,".");
		OLED_ShowNum(2,7,Length%100/10,1); //十
		OLED_ShowNum(2,8,Length%10/1,1);  //个
		
  }
}

📎测距模块.zip

六、实验现象

附录 串口调试版本

1、连线图

2、调试截图

3、模块化函数(相较于 五、模块化程序 新增部分)

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>

uint8_t Serial_RxData;
uint8_t Serial_RxFlag;

void Serial_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStructure);
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART1, ENABLE);
}

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}

uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}

void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}

int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	return ch;
}

void Serial_Printf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	Serial_SendString(String);
}

uint8_t Serial_GetRxFlag(void)
{
	if (Serial_RxFlag == 1)
	{
		Serial_RxFlag = 0;
		return 1;
	}
	return 0;
}

uint8_t Serial_GetRxData(void)
{
	return Serial_RxData;
}

void USART1_IRQHandler(void)
{
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		Serial_RxData = USART_ReceiveData(USART1);
		Serial_RxFlag = 1;
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}
#ifndef __SERIAL_H
#define __SERIAL_H

#include <stdio.h>

void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);

uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);

#endif
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "HC.h"
#include "Serial.h"

uint32_t Length;
float length;


int main(void)
{
	
	OLED_Init();
	HC_Init();
	Serial_Init();
  OLED_ShowString(1,1,"Length:");
  OLED_ShowString(2,10,"cm");
//	Serial_SendByte(0x41);
//	
//	uint8_t MyArray[] = {0x42, 0x43, 0x44, 0x45};
//	Serial_SendArray(MyArray, 4);
//	
//	Serial_SendString("\r\nNum1=");
//	
//	Serial_SendNumber(111, 3);
//	
//	printf("\r\nNum2=%d", 222);
//	
//	char String[100];
//	sprintf(String, "\r\nNum3=%d", 333);
//	Serial_SendString(String);
//	
//	Serial_Printf("\r\nNum4=%d", 444);
//	Serial_Printf("\r\n");

 
while(1)
	{ 
		length =HC_Get(); 
		Length = length*100; //eg:54.25->5425
		OLED_ShowNum(2,4,Length/1000,1);  // ǧ
		OLED_ShowNum(2,5,Length%1000/100,1); //°Ù
		OLED_ShowString(2,6,".");
		OLED_ShowNum(2,7,Length%100/10,1); //Ê®
		OLED_ShowNum(2,8,Length%10/1,1);  //¸ö
		
		Serial_SendString("The length is:");
		Serial_SendNumber(Length/1000, 1);
		Serial_SendNumber(Length%1000/100, 1);
		Serial_SendString(".");
		Serial_SendNumber(Length%100/10, 1);
		Serial_SendNumber(Length%10/1, 1);
		Serial_Printf("\r\n");
		Delay_ms(500);
		
  }
}

📎测距模块 - 串口调试版本.zip

  • 29
    点赞
  • 228
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
### 回答1: hc-sr04.rar 是一个压缩文件,通常用于存储和传输多个文件或文件夹。hc-sr04 是一种超声波传感器模块,用于测量距离。这个.rar 文件可能包含 hc-sr04 模块的相关文件和文档,如驱动程序、示例代码、使用手册等。使用 .rar 格式进行压缩可以有效地减小文件大小,方便存储和分享。 要使用 hc-sr04.rar 文件,首先需要解压缩。可以使用解压缩软件如WinRAR或7-Zip打开.rar 文件,并将其中的文件提取到指定的目标文件夹中。提取后,可以查看和使用.rar 文件中包含的文件。 对于 hc-sr04.rar 文件来说,其中可能会包含一些示例代码和驱动程序,可以用于连接、设置和使用 hc-sr04 模块。通过参考其中的使用手册,您可以了解有关 hc-sr04 模块的规格、功能和使用方法。 使用 hc-sr04.rar 文件,您可以更方便地获取 hc-sr04 模块的相关资源和文档,并在自己的项目中使用。如果您对 hc-sr04 模块的距离测量功能感兴趣,这个.rar 文件可能会提供您所需的信息和工具。 总之,hc-sr04.rar 是一个存储 hc-sr04 模块相关文件和文档的压缩文件。您可以解压缩、查看和使用其中的文件,以方便您的项目开发和应用。 ### 回答2: HC-SR04.rar是一个压缩文件,包含了HC-SR04超声波测距模块的相关文件。HC-SR04是一种常用的超声波传感器模块,可以用于测距、避障、探测等应用。 HC-SR04.rar文件中可能包含了用户手册、示例代码、驱动程序等相关内容。用户手册可以详细介绍HC-SR04模块的硬件参数、使用方法和注意事项,帮助用户正确使用该模块。示例代码可以提供给用户参考和学习,以便快速上手使用HC-SR04模块。驱动程序则可以帮助用户在不同的开发环境中与HC-SR04模块进行通信和控制。 使用HC-SR04.rar文件,用户首先需要将其解压缩到指定的目录中。然后,用户可以阅读用户手册,了解HC-SR04模块的技术规格和使用方法。根据需要,用户可以参考示例代码,编写自己的应用程序。如果需要在特定的开发环境中使用HC-SR04模块,用户可以查看驱动程序,并按照指引进行安装和配置。 总的来说,HC-SR04.rar文件是一个提供了HC-SR04超声波测距模块的相关资料和工具的压缩文件。它可以帮助用户更好地理解和应用HC-SR04模块,为用户的实际项目开发提供便利。 ### 回答3: hc-sr04.rar 是一个文件的名称,其中的.rar表示该文件是一个压缩包。这个压缩包可能包含有关HC-SR04超声波传感器的相关资料、代码示例、电路设计等。HC-SR04超声波传感器是一种常用的测距传感器,通过发射超声波脉冲并测量其返回时间来计算距离。这种传感器在很多电子项目中都有广泛的应用,例如避障机器人、无人驾驶车辆、门禁系统等。 使用HC-SR04超声波传感器的开发者可以从hc-sr04.rar压缩包中获取包含有关该传感器的信息,比如技术规格、使用方法和示例代码。通过研究和学习这些信息,开发者可以更好地理解和应用HC-SR04超声波传感器。压缩包可能包含有关传感器的详细说明,例如如何连接传感器到微控制器、如何编写代码来读取传感器的数据等。通过使用hc-sr04.rar压缩包中的资源,开发者可以更方便地学习和开发与HC-SR04传感器相关的项目。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值