用超声波模块来测距是非常方便有效的方式,而且精度比较高。超声波测距模块就是通过测量声波从发出到反射回来的时间来计算距离。因为声音在空气中传播的速度大概在340m/s左右,知道了往返时间再乘以速度就可以得出距离了。当然声速并不一定是固定的,这与空气温度、气压都是有一定关系的,因此超声波存在一定的误差。

超声波模块提供的使用接口很简单,除了5V和GND的供电接口外,提供了Trig和Echo两个口。在使用时,如下图:

首先单片机通过Trig口,产生10微秒以上的高电平(其实时间更长一些也不会有太大影响),然后超声波模块会自动发射出一串40kHz的超声波。发射结束后,超声波模块内部开始计数,超声波被发出后,沿直线方向前进,如果遇到面积比较大的目标,其一部分的声波会被反射回来,然后在A点时刻,返回的声波被超声波探头接收到。超声波模块接收到回波就会立刻拉高Echo引脚,然后持续 “它等待声波的那段时间” 后,在B点时刻将Echo下拉。

因此在使用时,我们需要在Echo的上升沿(A点)开始计时,然后在下降沿(B点)停止计时,得到的时间就是声波传递往返的时间。

一、单片机部分

1.1硬件连接

这里我用两个普通IO口连接其Trig和Echo。在程序中使用的是Trig为PA6,Echo为PA7。

1.2代码编写

1.2.1超声波程序

首先初始化,这里采用STM32的EXTI(外部中断)的功能,用于检测Echo口的上升沿和下降沿,以确定A点和B点。然后使用STM32的TIM2定时器来计时,当Echo上升沿时开始计时,下降沿时结束,并读取计时数值。

void initUltraSonic(){

GPIO_InitTypeDef GPIO_InitStructure;

EXTI_InitTypeDef EXTI_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB2PeriphClockCmd(USONIC_PORT_CLOCK, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

GPIO_InitStructure.GPIO_Pin = TRIG_PIN ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(USONIC_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = ECHO_PIN;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(USONIC_PORT, &GPIO_InitStructure);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource7);

EXTI_InitStructure.EXTI_Line = EXTI_Line7;

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

TIM_Cmd(TIM2,ENABLE); // 虽然TIM2挂载在36MHz的APB1下,但是其实际最高时钟频率可达72MHz。

TIM_TimeBaseStructure.TIM_Period = 65535;

TIM_TimeBaseStructure.TIM_Prescaler = 719; /// 719 = (72000000/100000)-1 ,每10us 计数器加一

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);

GPIO_ResetBits(USONIC_PORT,TRIG_PIN);}

下面是中断处理函数,STM32外部中断处理比较奇葩,为了节省函数入口,将Pin5到Pin9的通道合到一起,然后在中断处理函数中判断到底是哪个脚触发了中断。

void  EXTI9_5_IRQHandler(void)

{

if(EXTI_GetITStatus(EXTI_Line7))

{

//上升沿

if(GPIO_ReadInputDataBit(USONIC_PORT,ECHO_PIN))

{

//清零定时器值

TIM2->CNT=0;

//开始计时

TIM_Cmd(TIM2,ENABLE);

}else//下降沿

{

//读取定时器值

c = TIM2->CNT;

TIM_Cmd(TIM2,DISABLE);

}

//清除中断标志位

EXTI_ClearITPendingBit(EXTI_Line7);

}

}

然后是一个10微秒的延时程序,其实我也不知道是不是10微秒,实测是可以用的。

void delay10us(void){

for(short s=0;s<70;s++)

{}

}

然后是读取距离的函数:

short procUltraSonic(void){

short distance_mm;

if(c!=0)

distance_mm= (17*c/10);

GPIO_SetBits(USONIC_PORT,TRIG_PIN);

delay10us();

GPIO_ResetBits(USONIC_PORT,TRIG_PIN);

c=0;

return distance_mm;

}

1.2.2通信配置

//根据实际需要的变量,定义数据包中 bool byte short int float 五种类型的数目

#defineTX_BOOL_NUM0

#defineTX_BYTE_NUM0

#defineTX_SHORT_NUM 1

#defineTX_INT_NUM0

#defineTX_FLOAT_NUM0

在valuepack.h中定义收发的数据,由于只回传一个距离值,因此定义short的数目为1。

1.2.3主函数

TxPack txpack;

int main(void)

{

initUltraSonic();

initValuePack(115200);

while(1)

{

//延时

for(int i=0;i<1000000;i++)

{}

txpack.shorts[0] =procUltraSonic();

sendValuePack(&txpack);

}

}

在主函数中只需要调用procUltraSonic函数,即可得到毫米为单位的short值。

完整代码在此

二、手机端(使用蓝牙调试器)

2.1配置通信

2.2编辑控件

。。。链接和布局,具体我就不说了,在我之前的文章已经介绍了,如果有疑问,点击这里。

扫描下边的二维码下载 蓝牙调试器 搭建你自己的App界面

俗人一个,只要有人用了我的应用之后回来说一句“挺好用”我就真的满足了。当然能让我不饿肚子就更好了,大龄青年真的没脸问父母要钱。觉得有意思的话,支持一下吧。

