超声波测距原理

利用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.%dcmn",i,p-50,q);

i++;

/* 清零中断记录变量n */

n=0;

}

}

关键字:STM32  HC-SR04  超声波测距模块 引用地址:STM32—驱动HC-SR04超声波测距模块

上一篇:STM32—驱动DHT11数字温湿度传感器
下一篇:利用ST-LINK配合ST-LINK Utility 将bin文件下载到STM32的FLASH中

推荐阅读

1,warning Deprecated declaration/函数/ - give arg types解决方法:该函数如果没有参数就要在括号里加“void”2,USER\main.c(39): warning:  #223-D: function "function" declared implicitly 函数没有声明解决方法:在使用函数之前一定要声明 3,warning: #1-D: last line of file ends without a newline解决方法:在最后一行加个回车
工业机器人是在上个世纪40年代诞生出来的,最初的工业机器人是在固定的环境下进行重复作业,后来工业机器人用在了许多的行业,像是汽车、、金属、物流、医药、甚至是航空航天等等。随着科技的发展,人们需要的不是传统的不会变化的机器人,而是可以应用到更多场景的智能化的工业机器人,在功能上可以兼顾传感和智能化进行决策和判断,达到发掘工业数据的...
娃哈哈集团董事长宗庆后在全球创业者大会上表示,现在年轻人创业比我们难,过剩经济,竞争激烈,所以大家要选准方向,不要好高骛远,当年卖冰棍时也没想到能做成娃哈哈,不可能一开始就做成几十亿几百亿的企业。宗庆后说得很中肯,现在创业确实更加困难,很多小企业都活不过五年,何况是浮躁的年轻人创业。2019 年年底, CNET 记者将 iPhone 11 和 ...
- 什么是LCD1602LCD:Liquid Crystal Display—液晶显示器,简称LCD,其主要显示原理是以电流刺激液晶分子产生点、线、面并配合背部灯管构成画面,通常把各种液晶显示器都直接叫做液晶。1602:液晶的命名通常都是按照显示字符的行数或液晶点阵的行、列数来的。1602的意思是每行可以显示16个字符,一共可以显示俩行,类似还有0801、1601等。注意:此类液...

史海拾趣

问答坊 | AI 解惑

基于DSP的上网方案的软硬件设计与实现

随着现代网络技术的发展,嵌入式系统如单片机、DSP等系统对接入网络的需求日益增加,例如具有远程抄表功能的电表系统、可以进行远程控制的信息家电系统等。本文采用TI公司的TMS320VC33 DSP芯片设计与Realtek公司的RTL8019网卡的硬件接口电路,并在DSP ...…

查看全部问答∨

华为Quartus教程

华为的Quartus入门教程,比较系统全面,但讲得不深,有兴趣的朋友可以下来看看…

查看全部问答∨

delphi串口编程

章   Delphi串口(COM口)编程(附截图) 2009-06-27 19:45        因为公司有个读卡器由键盘口换成了COM口的,所以原来的程式要做个小小的调整,要改成从串口读数据。一般的系 ...…

查看全部问答∨

LPC2114中UCOS-II移植问题

现在在使用UCOS-II操作系统,我用的是飞利浦LPC2114开发板,通过加载基于UCOSII的模块,然后新建工程,系统会自动将UCOS-II操作系统加到你所建的工程中,然后你在上面编程你所想要实现的功能,我只是实现简单的Led闪烁,但是不知道什么原因,灯只会 ...…

查看全部问答∨

求Silverlight for Embedded应用例子

近来看见网上许多人讨论Silverlight for Embedded,不知MS有没有放出例子参考参考,在网上找了一下找不到,那位达人有的能贡献出来让大家参考一下吗?呵呵…

查看全部问答∨

51单片机中push的问题

正在学单片机 书中讲的是: push 后面的操作数只能是直接寻址方式 如:push 30H     push ACC 还说:push A不对,也就是操作数不能是寄存器寻址 可书中的例子中却多次出现:push A 请问是不是书上印错了…

查看全部问答∨

【C2000 LaunchPad】PWM 模块原理及使用

  PWM模块原理及使用   F28027有8路PWM(四个模块),4路HRPWM,特别对设计高精度电源提供了方便,每个PWM模块中又包括以下几个子模块:时基(Time-base)模块、计数比较(Counter-compare)模块、功能限定(Action-qualifier)模块、 ...…

查看全部问答∨

AD中断函数中取AD 转换结果,得到数据不正确

我需要在AD中断里面切换AD转换通道,但是只要在AD中切换通道得到的AD转换数据就不正常; 现象一、1、如果我在AD中断函数中只开启某一个AD转换通道,那么得到AD数据值a = (temp2<<8)+temp1,( 注释 temp2=ADC_DRH,temp1= ADC_DRL );a是正常的数 ...…

查看全部问答∨

滤波电路

谁能和我具体讲讲L型滤波电路和π型滤波电路各自的优劣?…

查看全部问答∨

TA 中断 疑问

void main(void) {   WDTCTL = WDTPW + WDTHOLD;             // Stop WDT   Init_Clk();   TA1CTL |= TASSEL_1+TACLR+TAIE;          ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved