首页 > 其他分享 >最详细STM32,cubeMX 超声波测距

最详细STM32,cubeMX 超声波测距

时间:2023-11-09 21:31:34浏览次数:47  
标签:定时器 HAL 信号 us STM32 TIM cubeMX GPIO 测距

这篇文章将详细介绍 STM32使用 cubeMX驱动超声波测距 。

@TOC


前言

  • 实验材料:STM32F103C8T6开发板, HC-SR04 超声波模块。
  • 所需软件:keil5 , cubeMX ,AiThinker Serial Tool 串口助手。
  • 实验目的:了解 STM32使用 cubeMX驱动超声波 。
  • 实验:超声波测距。

一、超声波模块

HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能。有4 个引脚:VCC, GND, Trig(信号触发引脚),Echo(接收返回信号)。

当超声波发出一个信号时,信号碰到物体或阻碍后会立即返回。只要得到 信号往返传输的时间就可以测出距离。

最详细STM32,cubeMX 超声波测距_外部中断

参数列表: 工作电压 VCC5 V 最远射程 : 4m 最近射程 :2cm 信号传输速度 :340m/s

测距原理

下图是 超声波时序图。

  1. 首先让超声波的 trig 引脚发送触发信号:一个 10 us 的 TTL 高电平。
  2. 然后模块内部会自动循环发出 8 个 40 KHZ 的脉冲。
  3. 接着 超声波的 echo 引脚会接收到回返信号。
  4. 最后只需要计算出这段回返信号的高电平时间 再带入公式 S = 340(m/s) * T(s) / 2 即可算出距离.这里是往返时间,要除 2。(因为 高电平的时间就是信号往返传输的时间)
  5. 最详细STM32,cubeMX 超声波测距_串口_02

二、cubeMX 配置

对于基础的配置可以看我之前的文章。

  1. 由于 要发送一个 10us 的高电平,这个时间用定时器进行配置,所以这里我使用 定时器 2 进行延时。(尽量不要使用 HAL_Delay 函数,多次使用会导致程序卡顿)

这里选择内部时钟源,并配置相关参数。这里配置的参数是 1us 延时。

最详细STM32,cubeMX 超声波测距_串口_03

  1. 我们还需要 一个定时器去 计算回返信号的高电平时间。使用定时器3。配置的定时时间依然是 1us。

如果对 定时器的定时时长有不了解的可以参考我之前的文章:最详细STM32,cubeMX 定时器

最详细STM32,cubeMX 超声波测距_外部中断_04

  1. 需要将测出的距离使用串口助手打印出来,所以这里需要使用一个 串口 USART2.(使用 异步传输)

如果对 串口的配置有不了解的可以参考我之前的文章:最详细STM32,cubeMX串口发送,接收数据

最详细STM32,cubeMX 超声波测距_引脚_05

  1. 对于检测 是否接收到 回返信号 ,可以使用外部中断。

超声波需要两个引脚分别用来 发送触发信号 ,接收回返信号。所以,这里我使用 PB3 用来 发送触发信号,设置为输出引脚。使用 PB6 接收信号,并将其设置为 外部中断模式。

如果对 外部中断的配置有不了解的可以参考我之前的文章:STM32不使用 cubeMX实现外部中断

最详细STM32,cubeMX 超声波测距_串口_06

  • 并将 PB6 设置为 双边沿触发中断。
  • 最详细STM32,cubeMX 超声波测距_外部中断_07

  • 并将外部中断使能。
  • 最详细STM32,cubeMX 超声波测距_引脚_08

三、实验程序

sr04.h:

#ifndef _SR04_H_
#define _SR04_H_

#include <stdio.h>
#include "main.h"

#define		Trigger_ON 		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_SET)
#define		Trigger_OFF 	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_RESET)


void Delay_us(uint16_t us);						// 使用定时器2编写的延时函数
void Trigger_signal(void);						// 发送 10us 的触发信号


#endif

sr04.c:

#include "sr04.h"

int distance_cm = 0;


extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim3;


/* 延时函数(单位 us) */
void Delay_us(uint16_t us)
{
	uint16_t time = 0xffff - us - 5;
	__HAL_TIM_SET_COUNTER(&htim2,time);								// 设置 定时器2 的值
	HAL_TIM_Base_Start(&htim2);										// 开启定时器2

	while(time < 0xffff-5)
	{
		time = __HAL_TIM_GET_COUNTER(&htim2);						// 获取定时器2 值
	}

	HAL_TIM_Base_Stop(&htim2);										// 停止 定时器2
}


/* 发送 10us 的触发信号 */
void Trigger_signal(void)
{
	Trigger_ON;							// 发送高电平
	Delay_us(10);						// 延时 10 us
	Trigger_OFF;						// 发送低电平
}


