完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
超声波测距原理
利用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_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; } } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1561 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1501 浏览 1 评论
933 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
665 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1555 浏览 2 评论
1847浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
609浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
503浏览 3评论
507浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
488浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-10 13:36 , Processed in 0.863202 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号