测距原理

HC-SRF05超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。像智能小车的测距以及转向,或是一些项目中,常常会用到。智能小车测距可以及时发现前方的障碍物,使智能小车可以及时转向,避开障碍物。

原理:
1.给超声波模块接入电源和地;
2.给脉冲触发引脚(trig)输入一个长为20us的高电平方波;
3.输入方波后,模块会自动发射8个40KHz的声波,与此同时回波引脚(echo)端的电平会由0变为1;(此时应该启动定时器计时);
4.当超声波返回被模块接收到时,回波引 脚端的电平会由1变为0;(此时应该停止定时器计数),定时器记下的这个时间即为超声波由发射到返回的总时长;
5.根据声音在空气中的速度为344米/秒,即可计算出所测的距离。

时序图表明你只需要提供一个10us以上脉冲信号,该模块内部将发出8个40kHz周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。

个人经验

上面的理论大可不必了解,这个东西无非就是通过声波测距,重点还是在代码上,搞了将近两周,踩了一些坑,和大家分享下:
1、5v的电压一定要接好,不然串口就会返回一个固定的值!
2、如果使用一般的延时来计时的话,配置好定时器就好了;但如果选择输入捕获来完成,注意配置时通道要对应好,否则串口会返回0或者很大的数。

3、如果使用不同定时器进行则分别配置,如使用同一个定时器的不同通道,则注意逻辑:不能接到上升/下降沿就关闭定时器,会相互影响。
4、注意定时器时32位还是16位,可能存在数据位数导致的错误。

代码

我使用的是stm32f4,两个定时器,两路超声波,如果需要一个定时器稍稍改一下逻辑即可:
初始化定时器:(正点原子例程也有):

     TIM_ICInitTypeDef  TIM3_ICInitStructure;GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;
//定时器3通道4,定时器9通道1输入捕获配置
void HC_Reci_TIM3_Init(u16 arr,u16 psc)
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);     //TIM3时钟使能 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);    //使能PORTB时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//PB1定时器3通道4GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;    //速度100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化PB1GPIO_PinAFConfig(GPIOB,GPIO_PinSource1,GPIO_AF_TIM3); //PB1复用位定时器3TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);//初始化TIM3通道4输入捕获参数TIM3_ICInitStructure.TIM_Channel = TIM_Channel_4; //CC1S=01    选择输入端 IC4映射到TI4上TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;   //上升沿捕获TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;    //配置输入分频,不分频 TIM3_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波TIM_ICInit(TIM3, &TIM3_ICInitStructure);//允许更新中断,触发方式中断TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);TIM_ITConfig(TIM3,TIM_IT_Trigger,ENABLE);NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;       //子优先级0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //IRQ通道使能NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器、TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允许更新中断 ,允许CC1IE捕获中断 TIM_Cmd(TIM3,ENABLE );  //使能定时器3
}

输入捕获:

void TIM3_IRQHandler(void)//TIM3通道4
{if((HC_1.sta&0X80)==0)//还未成功捕获   {if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//溢出{    Send_sound(GPIOB,GPIO_Pin_0);               if(HC_1.sta&0X40)//已经捕获到高电平了{if((HC_1.sta&0X3F)==0X3F)//高电平太长了{HC_1.sta|=0X80;       //标记成功捕获了一次HC_1.val=0XFFFF;}else HC_1.sta++;}     }if(TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET)//捕获1发生捕获事件{   if(HC_1.sta&0X40)       //捕获到一个下降沿      {               HC_1.sta|=0X80;        //标记成功捕获到一次高电平脉宽HC_1.val=(u16)TIM_GetCapture4(TIM3);//获取当前的捕获值.HC_1.temp=HC_1.sta&0X3F; HC_1.temp*=0XFFFF;                        //溢出时间总和HC_1.temp+=HC_1.val;         //得到总的高电平时间HC_1.Distance=HC_1.temp*172/10000;//cmHC_1.sta=0;               //开启下一次捕获printf("HC1: %d\n",HC_1.Distance);TIM_OC4PolarityConfig(TIM3,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
//                    Send_sound(GPIOB,GPIO_Pin_0);}else                                //还未开始,第一次捕获上升沿{HC_1.sta=0;            //清空HC_1.val=0;HC_1.sta|=0X40;        //标记捕获到了上升沿TIM_Cmd(TIM3,DISABLE );  //关闭定时器3TIM_SetCounter(TIM3,0);TIM_OC4PolarityConfig(TIM3,TIM_ICPolarity_Falling);      //CC1P=1 设置为下降沿捕获TIM_Cmd(TIM3,ENABLE );    //使能定时器3}           }                                              }TIM_ClearITPendingBit(TIM3, TIM_IT_CC4|TIM_IT_Update);
}

发送高电平:

void Send_sound(GPIO_TypeDef* GPIOx,uint16_t Pinx)
{GPIO_SetBits(GPIOx,Pinx);delay_us(20);GPIO_ResetBits(GPIOx,Pinx);
}

那么任务函数就很简洁了:

void sentry_ultrasonic ()
{HC_ult_send();HC_Reci_TIM3_Init(0XFFFF,84-1); //以1Mhz的频率计数 1us计数HC_Reci_TIM9_Init(0XFFFF,84-1);while(1){        task_delay_ms(50);}
}

以上代码已经经过串口验证无误,超声波测距正常。搞了快两周的测距模块终于差不多了,尽管踩坑无数。

