最详细STM32,cubeMX 超声波测距

举报
糖果罐子 发表于 2023/10/31 20:32:42 2023/10/31
【摘要】 >这篇文章将详细介绍 STM32使用 cubeMX驱动超声波测距 。@[TOC](文章目录)---# 前言- 实验材料:STM32F103C8T6开发板, HC-SR04 超声波模块。- 所需软件:keil5 , cubeMX ,AiThinker Serial Tool 串口助手。- 实验目的:了解 STM32使用 cubeMX驱动超声波 。- 实验:超声波测距。---# 一、超声波模块H...

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

@[TOC](文章目录)

---

# 前言

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

---

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

**当超声波发出一个信号时,信号碰到物体或阻碍后会立即返回。只要得到 信号往返传输的时间就可以测出距离。**
![在这里插入图片描述](https://img-blog.csdnimg.cn/f7c73501a072443bb5987cd6b8f8b9ad.png)
>参数列表:
工作电压 **VCC** : **5 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**。(因为 高电平的时间就是信号往返传输的时间)
![在这里插入图片描述](https://img-blog.csdnimg.cn/64b77d1a8e284a168e25013348619dbd.png)
# 二、cubeMX 配置
对于基础的配置可以看我之前的文章。
1. 由于 要发送一个 10us 的高电平,这个时间用定时器进行配置,所以这里我`使用 定时器 2 进行延时`。(尽量不要使用 HAL_Delay 函数,多次使用会导致程序卡顿)

这里选择内部时钟源,并配置相关参数。这里配置的参数是 1us 延时。
![在这里插入图片描述](https://img-blog.csdnimg.cn/eb05b2b5a46d426f8385b480a3bb0455.png)

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

如果对 定时器的定时时长有不了解的可以参考我之前的文章:[最详细STM32,cubeMX 定时器
](https://blog.csdn.net/wuyiyu_/article/details/133969768) 
![在这里插入图片描述](https://img-blog.csdnimg.cn/5826a02323cc4cfe9f063435896e7220.png)

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

如果对 串口的配置有不了解的可以参考我之前的文章:[最详细STM32,cubeMX串口发送,接收数据
](https://blog.csdn.net/wuyiyu_/article/details/133975425)

![在这里插入图片描述](https://img-blog.csdnimg.cn/bf7cfa0db80f4c53b3384dce01a94f85.png)

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

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

如果对 外部中断的配置有不了解的可以参考我之前的文章:[STM32不使用 cubeMX实现外部中断
](https://blog.csdn.net/wuyiyu_/article/details/133968220)
![在这里插入图片描述](https://img-blog.csdnimg.cn/82787065a66b4d83bb86bc657c37e73e.png)
- 并将 PB6 设置为 双边沿触发中断。
![在这里插入图片描述](https://img-blog.csdnimg.cn/136f805a91c44b38ab59309fa4b479d8.png)

- 并将外部中断使能。
![在这里插入图片描述](https://img-blog.csdnimg.cn/b298d362eab54c66a46fdf90f07a3bbe.png)
# 三、实验程序
**sr04.h:**

```c
#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:**

```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;
}
}
}

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

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

```

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

```c
  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.**
![在这里插入图片描述](https://img-blog.csdnimg.cn/87cda2d1b1814f4ba0d660db225d2c9c.png)

---

# 总结
下一篇文章为大家介绍 STM32 驱动蓝牙的实现。
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。