STM32L431(CubeMX)使用HC_SR04超声波模块测量距离并通过串口打印


参考文章:

【STM32】HAL库 STM32CubeMX教程八—定时器输入捕获

一、开发平台

·小熊派(STM32L431)
·HC_SR04超声波模块
·keil5
·cubemx
·使用HAL库

二、HC_SR04介绍

·实物图:
在这里插入图片描述
·基本工作原理
在这里插入图片描述
在这里插入图片描述

通过时序图可知,需要在TRIG的IO口上给出10us及以上的高电平信号,模块内部自动发出8个40KHz脉冲,自动检测是否有信号返回,若有信号返回,测量高电平在ECHO的IO口中输出的时间,测量距离 = (ECHO高电平输出时间*声速(340M/s)/2),建议测量周期在60ms(大约2.5cm)以上,否则测距功能会失效。

三、CubeMX配置

·选择芯片
在这里插入图片描述
RCC选择外部高速时钟
在这里插入图片描述
配置SYS
在这里插入图片描述
配置时钟树,stm32l431最大时钟频率为80MHz
在这里插入图片描述
配置USART,按默认配置,引脚默认在PA9,PA10。
在这里插入图片描述
配置TIM2时钟
在这里插入图片描述
·预分频填80-1,时钟计数频率 = 80MHz/PSC+1=1Mhz ,即计数频率为1us
·上升沿捕获
·自动装载值设置为32Bit最大值 65535
·并在NVIC设置中使能TIM2中断
在这里插入图片描述
配置GPIO,配置PB9作为TRIG,默认输出低电平
在这里插入图片描述

设置路径,工程名称,编译器
在这里插入图片描述
勾选代码生成
在这里插入图片描述

四、keil5代码部分

1、printf重定向

首先勾选Use MicroLIB调用MDK的微库,MicroLIB是对C标准库高度优化之后的库,比标准库代码更少,使用效率更高。
在这里插入图片描述

在usart.c文件最后加上代码,这里不使用HAL库函数HAL_UART_Transmit来发送数据,直接操作寄存器来发送,效率更高。

/* USER CODE BEGIN 1 */
#if 1
#include <stdio.h>
int fputc(int ch, FILE *stream)
{
    /* 堵塞判断串口是否发送完成 */
    while((USART1->ISR & 0X40) == 0);

    /* 串口发送完成,将该字符发送 */
    USART1->TDR = (uint8_t) ch;

    return ch;
}

#endif
/* USER CODE END 1 */

2、创建HC_SR04.c/.h文件

在这里插入图片描述
在这里插入图片描述

3、HC_SR04.h

·为了防止头文件重复定义

#ifndef	__HC_SR04_H__
#define __HC_SR04_H__

#endif

·添加所需头文件

#ifndef	__HC_SR04_H__
#define __HC_SR04_H__

#include "stm32l4xx_hal.h"
#include "tim.h"
#include "usart.h"
#include <stdio.h>

#endif

·定义TRIG高电平与低电平

#define TRIG_L	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)
#define TRIG_H	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET)

·声明函数

void delay_us(uint16_t us);
void Get_Distance(void);

4、HC_SR04.c

·包含头文件以及定义变量

#include "HC_SR04.h"

float distance;		//测量距离
uint32_t capture_value1;	//存放定时器捕获值数组
uint32_t capture_value2;
uint8_t cnt=0;		//状态计数值

·HC_SR04模块需要用到us级延时,而HAL库中的HAL_Delay只支持ms级延时,所以自己实现us延时

void delay_us(uint16_t us)
{     
	uint16_t differ = 0xffff-us-5;				
	__HAL_TIM_SET_COUNTER(&htim2,differ);	//设定TIM2计数器起始值
	HAL_TIM_Base_Start(&htim2);		//启动定时器	
	
	while(differ < 0xffff-5){	//判断
		differ = __HAL_TIM_GET_COUNTER(&htim2);		//查询计数器的计数值
	}
	HAL_TIM_Base_Stop(&htim2);
}

·根据时序图可知

/*
HC_SR04启动函数:触发信号顺序
给TRIG一个低电平,延时10us以上,再给TRIG一个高电平
*/
void HC_SR04_Start(void)
{
	TRIG_L;	
	delay_us(20);
	TRIG_H;
}

·tim中断回调函数