/* 外部中断回调函数 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{	
	 static uint32_t time_us = 0;
	
	if(GPIO_Pin == GPIO_PIN_6)
	{
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6))
		{
			HAL_TIM_Base_Start(&htim3);									// 开启定时器3(开始计时)
			__HAL_TIM_SetCounter(&htim3,0);								// 清空定时器3
		}
		else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6) == 0)
		{
			HAL_TIM_Base_Stop(&htim3);									//关闭定时器3(停止计时)
			time_us = __HAL_TIM_GetCounter(&htim3);							// 获取高电平时间
			printf("time_us : %d\r\n", time_us);
			distance_cm = time_us * 340/2*0.000001*100;
			printf("distance_cm is %d cm\r\n", distance_cm);
			
			time_us = 0;
		}
	}
}

对于串口发送数据,可以使用重定义函数,简化代码:

int fputc(int ch,FILE* f)
{
	while(HAL_UART_Transmit(&huart2,(uint8_t*)&ch,sizeof(ch),1000) != HAL_OK);
	return 0;
}

测试程序: 在 while 循环中持续发送触发信号。

int count = 0;

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		/* 每 50 ms 发送一次触发信号 */
		if(HAL_GetTick() - count > 50)
		{
			count = HAL_GetTick();
			Trigger_signal();
		}		
		
  }

HAL_GetTick() 函数 用来获取当前的时间。可以看到这个函数返回 uwTick 变量,在 HAL_IncTick() 中一直增加。uwTick 变量是从STM32 开机就开始计时。 1 uwTick 就是 1ms.

最详细STM32,cubeMX 超声波测距_串口_09


总结

下一篇文章为大家介绍 STM32 驱动蓝牙的实现。

标签:定时器,HAL,信号,us,STM32,TIM,cubeMX,GPIO,测距
From: https://blog.51cto.com/u_16159289/8285623

相关文章

  • STM32F407 LUA 串口代码传输进行功能热更新
    STM32F407LUA串口代码传输进行功能热更新1.首先放上LUA资源LUA2.整体思路创建keil工程--->移植lua--->补充相应功能3.移植LuaStep1正常解压即可只有这个文件有用Step2在这个文件夹里搜索,删掉这两个文件(这两个文件在stm32中不使用)剩余的文件按照添加BSP的流......
  • 1. 手动移植FreeRTOS V9.00到 Stm32F103C8T6
    记录移植过程,以便以后查看:1.使用cubeMAX配置一个工程a.选择单片机型号: b。设置SWD调试,选TIM4作为系统时钟,systick要用来跑freeRTOS c.NVIC默认使用Group4 配置GPIO,我这里配置了两个引脚,作为LED输出 d,RCC都选外部晶振 e。配置时钟树,HCLK72Mhz  f。project......
  • 给STM32装点中国风——华为LiteOS移植
    我都二手程序员好几个礼拜了!想给我的STM32来点“中国风”,装个华为LiteOS操作系统。在此之前,我也试过STM32CubeMX自带的FreeRTOS操作系统,不知是何缘故,用F103c8t6芯片时,FreeRTOS里的一个断言过不去。出师不利,决定换LiteOS试试,尽管移植LiteOS有些麻烦,不如STM32CubeMX生成......
  • (STM32)TIM
    TIM:定时器,定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断根据复杂度和应用场景分为:高级定时器、通用定时器、基本定时器三种类型 基本定时器:支持向上计数(0到1),只能选择内部的72MZ的时钟通用定时器、高级定时器:支持向上计数、向下面计数(1到0)、中央计数(0......
  • STM32 PWM控制LED流水灯 学习记录随笔
    代码部分#include"stm32f10x.h"                 //Deviceheader#include"Delay.h"intmain(void){   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//启用系统寄存器时钟,使能GPIOC组,并启动   GPIO_InitTypeDefGPIO_InitStructure;  ......
  • STM32驱动SIM900A保姆级调试日记
    外观在优信电子买的,比其它商铺价格略高,不过质量应该有保障引脚连接VCC_IN接5VGND接地RXD接MCU TXDTXD接MCURXD(mcu指的是单片机如STM32)因为我只是用来发短信,所以其它引脚不用接!如果需要打电话可能需要咪头和喇叭!但如果是仅仅需要电话做一个提醒的作用,也可以只接上述几个引脚!串......
  • stm32学习记录随笔23.11.3
    RCC外设时钟使能常用函数//标准库文件->stm32f10x_rcc.hvoidRCC_AHBPeriphClockCmd(uint32_tRCC_AHBPeriph,FunctionalStateNewState);//RCC_AHB外设时钟控制voidRCC_APB2PeriphClockCmd(uint32_tRCC_APB2Periph,FunctionalStateNewState);//RCC_APB2外设时钟控制void......
  • 舵机驱动——STM32F407ZGT6探索者——HAL库
    舵机驱动——STM32F407ZGT6探索者——HAL库1、材料准备开发板:正点原子STM32F407ZGT6探索者舵机:SG90舵机线材分辨:褐色/红色/橘黄色——GND/VCC/PWM_signal与开发板接线:褐色/红色/橘黄色——GND/+5V/PF6(任选的PF6)2、知识准备2.1、舵......
  • (STM32)中断系统和外部中断
    中断系统:是执行和管理中断的逻辑结构外部中断:是众多能产生中断的外设之一中断:指的是中断源(中断通道),中断产生CPU暂停正在执行程序,去执行中断程序,然后返回。提高效率F1系列的STM32有68个中断源,不同系列需要看手册EXTI(外部中断)、TIM、ADC、USART、SPI、I2C、RTC等多个外设都会......
  • stm32开发
    基于寄存器开发新建工程添加C/C++识别路径;  防止中文乱码- 改变编码格式   基于库函数开发......