历史上的今天
返回首页

历史上的今天

今天是:2024年09月01日(星期日)

正在发生

2021年09月01日 | STM32—驱动HC-SR04超声波测距模块

2021-09-01 来源:eefocus

超声波测距原理

利用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;

}

}

推荐阅读

史海拾趣

芯旺微电子(ChipON)公司的发展小趣事

芯旺微电子一直将技术创新作为公司发展的核心驱动力。公司拥有一支高素质的研发团队,不断在CPU系统结构、编译器、IDE软件、数模混合设计等领域进行技术创新和突破。这些技术创新的成果不仅提升了芯旺微电子的产品性能和质量,也为其在激烈的市场竞争中赢得了更多的机会和优势。

Heraeus公司的发展小趣事

近年来,芯旺微电子在资本市场也取得了显著的成果。公司先后完成了多轮融资,吸引了众多知名投资机构的关注和投资。同时,芯旺微电子也在积极推进上市进程,计划通过资本市场进一步拓展业务规模和提升品牌影响力。这些战略布局的实施不仅为芯旺微电子提供了更多的资金支持和发展动力,也为其未来的发展奠定了坚实的基础。

聚洵(Gainsil)公司的发展小趣事

芯旺微电子自2012年成立以来,始终致力于高可靠性MCU器件的研发设计。公司凭借其自主研发的KungFu内核架构处理器,迅速在汽车级和工业级混合信号MCU领域崭露头角。随着技术的不断积累和市场的深入拓展,芯旺微电子逐渐从一家初创公司发展成为国内车规级MCU市场的领军企业。

淩志比高公司的发展小趣事

随着国内市场的逐渐饱和,淩志比高公司开始将目光投向海外市场。公司制定了国际化战略,积极拓展海外市场,与多家国际知名企业建立了合作关系。通过不断的市场拓展和品牌推广,淩志比高逐渐在国际市场上获得了认可。

Gamewell-FCI ( Honeywell )公司的发展小趣事

为了进一步提升公司的知名度和影响力,淩志比高开始注重品牌建设和市场推广。公司积极参与行业展会、举办产品发布会等活动,与客户和合作伙伴建立了紧密的联系。同时,淩志比高还通过广告宣传、社交媒体营销等方式,提升了品牌知名度和美誉度。

Grayhill公司的发展小趣事
选择高质量的元件,如功率晶体管、电容、电阻等,以保证电路的稳定性和可靠性。

问答坊 | AI 解惑

送给单片机爱好者的礼物

送给单片机爱好者的礼物——相信大家一定用过很多LED数码管字段编码的小软件,由于单片机的IO口可以任意编程调换,在设计电路板时为了方便,调换了端口引脚顺序时,只需要在LED表编码做适当修改,就可以保证显示的字符正确!本文介绍的LED数码管在 ...…

查看全部问答>

无线收发题目素材

本帖最后由 paulhyde 于 2014-9-15 04:23 编辑 无线环境监测,估计题目。。。905程序。  …

查看全部问答>

一个软件工程师成长的六个阶段

第一阶段      此阶段主要是能熟练地使用某种语言。这就相当于练武中的套路和架式这些表面的东西。      第二阶段      此阶段能精通基于某种平台的接口(例如我们现在常用 ...…

查看全部问答>

volatile的作用

volatile的作用一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下 ...…

查看全部问答>

wince开机内存占用问题?

如上图,红色指示区域是wince进入桌面后程序内存的使用量。有9M多呢 这样子正常吗?启动应用都没运行呢! 哪位兄台解答一下啊? …

查看全部问答>

PXA270串口中断注册的问题~

PXA270有三个UART,全部连接MAX3073作为串口使用,奇怪的是已经用struct resource建立资源列表, 但Linux运行后使用cat /proc/interrupts显示只有第一个Full Function UART的中断,其他两个没有。 这是怎么回事呢?         ...…

查看全部问答>

wince开始菜单的源码的位置?

rt wince开始菜单的源码的位置在哪…

查看全部问答>

用SCSI_PASS_THROUGH 参数deviceiocontrol返回错误

用deviceiocontrol向设备发SCSI_PASS_THROUGH 命令,函数返回0,正常为非零,但设备已经收到命令,我要返回的结果,弄了好长时间,不明白,哪位有过类似经验,指点下,谢谢!…

查看全部问答>

对于STR711的芯片bootloader该如何修改?

实验室有一块EK-STR711的开发板(arm7tdmi),现在想做嵌入式系统,下载了u-boot-1.1.6,发现不知道该如何修改。网络上很多资料都是三星的芯片。可是我的芯片在u-boot中找不到相应的,不知道该如何下手。希望高手指点一下,万分感谢!…

查看全部问答>