使用STM32定时器输入捕获实现HC-SR04超声波测距

一、简单介绍

笔者所使用的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,与串口显示数据一致。

串口显示如下

作者:田甲

物联沃分享整理
物联沃-IOTWORD物联网 » 使用STM32定时器输入捕获实现HC-SR04超声波测距

发表回复