超声波测距原理

利用HC-SR04超声波测距模块可以实现比较精确的直线测距,其测距原理图如下:

HC-SR04的一端发出超声波,接触到反射物后反射,被另一个端口接收到,所以只要知道发射和接收的时间差,就可以根据声波传播的速率算出HC-SR04和反射物直接的距离。
所以实现超声波测距就需要俩个条件:

  • 发射和接收的时间差
  • 超声波传输的速率

HC-SR04工作原理

HC-SR04模块的电气参数如示:

HC-SR04模块的实物图如示:

有四个引脚:

  • Vcc:+5V电源供电
  • Trig:输入触发信号(可以触发测距)
  • Echo:传出信号回响(可以传回时间差)
  • Gnd:接地

用Trig和Echo引脚实现测距的流程:
1.通过Trig输出一段至少10us的高电平(脉冲),触发一次测距,超声波在传输的过程中Echo一直输出高电平。
2.在Trig脉冲输出后,立即检测Echo引脚的电平,测出Echo高电平持续的时间t,t就是超声波在所测距离一个来回所需时间。
测距时序图如示:

STM32实现驱动

利用STM32驱动HC-SR04需要做好几个关键点:

  • 引脚的配置
  • 时序的控制
  • 时间差的测量

下面来分开实现几个关键点

1.引脚的配置

HC-SR04四个引脚,Vcc和Gnd直接接在开发板的电源上即可,主要是Trig和Echo引脚的配置,我选择了PB1连接Trig引脚、PB2连接Echo引脚。
因为要控制Trig输出电平,所以PB1引脚模式是推挽输出GPIO_Mode_Out_PP
Echo要检测高电平持续的时间,所以PB2引脚模式是浮空输入GPIO_Mode_IN_FLOATING
相关的配置代码如下:

void SR04_GPIO_Init( void )
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd( Trig_Clock |Echo_Clock , ENABLE ); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = Trig_PIN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(Trig_PORT, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = Echo_PIN;
GPIO_Init(Echo_PORT, &GPIO_InitStruct);
}

2.时序控制

HC-SR04的时序是:先来一段10us的Trig高电平,接着接收一段Echo的高电平,伪代码如下:

#define Trig_H  GPIO_SetBits(GPIOB, GPIO_Pin_1)
#define Trig_L GPIO_ResetBits(GPIOB, GPIO_Pin_1) /* Trig给一个至少10us的高电平,超声波进行一次测距 */
Trig_H;
Delay_us( 10 );
Trig_L;
/* 等待Echo高电平 */

3.时间差测量

这个是最重要的一步,要测量Echo高电平持续的时间,因为光传播的速率是340m/s,而测距的范围大多是cm级别,所以相应Echo高电平持续的时间也就是us级别的。
所以,测量时间差的条件就比较苛刻,我是利用SysTick(系统计数器)的原理实现计时的。SysTick计数器原理是对通过SysTick_Config()函数配置每俩次中断之间的节拍数,也就是俩次中断之间的机器周期,我大概算出了,测出0.1cm距离的Echo高电平时间约为6um,而系统时钟的频率是72MHz,所以配置每俩次中断之间的节拍为432的时候,进入一次中断就代表0.1cm的距离,所以只需要记录进入中断的次数就可以算出距离。通过一个全局变量在中断函数中自增来记录中断次数。SysTick_Config函数源代码如下:

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
/* 判断ticks 是否超出装填值和重装值的最大值 */
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* 配置 装载寄存器 */
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
/* 配置 内核中断的优先级,也是在NVIC中 */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
/* 加载计数器的值 */
/* SysTick->VAL是当前数值寄存器的值 */
SysTick->VAL = 0; /* CTRL是SysTick控制及状态寄存器:
CLKSOURCE:位段2 时钟源选择,0=APB/8;1=APB APB即72MHz
TICKINT: 位段1 当置为1时,计数器递减到0时会产生中断请求;当置为0时无动作
ENABLE: 位段0 使能位,可以启动SysTick定时器*/
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}

SysTick的具体原理可以参考一下我之前的博客:SysTick原理

注意:SysTick_Config()函数执行完就开启了中断,所以必须在Echo为低电平后及时关闭中断,并且将记录中断的变量清零。
中断函数如示:

/* 用extern和volatile关键字修饰的 全局变量n */
extern volatile uint32_t n; void SysTick_Handler(void)
{
n++;
}

关闭中断及清零n的代码如下:

/* 本来的使能位取反 */
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

SysTick->CTRL寄存器的0位控制着中断的使能,具体情况在之前SysTick的博客中已做详细说明。

4.如何将距离测出来

我在main函数中实现了距离的测量,并且通过串口打印函数将距离传到上位机,具体代码如示:

int main(void)
{ int i=1,q;
float p;
/* HC-SR04模块引脚初始化 */
SR04_GPIO_Init();
/* 串口相关配置 */
GQ_UART_Config();
/* 打印调试信息 */
printf("慢漫的测距实验\n "); while( 1 )
{
/* 每0.5s测一次距离 */
Delay_ms( 500 ); /* Trig给一个至少10us的高电平,超声波进行一次测距 */
Trig_H;
Delay_us( 10 );
Trig_L;
/* 等待Echo高电平 */
while( Echo_Value != 1 );
/* 打开中断,对Echo高电平时间计时 */
/* 配置计数器的装载值是72*6=432,即一次中断6um,正好是超声波的0.1cm,所以中断次数n对应着n*0.1cm */
/* SysTick_Config()中已经使能计数器了,所以无需再开启 */
SysTick_Config( 432 );
/* 等待直到Echo为低电平 */
while(Echo_Value == 1);
/* 关闭中断,通过参数n来取得距离参数 */
/* 本来的使能位取反 */
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
/* p、q分别是距离的整数部分和小数部分 */
p=n/10;
q=n%10;
/* 打印距离信息 */
/* p-50时经过调试的,因为测量的距离和诸多因素有关,这个操作减小了误差 */
printf("第%d次测量为:%.0f.%dcm\n",i,p-50,q);
i++;
/* 清零中断记录变量n */
n=0;
} }