萌新初来报道,多多包涵,大家凑合看哈。拜谢支持。

HY-SRF05 五针超声波测距模块 在stm32f4上实现 附代码 个人经验相关推荐

  1. STM32F103超声波HCSR04模块串口输出距离(附代码)

    1. 接线 VCC-5V; GDN-GND; TRIG-PB6; ECOH-PB9 也可自行选择不冲突引脚 2. 代码部分 csb.c //.c文件 #include "delay.h&qu ...

  2. arduino UNO 与 超声波测距模块 实验详情

    US-015 超声波测距模块 超声波传感器 US-020升级版 送全套资料 资料下载地址:http://pan.baidu.com/s/1c0AfkIG US-015超声波测距模块 1. 概述 US- ...

  3. STM32单片机基于HAL库开发HC-SR04 超声波测距模块(终极版)

    参考: 某宝HC-SR04 超声波测距模块商品详情页 STM32L051C8T6 HAL库 输入捕获进行超声波测距 案例 STM32CubeMX学习笔记3--TIM2输入捕获(SR-04测距) cub ...

  4. STM32——超声波测距模块(HAL库CubeMx)

    超声波测距 1. 超声波测距模块原理 2. CubeMx配置 3. 代码的编写 3.1 定时器计时的计算 3.2 接口函数 1. 超声波测距模块原理 (2021/11/28 16:25编辑) 超声波测 ...

  5. US-016超声波测距模块

    1.  概述 US-016超声波测距模块可实现2cm~3m的非接触测距功能,供电电压为5V,工作电流为3.8mA,支持模拟电压输出,工作稳定可靠.本模块根据不同应用场景可设置成不同的量程(大测量距离分 ...

  6. 51单片机:HCSR04超声波测距模块及1602显示—C51程序(超详细)

    测试完成于STC89C516单片机,晶振12MHZ.超声波模块Echo=P1^0.Trig=P1^1,1602液晶8位数据口=P0.E=P2^7.RS=P2^6.RW=P2^5.. 程序文件分为4部分 ...

  7. stm32控制超声波测距模块HC-SR04

    引脚:PB15 TRIG,PB0 ECHO: 不同距离,LED对应不良.闪烁.亮状态,并通过串口发送到PC; TIM3定时中断,测出脉宽长度,没有像野火一样使用捕捉功能: 1.HS-SR04模块实物图 ...

  8. 【mcuclub】超声波测距模块HC-SR04

    一.实物图 二.原理图 编号 名称 功能 1 VCC 电源正 2 TRIG 触发控制信号输入 3 ECHO 回响信号输出 4 GND 电源地 三.简介 由于超声波指向性强,能量消耗缓慢,在介质中传播的 ...

  9. STM32智能小车------超声波测距模块

    文章目录 一.原理讲解 1.实物图 2.工作原理: 3.接线: 二.软件驱动代码 1.接口定义 2.驱动函数 总结 最终效果 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的普通大学生. 进 ...

  10. 通过串口打印--超声波测距模块测得距离

    通过串口打印--超声波测距模块测得距离 原理 超声波测距模块 串口传输 实战代码 原理 超声波测距模块 在这里首先需要了解超声波测距模块的原理.在我的这篇博客有很多介绍.超声波模块介绍 串口传输 串口 ...

最新文章

  1. python下载文件的11种方式_Python 中常见的几种下载文件方法
  2. 修复迁移后Net Standard项目中的错误
  3. mysql typeindex_explain mysql的type字段,索引的类型
  4. mac下查看redis安装路径_干货!win10环境下Redis安装、启动教程
  5. C# 编程规范 (coding standard)
  6. 【干货】腾讯人力资源与组织管理体系.pptx(附下载链接)
  7. 在Recyclerview使用GlideAPP加载大量图片导致内存溢出(oom)
  8. iOS开发那些事-iOS应用本地化-资源文件本地化
  9. 使用lex与yacc词法语法工具进行简单的SQL语义检查
  10. Android——获取实时的手机屏幕四个点经纬度(百度地图)
  11. ReadHub android版
  12. 使用python将excel单元格中指定文字加粗标红
  13. 饥荒服务器不显示管理员,饥荒联机版管理员怎么添加_饥荒联机版管理员介绍与添加方法详解_玩游戏网...
  14. 解读Seele元一子链协议 产业公链底层框架非常完美!
  15. Android ListView下拉刷新
  16. 路径中的'.'和'..'还有'./'和'../'都是什么意思
  17. IT风云15年的那些人、那些事(一)
  18. C#制作activeX控件
  19. 一文详解东数西算下绿色数据中心节能减排十大技术、智算中心八大趋势
  20. 计算机无法启动硬盘损坏,如果无法打开计算机硬盘分区该怎么办? chkdsk方法修复损坏的磁盘...

热门文章

  1. Peeking into the Future: Predicting Future Person Activities and Locations in Videos 翻译
  2. 论文阅读笔记--Predicting Human Eye Fixations via an LSTM-based Saliency Attentive Model
  3. 数据结构——数组以及n维数组
  4. AopAutoConfiguration matched的异常
  5. 瀑布模型(waterfall model)需求明确+严格顺序执行
  6. 曲婉婷-----没有什么不同
  7. 使用开源文档工具docsify,用写博客的姿势写文档
  8. 大文件异步分片上传到Seaweed服务器
  9. 从云到「链」,京东云成为中国第四朵云背后
  10. Ubuntu系统中如何删除一个用户