本篇文章是个人整理的包含超声波测距模块HC-SR04的基本介绍与基本工作原理以及分别通过LCD1602、数码管和串口显示距离的实例讲解与代码的笔记,部分内容来自《HC-SR04超声波测距模块说明书》,代码使用模块化编辑,部分模块来自江科大自化协的51单片机教学视频。
希望大家早日掌握单片机。
超声波测距模块是根据超声波遇障碍反射的原理进行测距的,能够发送超声波、接收超声波并通过处理,输出一段和发送与接收间隔时间相同的高电平信号,是常用的测距模块之一。HC-SR04是最常用的超声波测距模块之一,HC-SR04超声波模块可提供2cm~400cm的非接触式距离感测功能,测距精度可达3mm,工作电压为5V;内部模块包括超声波发射器、接收器与控制电路。如下为实物与对应端口图:

(1)采用I/O口连接Trig触发测距,给最少10us的高电平后即可发送超声波;
(2)模块自动发送8个40kHz的方波,并自动检测是否有信号返回;
(3)若有信号返回,经内部电路处理后,通过Echo到I/O口输入一个高电平,高电平持续的时间就是超声波从发射到返回的时间;
(4)测试距离=(高电平时间*音速)/2;音速=340m/s=0.034cm/us。

以上时序图表明你只需要向模块提供一个10us以上的脉冲触发信号,然后该模块内部将发出8个40kHz周期电平并检测回波,一旦检测到有回波信号,模块就向I/O口输出回响信号。回响信号的脉冲宽度与所测的距离成正比,由此通过回响信号的高电平时间计算得到距离。建议先将单位转换为cm/us,便于数据显示;测量周期为60ms以上,以防止发射信号对回响信号的影响。
先将端口初始化(置0),再通过Trig输入一个12us的高电平作为触发信号,最后接收回响信号,回响信号高电平的时间通过定时器0测量——当Echo为1时开始计时,Echo为0时结束计时,不需要打开中断。得到时间后根据公式:测试距离=(高电平时间*音速)/2;音速=340m/s=0.034cm/us,计算出实际距离。
调用LCD1602函数进行显示:
调用数码管函数进行显示,使用定时器扫描数码管。
#include <REGX52.H>
#include "Timer0.h"
//定义引脚接口
sbit Trig = P1^0;
sbit Echo = P1^1;
/**
* @brief HC-SR04初始化
* @param 无
* @retval 无
*/
void HCSR04_Init()
{
Timer0_Init();
Trig = 0;
Echo = 0;
}
/**
* @brief HC-SR04接收一个12us的触发信号
* @param 无
* @retval 无
*/
void HCSR04_Trig()
{
unsigned char i;
Trig = 1;
i = 5;while (--i); //延时12us
Trig = 0;
}
/**
* @brief HC-SR04接收触发信号并计算回波信号高电平时间
* @param 无
* @retval 无
*/
void HCSR04_Set()
{
HCSR04_Trig();
while(!Echo);
TR0 = 1;
while(Echo);
TR0 = 0;
}
/**
* @brief HC-SR04计算模块与障碍间的距离
* @param Duration(持续时间) 发送到接收的间隔时间
* @param Distance 模块与障碍间的距离
* @retval Distance
*/
float HCSR04_Calc()
{
unsigned int Duration = 0;
float Distance = 0;
Duration = TH0*256+TL0;
Distance = Duration*0.017;//时间*音速/2,音速=340m/s=0.034cm/us
TH0 = 0;
TL0 = 0;
return Distance;
}
#include <REGX52.H>
/**
* @brief 定时器0初始化@11.0592MHz
* @param 无
* @retval 无
*/
void Timer0_Init() //@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TH0 = 0; //设置定时初值
TL0 = 0; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0不计时
}
#include <REGX52.H>
#include "Delay.h"
#include "HCSR04.h"
#include "LCD1602.h"
unsigned int Distance;
void main()
{
LCD_Init(); //LCD1602初始化
HCSR04_Init(); //HC-SR04初始化
LCD_ShowString(1,1,"Distance:");
LCD_ShowString(2,4,"cm");
while(1)
{
HCSR04_Set(); //HC-SR04接收触发信号并计算回波信号高电平时间
Distance = HCSR04_Calc(); //计算距离
LCD_ShowNum(2,1,Distance,3);//调用显示
Delay(20);
}
}
#include <REGX52.H>
#include "Delay.h"
//数码管显示缓存区
unsigned char Nixie_Buf[9]={0,10,10,10,10,10,10,10,10};
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};
/**
* @brief 设置显示缓存区
* @param Location 要设置的位置,范围:1~8
* @param Number 要设置的数字,范围:段码表索引范围
* @retval 无
*/
void Nixie_SetBuf(unsigned char Location,Number)
{
Nixie_Buf[Location]=Number;
}
/**
* @brief 数码管扫描显示
* @param Location 要显示的位置,范围:1~8
* @param Number 要显示的数字,范围:段码表索引范围
* @retval 无
*/
void Nixie_Scan(unsigned char Location,Number)
{
P0=0x00; //段码清0,消影
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
}
/**
* @brief 数码管驱动函数,在中断中调用
* @param 无
* @retval 无
*/
void Nixie_Loop(void)
{
static unsigned char i=1;
Nixie_Scan(i,Nixie_Buf[i]);
i++;
if(i>=9){i=1;}
}
#include <REGX52.H>
/**
* @brief 定时器1初始化,1ms@11.0592MHz
* @param 无
* @retval 无
*/
void Timer1_Init(void)
{
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0x65; //设置定时初值
TH1 = 0xFC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1=1;
EA=1;
PT1=0;
}
/*定时器中断函数模板
void Timer1_Routine() interrupt 3
{
static unsigned int T1Count;
TL1 = 0x65; //设置定时初值
TH1 = 0xFC; //设置定时初值
T1Count++;
if(T1Count>=1000)
{
T1Count=0;
}
}
*/
#include <REGX52.H>
#include "Timer0.h"
//定义引脚接口
sbit Trig = P1^0;
sbit Echo = P1^1;
/**
* @brief HC-SR04初始化
* @param 无
* @retval 无
*/
void HCSR04_Init()
{
Timer0_Init();
Trig = 0;
Echo = 0;
}
/**
* @brief HC-SR04接收一个12us的触发信号
* @param 无
* @retval 无
*/
void HCSR04_Trig()
{
unsigned char i;
Trig = 1;
i = 5;while (--i); //延时12us
Trig = 0;
}
/**
* @brief HC-SR04接收触发信号并计算回波信号高电平时间
* @param 无
* @retval 无
*/
void HCSR04_Set()
{
HCSR04_Trig();
while(!Echo);
TR0 = 1;
while(Echo);
TR0 = 0;
}
/**
* @brief HC-SR04计算模块与障碍间的距离
* @param Duration(持续时间) 发送到接收的间隔时间
* @param Distance 模块与障碍间的距离
* @retval Distance
*/
unsigned int HCSR04_Calc()
{
unsigned int Distance,Duration;
Duration = TH0*256+TL0;
Distance = Duration*0.017;//时间*音速/2,音速=340m/s=0.034cm/us
TH0 = 0;
TL0 = 0;
return Distance;
}
#include <REGX52.H>
#include "Delay.h"
#include "HCSR04.h"
#include "Nixie.h"
#include "Timer1.h"
unsigned int Distance;
void main()
{
HCSR04_Init(); //HC-SR04初始化
Timer1_Init(); //定时器1初始化
while(1)
{
HCSR04_Set(); //HC-SR04接收触发信号并计算回波信号高电平时间
Distance = HCSR04_Calc(); //计算距离
Nixie_SetBuf(1,Distance/100);
Nixie_SetBuf(2,Distance%100/10);
Nixie_SetBuf(3,Distance%100%10);//调用显示
Delay(50);
}
}
void Timer1_Routine() interrupt 3
{
static unsigned int T1Count1;
TL1 = 0x65; //设置定时初值
TH1 = 0xFC; //设置定时初值
T1Count1++;
if(T1Count1>=2)
{
T1Count1=0;
Nixie_Loop();//2ms调用一次数码管驱动函数
}
}
#include <REGX52.H>
#include "Timer0.h"
//定义引脚接口
sbit Trig = P1^0;
sbit Echo = P1^1;
/**
* @brief HC-SR04初始化
* @param 无
* @retval 无
*/
void HCSR04_Init()
{
Timer0_Init();
Trig = 0;
Echo = 0;
}
/**
* @brief HC-SR04接收一个12us的触发信号
* @param 无
* @retval 无
*/
void HCSR04_Trig()
{
unsigned char i;
Trig = 1;
i = 5;while (--i); //延时12us
Trig = 0;
}
/**
* @brief HC-SR04接收触发信号并计算回波信号高电平时间
* @param 无
* @retval 无
*/
void HCSR04_Set()
{
HCSR04_Trig();
while(!Echo);
TR0 = 1;
while(Echo);
TR0 = 0;
}
/**
* @brief HC-SR04计算模块与障碍间的距离
* @param Duration(持续时间) 发送到接收的间隔时间
* @param Distance 模块与障碍间的距离
* @retval Distance
*/
float HCSR04_Calc()
{
unsigned int Duration = 0;
float Distance = 0;
Duration = TH0*256+TL0;
Distance = Duration*0.017;//时间*音速/2,音速=340m/s=0.034cm/us
TH0 = 0;
TL0 = 0;
return Distance;
}
#include <REGX52.H>
/**
* @brief 串口初始化,9600bps@12.000MHz
* @param 无
* @retval 无
*/
void UART_Init()
{
//设定定时器0和定时器1的工作模式
TMOD = 0x21;
//设置定时器0用于计时
TH0 = 0;
TL0 = 0; //设定定时器0重装初值
TF0 = 0; //清除TF1标志
TR0 = 0; //停止定时器0
//设置定时器1用于串口波特率
SCON = 0x40; //设定串行口工作方式1
PCON = 0x00; //波特率不翻倍
TH1 = 0xFD;
TL1 = 0xFD; //设定定时器1重装初值,波特率为9600
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
TI = 1; //将发送中断请求标志位置1,使计算机不断接收数据
}
#include <REGX52.H>
#include <stdio.h>
#include "Delay.h"
#include "HCSR04.h"
#include "UART.h"
float Distance;
void main()
{
UART_Init(); //串行口初始化
while(1)
{
HCSR04_Set(); //HC-SR04接收触发信号并计算回波信号高电平时间
Distance = HCSR04_Calc(); //计算模块与障碍间的距离
printf("--.---cm\n"); //在串口上打印分割线
printf("Distance=%.3f cm\n",Distance); //在串行口上打印距离数据
Delay(200); //延时200ms
}
}
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
我试图在Ubuntu14.04中使用Curl安装RVM。我运行了以下命令:\curl-sSLhttps://get.rvm.io|bash-sstable出现如下错误:curl:(7)Failedtoconnecttoget.rvm.ioport80:Networkisunreachable非常感谢解决此问题的任何帮助。谢谢 最佳答案 在执行curl之前尝试这个:echoipv4>>~/.curlrc 关于ruby-在Ubuntu14.04中使用Curl安装RVM时出错,我们在Stack
安装Rails时,一切都很好,但后来,我写道:rails-v和输出:/home/toshiba/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in`require':cannotloadsuchfile--rails/cli(LoadError)from/home/toshiba/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in`r
一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
提供3种Ubuntu系统安装微信的方法,在Ubuntu20.04上验证都ok。1.WineHQ7.0安装微信:ubuntu20.04安装最新版微信--可以支持微信最新版,但是适配的不是特别好;比如WeChartOCR.exe报错。2.原生微信安装:linux系统下的微信安装(ubuntu20.04)--微信适配的最好,反应最快,但是微信版本只到2.1.1,版本太老,很多功能都没有。3.深度deepin-wine6安装微信:ubuntu20.04+系统deepin-wine6安装新版微信--综合比较好,当前个人使用此种方法1个月,微信版本3.4;没什么大问题,尚可。一、WineHQ7.0安装微信
这个问题在这里已经有了答案:Unabletoinstallgem-Failedtobuildgemnativeextension-cannotloadsuchfile--mkmf(LoadError)(17个答案)关闭9年前。嘿,我正在尝试在一台新的ubuntu机器上安装rails。我安装了ruby和rvm,但出现“无法构建gemnative扩展”错误。这是什么意思?$sudogeminstallrails-v3.2.9(没有sudo表示我没有权限)然后它会输出很多“获取”命令,最终会出现这个错误:Buildingnativeextensions.Thiscouldtakeawhi
这是什么。我首先做了:rvmgetstablervminstallruby-2.2.2没有交易。它向我展示了以下内容:$rvminstallruby-2.2.2Searchingforbinaryrubies,thismighttakesometime.Nobinaryrubiesavailablefor:ubuntu/14.04/i386/ruby-2.2.2.Continuingwithcompilation.Pleaseread'rvmhelpmount'togetmoreinformationonbinaryrubies.Checkingrequirementsforubunt
开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建