【STM32】超声波测距模块HC-SR04用定时器输入捕获实现测距

本文详细介绍了如何在STM32F103CBT6单片机上利用SR04模块进行超声波测距,包括电路连接、CUBEMx中TIM2的配置、代码编写和测量原理。通过HAL库实现中断处理和数据计算。
摘要由CSDN通过智能技术生成

一、简单介绍

笔者所使用的SR04模块如下图所示

二、工作原理

三、电路连接

笔者的单片机为STM32F103CBT6,使用TIM2的通道1作为输入捕获通道,PA1作为触发的GPIO

因此接线如下

VCC-->3V3

ECHO-->PA0

TRIG-->PA1

GND-->GND

四、cubemx配置

配置定时器2

需要开启定时器2的中断

开启串口1作为显示输出

时钟配置

五、代码编写

添加串口重定向代码至usart.c文件中

/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

        根据工作原理,思路非常简单:我们想要测距的时候,在TRIG引脚产生一个高电平持续至少10us的脉冲,超声波模块就会启动,然后也返回一个脉冲,我们只需要测量这个脉冲的高电平持续时间就能知道距离。

        在输入捕获回调函数中进行配置,因为当通道捕获到高电平时,就要立刻设置捕获策略为捕获低电平,否则无法测量高电平持续时间,得到的只不过是两个上升沿的时间间隔罢了。

        考虑定义一个结构体用来存放信息。

代码如下

SR04.c

#include "sr04.h"

SR04_PulseType pulse;


void SR04_Init()
{
	HAL_TIM_Base_Start_IT(&SR04_TIM);
	HAL_TIM_IC_Start_IT(&SR04_TIM,SR04_CHANNEL);
}
void SR04_Start()
{
	HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_SET);
	HAL_Delay(1);
	HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_RESET);
	
	pulse.rising_flag =1;
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(pulse.rising_flag)
	{
		pulse.start = HAL_TIM_ReadCapturedValue(&SR04_TIM,SR04_CHANNEL);
		__HAL_TIM_SET_CAPTUREPOLARITY(&SR04_TIM,SR04_CHANNEL,TIM_INPUTCHANNELPOLARITY_FALLING);
		pulse.rising_flag = 0;
	}
	else
	{
		__HAL_TIM_SET_CAPTUREPOLARITY(&SR04_TIM,SR04_CHANNEL,TIM_INPUTCHANNELPOLARITY_RISING);
		pulse.end = HAL_TIM_ReadCapturedValue(&SR04_TIM,SR04_CHANNEL);
		pulse.rising_flag = 1;
	}
}


void SR04_Calculate()
{
	if(pulse.end > pulse.start)
		pulse.cnt = pulse.end - pulse.start; 
	else
		pulse.cnt = SR04_COUNT_PERIOD + pulse.end - pulse.start; 
	pulse.distance = pulse.cnt * SPEED *100 / 2.0f /1000.0f /1000.0f;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	
}

sr04.h

#ifndef SR04_H
#define SR04_H

#include "main.h"
#include "tim.h"
#include "stdio.h"


#define SPEED 				340.0f
#define SR04_TIM 			htim2
#define SR04_CHANNEL 		TIM_CHANNEL_1
#define SR04_COUNT_PERIOD 	10000


typedef struct
{
	uint16_t start;
	uint16_t end;
	uint16_t cnt;
	float distance;
	uint8_t rising_flag;
}SR04_PulseType;


extern SR04_PulseType pulse;


void SR04_Init();
void SR04_Start();
void SR04_Calculate();

#endif

主函数主要代码

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  SR04_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  	SR04_Start();
	SR04_Calculate();
    printf("%d\t%.3fmm\r\n",pulse.cnt,pulse.distance);
	HAL_Delay(200);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

波形如下

高电平持续时间约为472us,与串口显示数据一致。

串口显示如下

  • 13
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一种可能的 STM32 驱动 HC-SR04 超声波测距模块的程序代码: ```c #include "stm32f4xx.h" #define TRIG_PIN GPIO_Pin_10 #define ECHO_PIN GPIO_Pin_9 #define GPIO_PORT GPIOA void delay_us(uint32_t us) { uint32_t count = us * (SystemCoreClock / 1000000); while(count--); } void HC_SR04_Init(void) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = TRIG_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = ECHO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIO_PORT, &GPIO_InitStruct); } float HC_SR04_Read(void) { GPIO_WriteBit(GPIO_PORT, TRIG_PIN, Bit_SET); delay_us(10); GPIO_WriteBit(GPIO_PORT, TRIG_PIN, Bit_RESET); uint32_t count = 0; while(GPIO_ReadInputDataBit(GPIO_PORT, ECHO_PIN) == Bit_RESET) { count++; delay_us(1); if(count > 50000) return -1.0f; } uint32_t time_start = TIM1->CNT; while(GPIO_ReadInputDataBit(GPIO_PORT, ECHO_PIN) == Bit_SET) { count++; delay_us(1); if(count > 50000) return -1.0f; } uint32_t time_end = TIM1->CNT; float time_diff = (float)(time_end - time_start) / 1000.0f; return time_diff * 0.34f / 2.0f; // distance in cm } int main(void) { SystemInit(); HC_SR04_Init(); while(1) { float distance = HC_SR04_Read(); if(distance >= 0) { printf("Distance: %.2f cm\n", distance); } else { printf("Error\n"); } delay_us(500000); } return 0; } ``` 注意:这段程序并没有经过完整验证,仅供参考。实际上还需要配置定时器 TIM1,以及可能需要调整延时函数 delay_us 的实现方式。同时需要注意 HC-SR04 需要使用 5V 电源,因此还需要将 STM32 的 PB2 引脚(VDD)连接到 HC-SR04 的 Vcc 引脚。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值