单片机开发无线控制系列-手机无线超声波测距相关推荐

  1. 安卓连接linux软件,利用 Telnet 无线控制安卓手机 无需 Root

    以往的文章里菲菲君一直在极力推荐 adb 来远程执行安卓 shell 命令,虽然 adb 也支持无线连接但需 Root 权限(现在的 Android 真的没有 Root 的必要了),连接数据线又很麻烦 ...

  2. OpenWrt配置打印服务器无线桥接,手机无线打印

    无线桥接,先无线桥接路由器,无线网卡配置静态ip网关dns且禁用本地dhcp(ip取自桥接后自动获取的ip,复制粘贴即可),防火墙区域设置入站数据接受,使用原wifi信号ssid访问无线网卡ip访问打 ...

  3. 单片机开发无线控制系列-单片机端代码实现

    借助蓝牙调试器我们可以很轻易地通过各种控件操作变量,现在要考虑的是如何让单片机获知这些变量? 首先确定单片机和蓝牙串口模块的连接方式: 需要注意的是蓝牙串口模块与单片机之间的连接,其TX.RX与单片机 ...

  4. 111、基于51单片机的电磁感应无线充电系统 手机无线充电器设计(程序+原理图+Proteus仿真+程序流程图+论文参考资料等)

    方案选择 单片机的选择 方案一:AT89C52是美国ATMEL公司生产的低电压,高性能CMOS型8位单片机,器件采用ATMEL公司的高密度.非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通 ...

  5. php声波模拟开门,关于 php使用扩展控制树莓派io 驱动超声波测距

    经过昨天一下午,终于写好了基于 只需要安装完毕,就可以调用函数了:<?php /** * Created by PhpStorm. * User: tioncico * Date: 19-7-6 ...

  6. 基于单片机的地铁(公交)无线控制报站系统设计 地铁报站系统设计 公交报站系统设计

    系统设计前言 基于单片机的地铁(公交)无线控制报站系统设计是酷毕啦电子设计室报站系列的无线控制版本,无线控制的特点是布线少.控制方便等功能,体现出物联网控制的技术.介于大部分需求的群体都是本科设计,所 ...

  7. HC-SR04超声波测距块讲解(附32单片机源码)

    文章目录 一.HC-SR04超声波测距模块原理 1.模块简介 2.模块电气参数 3.模块工作原理 二.HC-SR04超声波测距模块与32单片机接线 三.32单片机源码 总结 一.HC-SR04超声波测 ...

  8. 基于51单片机的智能停车场管理车位引导系统红外检测无线蓝牙/WiFi手机APP控制设计

    本系统由STC89C52单片机.(无线蓝牙/WIFI模块-可选).红外对管传感器.LCD1602液晶显示.LED指示灯及电源组成. 通过红外对管模块实时检测车位是否占用,车位分为1车位.2车位.3车位 ...

  9. 手机android app 无线控制led灯开关

    先讲一下整体思路哈!手机肯定不能直接控制台灯的,需要一个中间物来协调,在这里我用的是51单片机(如果大家不知道也没关系,下面我还会说的).接下来就是具体怎么控制的,其实原理挺简单的.1.手机通过蓝牙来 ...

最新文章

  1. 【转】Android Studio系列教程一--下载与安装
  2. Android Treble架构解析
  3. 8.类定义、属性、初始化和析构
  4. ORA-29702:error occurred in Cluster Group Service operation错误解决
  5. 服务器简历共享文件,通过 NFS 实现服务器目录共享
  6. java 数据分析 用户信息_Java数据库——使用元数据分析数据库
  7. 微软纸牌服务器慢,微软为何设计纸牌和扫雷?真是用心良苦
  8. linux-centos使用 wget命令获取jdk
  9. markdown首行空两格
  10. Java SE基础——Java集合
  11. FinClip黑客马拉松@您,小程序风云来袭
  12. [蓝牙 Mesh Zephyr]-[001]-Mesh beacon
  13. lic文件用计算机程序打开,LIC 文件扩展名: 它是什么以及如何打开它?
  14. 英仕曼235年传奇之路从CTA策略鼻祖到全球最大上市对冲基金
  15. 将 libVLC 视频渲染到 QWidget 中
  16. Scrapy框架学习 - 爬取豆瓣电影排行榜TOP250所有电影信息并保存到MongoDB数据库中
  17. 100行代码撸一个语音对话助手
  18. 如何更改Code::Blocks背景颜色(懒人版)
  19. python 验证码 高阶验证
  20. 2022年 Q1书单:17本书《可口可乐传》《随机漫步的傻瓜》等 | δ星 丨读书笔记与书单 notes...

热门文章

  1. Python 二进制文件流转图片
  2. com lofter android,LOFTER
  3. 一段集大成的thymeleaf代码
  4. git clone 失败问题解决方案
  5. opencv 脸部识别开源软件
  6. springboot毕设项目同城上门喂遛宠物预约vfo34(java+VUE+Mybatis+Maven+Mysql)
  7. SpringBoot 博客开发 个人学习(项目开始和前端页面)
  8. 07_音频录制01_命令行
  9. kali linux 64bit 2019.1a下启动bbqsql:No module named coros
  10. 塑料粘结硬质铁氧体磁铁的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告