超聲波障礙物測距
- 一、HC-SR04超聲波模塊
- (一)什么是HC-SR04?
- (二)HC-SR04工作原理
- (三)如何使用HC-SR04
- (四)注意事項
- 二、程序編寫
- (一)CubeMX配置
- 1.芯片選擇
- 2.配置RCC、SYS、時鐘樹
- 3.配置GPIO
- 4.配置串口1
- 5.配置定時器
- 6.開啟定時器中斷
- 7.設置路徑、生成代碼工程
- (二)代碼編寫
- 三、效果展示
- 四、總結
- 五、引用
使用的軟硬件設備與應用:
- 硬件:STM32F103C8T6、HC-SR04、LED燈
- 軟件:Keil5、CubeMX、串口助手
一、HC-SR04超聲波模塊
(一)什么是HC-SR04?
HC-SR04是一款常用的超聲波測距模塊,它能夠通過發送超聲波脈沖并接收其回波來測量物體與傳感器之間的距離。這種模塊廣泛應用于機器人、智能小車、智能家居等領域,可以用于測量墻壁距離、障礙物距離、物品距離。
(二)HC-SR04工作原理
HC-SR04模塊的工作原理是,通過IO口TRIG觸發測距,給至少10us的高電平信號,模塊自動發送8個40kHz的方波,并自動檢測是否有信號返回。如果有信號返回,通過IO口ECHO輸出一個高電平,高電平持續的時間即為超聲波從發射到返回的時間。通過測量這個時間,可以計算出距離,公式為:測試距離 = (高電平時間 × 聲速(340m/s)) / 2。
(三)如何使用HC-SR04
模塊的電氣連接通常包括四個引腳:VCC、Trig、Echo、GND。VCC和GND分別為正負電源引腳,Trig為觸發引腳,Echo為回波引腳。在使用時,需要給Trig引腳發送一個10us以上的高電平信號,然后在Echo引腳等待高電平輸出,當Echo引腳變為低電平時,讀取定時器的值,即為此次測距的時間。
(四)注意事項
- 不宜帶電連接模塊,如果要帶電連接,則先讓模塊的GND端先連接,否則會影響模塊工作。
- 測距時,被測物體的面積不少于0.5平方米且要盡量平整,否則會影響測試結果。
- HC-SR04模塊的典型工作電壓為5V,靜態工作電流小于2mA,感應角度不大于15度,探測距離為2cm-400cm,精度可達0.3cm,存在一個2cm的盲區。2020版本的HC-SR04支持GPIO、UART和IIC三種模式接口,工作電壓3-5.5V,測量范圍2cm-450cm。
二、程序編寫
(一)CubeMX配置
1.芯片選擇
2.配置RCC、SYS、時鐘樹
3.配置GPIO
A1連接的是ECHO,B9為LED
4.配置串口1
5.配置定時器
6.開啟定時器中斷
7.設置路徑、生成代碼工程
(二)代碼編寫
main.c
:
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** <h2><center>© Copyright (c) 2022 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under BSD 3-Clause license,* the "License"; You may not use this file except in compliance with the* License. You may obtain a copy of the License at:* opensource.org/licenses/BSD-3-Clause********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "SR04.h"
#include "led.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
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 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){float distance = SR04_GetData();//HAL_Delay(1500);/* USER CODE END WHILE */// 根據距離計算閃爍頻率uint32_t flashRate = CalculateFlashRate(distance);LED_Flash(flashRate); // 閃爍LED/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
SR04.h
:
#ifndef __SR04_H
#define __SR04_H
#include "main.h"
#include "tim.h"
#include "stdio.h"#define TRIG_H HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_SET)
#define TRIG_L HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_RESET)void delay_us(uint32_t us);
float SR04_GetData(void);#endif
SR04.c
:
#include "SR04.h"
#include "stm32f1xx_hal.h" float distant; //測量距離
uint32_t measure_Buf[3] = {0}; //存放定時器計數值的數組
uint8_t measure_Cnt = 0; //狀態標志位
uint32_t high_time; //超聲波模塊返回的高電平時間//===============================================讀取距離
float SR04_GetData(void)
{switch (measure_Cnt){case 0:TRIG_H;delay_us(30);TRIG_L;measure_Cnt++;__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); // 啟動輸入捕獲break;case 3:high_time = measure_Buf[1] - measure_Buf[0]; // 高電平時間printf("\r\n----高電平時間-%d-us----\r\n", high_time);float distance = (high_time * 0.034f) / 2; // 單位cmprintf("\r\n-檢測距離為-%.2f-cm-\r\n", distance);measure_Cnt = 0; // 清空標志位TIM2->CNT = 0; // 清空計時器計數// 返回計算得到的距離值return distance;}return 0; // 如果沒有測量完成,返回0或合適的默認值
}//===============================================us延時函數void delay_us(uint32_t us)//主頻72M
{uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);while (delay--){;}
}//===============================================中斷回調函數
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//
{if(TIM2 == htim->Instance)// 判斷觸發的中斷的定時器為TIM2{switch(measure_Cnt){case 1:measure_Buf[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//獲取當前的捕獲值.__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING); //設置為下降沿捕獲measure_Cnt++; break; case 2:measure_Buf[1] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//獲取當前的捕獲值.HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1); //停止捕獲 或者: __HAL_TIM_DISABLE(&htim5);measure_Cnt++; }}}
led.h
:
#ifndef __LED_H__
#define __LED_H__#include "stm32f1xx_hal.h"void LED_Init(void);
void LED_Flash(uint32_t period);
uint32_t CalculateFlashRate(float distance);#endif // __LED_H__
led.c
:
#include "led.h"#define LED_GPIO_Port GPIOB
#define LED_Pin GPIO_PIN_9void LED_Init(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};// 使能GPIOB時鐘__HAL_RCC_GPIOB_CLK_ENABLE();// 配置GPIO Pin為推挽輸出,無上拉電阻,低頻率GPIO_InitStruct.Pin = LED_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
}void LED_Flash(uint32_t period) {// 切換LED狀態HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);// 延時HAL_Delay(period);// 再次切換LED狀態,完成一次閃爍HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}uint32_t CalculateFlashRate(float distance) {uint32_t flashRate;if (distance < 10.0f) {flashRate = 100; // 距離小于10厘米時,快速閃爍} else if (distance < 50.0f) {flashRate = 500; // 距離在10-50厘米之間時,中速閃爍} else {flashRate = 1000; // 距離大于50厘米時,慢速閃爍}return flashRate;
}
三、效果展示
HC-SR04
四、總結
本次實現了STM32F103C8T6微控制器和HC-SR04超聲波測距模塊的結合應用,并通過LED閃爍頻率表現出來。通過CubeMX的圖形化配置和Keil5的開發環境,項目簡化了開發流程,提高了開發效率。此外,項目還提供了對超聲波測距原理的深入理解,以及如何通過軟件控制硬件來實現特定功能的方法。
五、引用
【嵌入式創客工坊】STM32系列(HAL庫)——F103C8T6通過HC-SR04超聲波模塊實現測距