STM32—驱动HC-SR04超声波测距模块的更多相关文章

  1. [自娱自乐] 3、超声波测距模块DIY笔记(三)

    前言 上一节我们已经研究了超声波接收模块并自己设计了一个超声波接收模块,在此基础上又尝试用单片机加反相器构成生成40KHz的超声波发射电路,可是发现采用这种设计的发射电路存在严重的发射功率太低问题,对 ...

  2. STM32(HY-SRF05)超声波测距项目

    参考资料: https://www.cnblogs.com/qsyll0916/p/6964638.html http://blog.csdn.net/zhangdaxia2/article/deta ...

  3. loto示波器实践——超声波测距模块

    我们这里用到的超声波测距模块,一般是用于arduino智能小车自动避障的.经常见到的应用是使用单片机或者stm32和这种模块结合进行开发的. 我们使用LOTO示波器可以更直观和快速的看到超声波测量距离 ...

  4. [自娱自乐] 4、超声波测距模块DIY笔记(四)——终结篇·基于C#上位机软件开发

    前言 上一节我们已经基本上把超声波硬件的发射和接收模块全部做好了,接下来我们着手开发一个软硬结合的基于C#的平面定位软件! 目录 一.整体思路 二.效果提前展示 2-1.软件部分展示 2-2.硬件部分 ...

  5. [自娱自乐] 2、超声波测距模块DIY笔记(二)

    前言 上一节我们已经大致浏览下目前销售的超声波测距模块同时设计了自己的分析电路,这次由于我买的电子元件都到了,所以就动手实验了下!至写该笔记时已经设计出超声波接收模块和超声波发射模块,同时存在超声波发 ...

  6. 基于STM32F103ZET6 HC_SR04超声波测距模块

    这是最后的实验现象,改变不同的角度即可测得距离 板子 PZ6806L 超声波模块 HC_SR04 HC_SR04模块讲解 通过该超声波模块说明书,可明白供电需VCC 5V  还需GND  ECHO(回 ...

  7. 树莓派 HC-SRO4超声波测距模块的使用

    先上个图 这个模块的针脚跟之前玩的那三个有所区别,除了VCC和GND两个针脚,还多了两个Trig和Echo针脚,分别是输出和输入,Trig我接的是20针脚,Echo是21 该模块的工作原理为,先向TR ...

  8. 张高兴的 Windows 10 IoT 开发笔记:HC-SR04 超声波测距模块

    HC-SR04 采用 IO 触发测距.下面介绍一下其在 Windows 10 IoT Core 环境下的用法. 项目运行在 Raspberry Pi 2/3 上,使用 C# 进行编码. 1. 准备 H ...

  9. Arduino 控制超声波测距模块

    一.实物图 二.例子代码 用到数字2 和3 引脚,还有两个就是vcc GND两个阴脚,用模块连线比较简单

随机推荐

  1. Game游戏分析

    1.鲁棒图分析 2.系统上下文及交互方式 3.用例 4.逻辑拓扑图 5.物理拓扑图 6.时序图 7.状态图 8.物理数据模型 9.类图 10.技术选型 11.框架搭建 12.工具及通用服务 13.架构 ...

  2. 2shell中处理字符串,字符串的截取、替换

    0.字符串的小知识点 1.字符串的截取 1.1从指定位置开始截取 1.2 从指定字符(子字符串)开始截取 1.3字符串截取的总结 1.4 按指定要求截取 2.字符串的拼接 3.字符串的替换 0.字符串 ...

  3. Jquery Validate动态添加和删除校验规则

    以下面文本框为例, <input type="text"name="username" id="username"/> 我们要让 ...

  4. PHP常见的设计模式

    设计模式六大原则 开放封闭原则:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象. 依赖倒置原则:高层模块不应该依赖低层模块,二者 ...

  5. XCTF crypto 不仅仅是Mors

    一. 题目暗示摩斯码,打开文件发现里面有反斜杠的.不管它直接拿来解密 二. 发现一句话是句英文,还有其他的加密方式,后面那串只有两种字符A和B,手抓饼A套餐,b套餐 培根加密,拿来解密后,得到flag

  6. Ionic命令笔记

    Ionic命令:ionic serve 开启服务调试ionic cordova prepare android 生成android原生项目 ionic cordova run browser 打包成混 ...

  7. 交换机卡在CPU task进程处理方法

    故障现象: 笔记本通过console线连接H3C交换机的console口,无法登陆,敲任何东西都无效.因为没有备份,不敢重启.显示以下报错: <test-sw> wrong input! ...

  8. Django基础006--在pycharm中将项目配置为Django项目

    1.在File--Settings--搜索Django 操作按照如图所示 2.在pycharm右上方项目处,选择Edit Configurations 3.在Name处写上项目名称 python环境选 ...

  9. 家庭账本开发day03

    今天在编写form表单提交时遇到很多问题,在向servlet提交请求时找不到资源, 在网上查找学习了相关的信息,找到原因,添加注解或者配置xml文件的相关映射 解决问题.成功完成了账单添加的功能.

  10. 前端开发入门到进阶第二集【emmet插件的使用技巧】

    Emmet (前身为 Zen Coding) 是一个能大幅度提高前端开发效率的一个工具.基本上,大多数的文本编辑器都会允许你存储和重用一些代码块,我们称之为"片段".虽然片段能很好 ...