STM32—驱动HC-SR04超声波测距模块
超声波测距原理
利用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超声波测距模块的更多相关文章
- [自娱自乐] 3、超声波测距模块DIY笔记(三)
前言 上一节我们已经研究了超声波接收模块并自己设计了一个超声波接收模块,在此基础上又尝试用单片机加反相器构成生成40KHz的超声波发射电路,可是发现采用这种设计的发射电路存在严重的发射功率太低问题,对 ...
- STM32(HY-SRF05)超声波测距项目
参考资料: https://www.cnblogs.com/qsyll0916/p/6964638.html http://blog.csdn.net/zhangdaxia2/article/deta ...
- loto示波器实践——超声波测距模块
我们这里用到的超声波测距模块,一般是用于arduino智能小车自动避障的.经常见到的应用是使用单片机或者stm32和这种模块结合进行开发的. 我们使用LOTO示波器可以更直观和快速的看到超声波测量距离 ...
- [自娱自乐] 4、超声波测距模块DIY笔记(四)——终结篇·基于C#上位机软件开发
前言 上一节我们已经基本上把超声波硬件的发射和接收模块全部做好了,接下来我们着手开发一个软硬结合的基于C#的平面定位软件! 目录 一.整体思路 二.效果提前展示 2-1.软件部分展示 2-2.硬件部分 ...
- [自娱自乐] 2、超声波测距模块DIY笔记(二)
前言 上一节我们已经大致浏览下目前销售的超声波测距模块同时设计了自己的分析电路,这次由于我买的电子元件都到了,所以就动手实验了下!至写该笔记时已经设计出超声波接收模块和超声波发射模块,同时存在超声波发 ...
- 基于STM32F103ZET6 HC_SR04超声波测距模块
这是最后的实验现象,改变不同的角度即可测得距离 板子 PZ6806L 超声波模块 HC_SR04 HC_SR04模块讲解 通过该超声波模块说明书,可明白供电需VCC 5V 还需GND ECHO(回 ...
- 树莓派 HC-SRO4超声波测距模块的使用
先上个图 这个模块的针脚跟之前玩的那三个有所区别,除了VCC和GND两个针脚,还多了两个Trig和Echo针脚,分别是输出和输入,Trig我接的是20针脚,Echo是21 该模块的工作原理为,先向TR ...
- 张高兴的 Windows 10 IoT 开发笔记:HC-SR04 超声波测距模块
HC-SR04 采用 IO 触发测距.下面介绍一下其在 Windows 10 IoT Core 环境下的用法. 项目运行在 Raspberry Pi 2/3 上,使用 C# 进行编码. 1. 准备 H ...
- Arduino 控制超声波测距模块
一.实物图 二.例子代码 用到数字2 和3 引脚,还有两个就是vcc GND两个阴脚,用模块连线比较简单
随机推荐
- <mvc:default-servlet-handler/>导致controller失效,报404错误
最近在做ssm框架整合的一个小项目时,页面跳转一直有404错误,也没有报错提示.然后一步一步去找,终于发现是<mvc:default-servlet-handler/>的原因.如下图所示, ...
- 在spring boot使用总结(九) 使用yaml语言来写配置文件
yaml是专门用来写配置文件的语言.使用yaml来写配置文件扩展性比较强而且十分方便.spring boot支持使用yaml语言来写配置文件,使用snakeyaml库来读取配置文件.spring bo ...
- Linux文件目录结构详解 (转)
整理自<鸟哥的私房菜> 对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能, ...
- docker挂载数据卷
1.Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker中称为数据卷,简单的理解就是将数据持久化的工具. 2.在使用docker容器的时候,会产生一系列的数据文件,这些数据文件在我们 ...
- Charles使用笔记001
一.抓电脑的请求 Proxy-->勾选Windows Proxy 二.Charles 拦截原理 三.Charles 拦截修改数据 选择一个链接-->右键-->勾选Breakpoint ...
- C语言:延时1秒
使用sleep()函数将程序阻塞,头文件在windows系统和linux系统下是不一样的windowsSleep()//第一个字母大写#include <windows.h>函数原型voi ...
- 浅谈MVC设计模式
摘要:MVC即Model.View.Controller即模型.视图.控制器,它是用一种业务逻辑.数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用 ...
- js学习-es6实现枚举
最近大部分时间再写dart,突然用到js,发现js不能直接声明一个枚举.搜索发现还是有实现的方式,于是总结一下. 目录 枚举特点 Object.freeze() Symbol 实现 体现不可更改 体现 ...
- 以太坊-Win环境下remix环境搭建
一.node.js环境搭建 有多个安装方法,但是注意npm与node版本相关性较强!以下方案较为简便 1.下载网址 http://nodejs.cn/download/ 2.下载window 64位 ...
- npm 安装、卸载模块
npm安装模块 [npm install xxx]利用 npm 安装xxx模块到当前命令行所在目录:[npm install -g xxx]利用npm安装全局模块xxx:本地安装时将模块写入packa ...