/*中断回调函数*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//
{
	
		if(TIM2 == htim->Instance)// 判断触发的中断的定时器为TIM2
		{	
			switch(cnt){
			case 1:
			capture_value1 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);  //设置为下降沿捕获
			cnt++;
			break;
			
			case 2:
			capture_value2 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
			HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1); //停止捕获   或者: __HAL_TIM_DISABLE(&htim2);			
			cnt++;
		}
	}
}

·获得测量后的距离

/*
获取HC_SR04测出与目标之间的距离

*/
void Get_Distance(void)
{
	uint16_t measure;
	switch(cnt){
		case 0:
		HC_SR04_Start();
		__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
		HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);	//启动输入捕获       或者: __HAL_TIM_ENABLE(&htim5);   
		cnt++;
		break;
	
		case 3:
		measure = capture_value2-capture_value1;
		distance = (measure*0.034)/2;
		printf("距离为%f cm\r\n",distance);
		cnt = 0;
		TIM2->CNT = 0;
		break;

	}
}

实现以上功能的流程

1.设置TIM2 CH1为输入捕获功能;
2.设置上升沿捕获;
3.使能TIM2 CH1捕获功能;
4.捕获到上升沿后,定时器当前计数值存入capture_value1,改为捕获下降沿;
5.捕获到下降沿后,定时器当前计数值存入存入capture_value2,关闭TIM2 CH1捕获功能; cnt=3;
6. 高电平时间: capture_value2 - capture_value1 重新启动输入捕获

__HAL_TIM_SET_COUNTER(&TIM2_Handler,0); //设置计数寄存器的值变为0
HAL_TIM_PWM_Start() 函数用于使能定时器某一通道的PWM输出。
HAL_TIM_IC_Start_IT() 函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断
HAL_TIM_IC_Stop_IT() 函数和开启功能相反,是关闭定时器某一通道的输入捕获功能和相应中断
__HAL_TIM_SET_CAPTUREPOLARITY不是函数,而是底层操作的一个宏定义
在stm32l4xx_hal_tim.h文件中可以找到。其作用是修改定时器某一通道的输入捕获极性在这里插入图片描述
其中有两个函数,第一个为清除清除原来的捕获极性,第二个为设置通道捕捉极性

TIM_RESET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_1);   //一定要先清除原来的捕获极性!!
TIM_SET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器2通道1设置为下降沿捕获(重设捕获极性)

在修改定时器某一通道的输入捕获极性时,一定要先清除该通道之前捕获极性
__HAL_TIM_GET_COMPARE也是一个宏定义。 
在stm32l4xx_hal_tim.h文件中可以找到。其作用是获取定时器某一通道的捕获/比较寄存器值,等价于 : HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
在这里插入图片描述
两者都是直接读取对应CCRx寄存器的值

5、main.c

在main函数的循环中添加

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

    /* USER CODE BEGIN 3 */
		Get_Distance();
		HAL_Delay(500);
  }
  /* USER CODE END 3 */

五、接线

HC_SR04开发板
VCC5V
TRIGPB9
ECHOPA0
GNDGND

六、串口打印效果

在这里插入图片描述

作者能力有限,如有出错,希望各位大佬帮忙指出,谢谢

### 鸿蒙 Hi3861 芯片在送餐车项目中的应用 #### 1. 硬件准备与配置 Hi3861 是一款高度集成的2.4GHz SoC WiFi芯片,具有高性能32位微处理器,最大工作频率达160 MHz,内置SRAM 352 KB、ROM 288 KB 和 Flash 2 MB[^1]。对于送餐车项目而言,这些硬件特性能够满足基本的数据处理需求。 为了实现送餐车的功能,建议选用带有Wi-Fi模块的支持LiteOS-M操作系统的OpenHarmony开发板,如来自深开鸿、润和软件或小熊派的产品。这类开发板可以方便地与其他传感器(如超声波测距仪)、电机驱动器以及无线通信模块相连接。 #### 2. 开发环境搭建 针对Windows操作系统用户,推荐使用DevEco Device Tool作为主要IDE来完成应用程序编写与调试任务。安装前需确认已正确设置了Python运行环境,确保版本兼容性良好[^2]。 #### 3. 应用程序设计思路 考虑到送餐车可能涉及的任务调度复杂度较高,而Hi3861仅支持毫秒级定时器,在某些情况下可能会导致性能瓶颈甚至系统崩溃的问题[^3]。因此,在规划具体功能时应特别注意优化算法效率合理分配资源: - **路径规划**:利用A*搜索或其他高效寻路算法计算最优行驶路线; - **避障机制**:结合红外线/激光雷达等感知装置实时监测周围障碍物情况; - **配送状态反馈**:通过HTTP RESTful API接口向云端服务器发送当前位置信息及订单进度更新; 此外还需考虑如何有效管理和同步多个子系统之间的协作关系,比如当接收到新的取货指令时及时调整行动方案。 #### 4. 测试与部署 完成编码之后可以通过PUTTY或者其他类似的串口终端工具连接至目标设备进行初步测试验证。设置好相应的通讯参数(例如波特率为115200bps),按下复位按钮使能固件加载过程[^4]。经过充分联调后即可正式投入使用。 ```bash # 进入Deveco Device Tool命令行界面 $ devecotool --version ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值