学习STC51单片机13(芯片为STC89C52RC)
我去,兄弟们我们今天来学习一个牛逼 的硬件,它叫超声波测距模块HC—SR04
硬件:HC—SR04
哎,想当初最想要玩的就是这个模块,科技感十足,那现在就让我们玩玩吧
超声波测距传感器
原理就是说需要给Trig 10us的高电平,相当于是一个信号,到模块内部,模块内部有脉冲模块一直向着外部发送超声波,此时echo由低电平变成了高电平,然后如果有障碍物了,那么返回到echo里面会由高电平转换为低电平,计算的就是echo接收的第一个波到最后一个波,由高电平到最后一个波结束变成低电平的时间
因为你可以拿 0001(1) 0010(2) 0100(3) 1000(4) 这个几个二进制数从1转换到4,你一个个转换会发现就是有这个规律 :二进制左移一位相当于x2的一次方 左移8位相当于左移2的8次方
超声波的时序图:(这也是我们第一次接触时序图)
这个是我们的最终代码,其中有很多的优化细节 都是为了测试硬件和提高稳定性的,所以有些代码不是功能的实现,而是细节的提升
#include "reg52.h"
#include <intrins.h> // 包含_nop_()函数
sbit D5 = P3^7; // 黄灯(距离<10cm时亮)
sbit D6 = P3^6; // 蓝灯(距离≥10cm时亮)
sbit Trig = P1^5; // 超声波触发引脚
sbit Echo = P1^6; // 超声波接收引脚
// 精确延时函数
void Delay10us() //@11.0592MHz
{
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
}
void Delay50ms() //@11.0592MHz
{
unsigned char i, j;
i = 90;
j = 163;
do
{
while (--j);
} while (--i);
}
void Delay100ms() //@11.0592MHz
{
unsigned char i, j;
i = 183;
j = 105;
do
{
while (--j);
} while (--i);
}
// 定时器0初始化(16位模式)
void Time0_Init()
{
TMOD &= 0xF0; // 清零T0模式位
TMOD |= 0x01; // 设置T0为模式1(16位定时器)
TH0 = 0; // 初始化计数寄存器
TL0 = 0;
TR0 = 0; // 初始不启动定时器
}
// 触发超声波测距
void Trigger_HC_SR04()
{
Trig = 0;
_nop_();
Trig = 1; // 发送至少10μs的高电平触发信号
Delay10us();
Trig = 0;
}
// 主函数
void main()
{
unsigned int Time; // 超声波飞行时间(μs)
unsigned int Distance; // 距离(cm)
unsigned int timeout; // 超时计数器
unsigned char i; // 定义循环变量(解决编译错误)
Time0_Init(); // 初始化定时器
// 上电自检:LED交替闪烁3次
for(i=0; i<3; i++) { // 修正后的for循环
D5 = 0; D6 = 1; // 黄灯亮
Delay100ms();
D5 = 1; D6 = 0; // 蓝灯亮
Delay100ms();
}
// 默认状态:蓝灯亮(表示距离≥10cm)
D5 = 1;
D6 = 0;
Delay100ms(); // 等待传感器稳定
while(1)
{
// 确保Echo初始为低电平(否则可能是传感器异常)
if(Echo == 1) {
D5 = 1; D6 = 1; // 双灯亮表示异常
Delay100ms();
continue;
}
// 触发测距
Trigger_HC_SR04();
// 等待Echo变高(添加超时:约10ms)
timeout = 10000;
while(Echo == 0 && --timeout);
if(timeout == 0) {
D5 = 1; D6 = 1; // 超时错误:双灯亮
Delay50ms();
continue;
}
// 启动定时器
TH0 = 0;
TL0 = 0;
TR0 = 1;
// 等待Echo变低
timeout = 65535;
while(Echo == 1 && --timeout);
TR0 = 0;
// 计算距离(仅在未超时的情况下)
if(timeout != 0) {
// 计算时间(晶振补偿:11.0592MHz需要乘以1.085)
Time = (TH0 * 256 + TL0) * 1.085;
// 计算距离(单位:cm)
Distance = Time * 17 / 1000; // 等价于Time * 0.017
// 根据距离控制LED
if(Distance < 10) { //如果 timeout 没有减到 0(即 Echo 信号在超时之前成功从高电平变回低电平)
D5 = 0; D6 = 1; // 蓝灯亮:距离大于小于10cm
} else {
D5 = 1; D6 = 0; // 黄灯亮:距离大于10cm
}
} else {
D5 = 1; D6 = 1; // 超时错误:双灯亮
}
Delay50ms(); // 测量间隔,避免频繁触发 手册规定两次间隔至少60ms(哎我这边写50也无所谓的)
}
}
当然我这个是优化过了的代码,因为之前的代码不稳定,容易实现不了功能你们可以拿去试试水
旧代码
这个代码有几点 需要重要解释的就是计算
首先时间的计算,本质就是计算echo的高电平到低电平的时间
那么我们定时器的TH0 和TL0 是发挥作用的,因为他们记录了次数,每次是1.085us,因为晶振的频率是11.059Mhz,我们定时器的模式又是16位,所以我们又要知道TH0和TL0是8位寄存器,高八位给TH0,低八位给TL0,记录的都是次数,我们将低八位让给TL0 其实就是这个效果啦
10101011 要变成1010101100000000(这个是一个二进制格式),那么我们该怎么办呢其实就是用到了这个方法
二进制左移一位相当于x2的一次方 左移8位相当于左移2的8次方
你看这个图就非常明显了,DEC是十进制这个数为65535是2的16次方,也就是16位2进制能有多少种搭配个数,那我们这个 前面8位数TH0的位置 后面8位数TL0的位置,所以我们可以根据这个信息来获取次数,我们通过二进制的数据来转换成10进制的次数,那么这个次数就可以与每次1.085us进行相乘得出总的时间
还有一个要注意的是距离的计算,有个公式叫做距离=速度 x 时间 但是由于我们这个超声波的话是这样的,时间多付出一倍,所以距离要/2的,一来一回
声音的速度为340m/s
随后根据公式就可以算出距离了。
最后我们来一些Tips:
对于第一个timeout设置为10ms是为什么?????
10ms 就是一个“兼顾大家”的折中值,既不过短(避免误判),也不过长(避免卡死),属于经验性参数。它的合理性可以从这几个角度理解
1. “大家”是谁?
- 硬件层面:超声波模块(如 HC-SR04)的典型响应时间在 微秒级到几毫秒(例如,测距 1 米时,Echo 变高延迟约 5.8ms,但实际传感器内部电路响应可能更快)。
- 软件层面:嵌入式系统通常需要 快速失败(避免因硬件故障导致整个系统僵死)。
- 用户体验:10ms 对人类来说几乎无感(LED 报错时用户不会觉得“卡顿”)。
就是Trig高电平进去之后,我们这个就要进行判断了,因为:超声波模块(如 HC-SR04)的典型响应时间在 微秒级到几毫秒
所以
- 只要 Echo 仍然为 0(低电平)并且 timeout 自减后仍不为 0,就继续循环。
- 如果 Echo 变为 1(高电平)或者 timeout 减到 0,循环终止。
Echo 高电平的持续时间(从第一个有效回波触发变高,到最后一个回波处理完毕变低)直接对应超声波往返的时间,而这个时间可以用来计算距离
这段代码有点意思:
timeout = 65535;
while(Echo == 1 && --timeout);
TR0 = 0;
- 如果 Echo 正常变低(测距完成),循环退出。
- 如果 Echo 因硬件故障一直保持高电平,timeout 会递减至 0,强制退出循环(避免死等)。
4. 为什么 timeout 初始值设为 65535?
- 65535(0xFFFF)是 16 位无符号整数的最大值,确保超时时间足够长(约 71ms @11.095MHz 51单片机)。
- 覆盖最大测距:
- HC-SR04 最大测距约 5 米,对应 Echo 高电平时间 ≈ 29ms(580µs/cm × 500cm)。
- 设置 timeout = 65535 可确保即使测最远距离也不会误触发超时。
5米最大测距 = 硬件限制(Echo 最大 29ms) + 声波衰减。
3. 实例验证
场景1:正常测距(Echo 按预期变低)
- Echo 从 1 → 0(耗时 5ms),timeout 从 65535 减到 60000(未到 0)。
- 结果:timeout != 0 → 进入 if 分支,计算距离。
场景2:超时异常(Echo 保持高电平)
- Echo 始终为 1,timeout 从 65535 递减至 0(耗时约 65ms)。
- 结果:timeout == 0 → 进入 else 分支,双灯亮报错。
场景3:干扰导致 Echo 异常变低
- Echo 因干扰短暂变低,但 timeout 未减到 0(如剩余 10000)。
- 结果:timeout != 0 → 仍进入 if 分支,但计算的距离可能无效(需软件滤波处理)。
相关文章:

学习STC51单片机13(芯片为STC89C52RC)
我去,兄弟们我们今天来学习一个牛逼 的硬件,它叫超声波测距模块HC—SR04 硬件:HC—SR04 哎,想当初最想要玩的就是这个模块,科技感十足,那现在就让我们玩玩吧 超声波测距传感器 原理就是说需要给Trig 10u…...

Claude 4 系列 Opus 4 与 Sonnet 4正式发布:Claude 4新特性都有哪些?
随着 Claude 4 系列(Opus 4 与 Sonnet 4)的正式发布,Anthropic 把自家大模型从“会聊天”推进到“能当自主代理”──不仅推理更深、上下文更长,还内置代码执行、多模态理解、工具调用等一揽子全新能力;同时࿰…...
Swagger API 未授权访问漏洞【原理扫描】修复
一、背景 漏洞名称:Swagger API 未授权访问漏洞【原理扫描】 风险等级:中 详细描述: Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务,方便开发者快速了解和调试接口。但由于…...

深度“求索”:DeepSeek+Dify构建个人知识库
目录 前言 环境部署 安装Docker 安装Dify 配置Dify 部署知识库 创建应用 前言 在当今数字化信息爆炸的时代,数据隐私和个性化知识管理成为企业和个人关注的焦点。Dify,作为一款备受瞩目的开源 AI 应用开发平台,为用户提供了完整的私有…...

基于R语言的空间异质性数据分析技术
在自然和社会科学领域,存在大量与地理或空间相关的数据,这些数据通常具有显著的空间异质性。传统的统计学方法在处理这类数据时往往力不从心。基于R语言的一系列空间异质性数据分析方法,如地理加权回归(GWR)、地理加权…...
C++:动态刷新打印内容
目录 1.简介1.1 Display类原理简述 2.代码2.1 main.cpp:无注释版2.2 main.cpp:有注释版 3.编译运行 1.简介 本文介绍一个用于命令行动态覆盖输出的C实现(Display类); 效果说明: 普通输出会直接换行显示。…...

网络学习-TCP协议(七)
一、TCP协议 TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。 1、三次握手 客户端: 1、先发起连接,发送SYN置1,seqnum12345(随机值)----半连接…...

基于微信小程序的高校校园微活动管理系统设计与实现(源码+定制+开发)高校微信小程序校园活动发布与互动平台开发 面向大学生群体的校园活动移动平台设计与实现
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...
Python 项目中安装 OpenAI 库的详细指南
在 Windows 系统中指定版本安装 OpenAI 库的指南 在 Windows 系统中,尤其是使用 Python 3.7.8 时,安装 OpenAI 库可能会遇到一些问题。本文将为你提供一个简单易懂的解决方案,帮助你成功安装指定版本的 OpenAI 库。 一、问题背景 当你在 W…...

云计算与大数据进阶 | 27、存储系统如何突破容量天花板?可扩展架构的核心技术与实践—— 分布式、弹性扩展、高可用的底层逻辑(上)
数据中心里,存储系统是至关重要的组成部分。由于相关硬件组件与存储操作系统的多样性和复杂性,如何在保证存储稳定、安全、可靠的同时,实现灵活扩展和自服务,一直是困扰数据中心全面云化的难题。 简单来说,现在的难题…...
使用Gemini, LangChain, Gradio打造一个书籍推荐系统 (第二部分)
建立向量嵌入数据库 from langchain_community.document_loaders import TextLoader from langchain_text_splitters import CharacterTextSplitter from langchain.docstore.document import Document from langchain_chroma.vectorstores import Chromaimport vertexai from…...

IvorySQL-WASM:免安装的数据库探索之旅
简介 为了降低社区用户的使用门槛,提升使用体验,IvorySQL 社区特别推出了 IvorySQL-WASM 项目,帮助用户快速在线 Demo。 IvorySQL-WASM 基于开源的 Postgres-WASM 框架开发。它允许用户直接在网页浏览器中体验 IvorySQL,无需本地…...

飞牛fnNAS远程映射盘符
目录 一、NAS、PC端配置Zerotier 二、使用网上邻居 三、使用WebDAV 1.开启WebDAV 2.PC上安装RaiDrive并设置 如果能将NAS作为本机一个盘符来使用,一定会令我非常方便。如果是本地,可以很方便实现。 将飞牛NAS映射为本地盘符,常用两种方式,一种是网上邻居,另一种是We…...

Java设计模式:探索编程背后的哲学
设计模式是软件开发中的一种常见方法,它为常见问题提供了解决方案。在Java世界中,设计模式的应用尤为广泛。本文将深入探讨Java设计模式的起源、分类和实际应用,帮助读者更好地理解和应用这些模式。设计模式不仅是编程的技术,更是…...
会话管理有哪些
使用服务器或者框架的会话管理控制。应用程序应当只识别有效的会话标识符。 会话标识符必须总是在一个可信系统(比如:服务器)上创建。 会话管理控制应当使用通过审查的算法以保证足够的随机会话标识符。 为包含已验证的会…...
《C++20新特性全解析:模块、协程与概念(Concepts)》
引言:C20——现代C的里程碑 C20是继C11之后最具革命性的版本,它通过模块(Modules)、协程(Coroutines)和概念(Concepts)三大核心特性,彻底改变了C的代码组织方式、并发模…...

Docker部署OpenSearch集群
OpenSearch 简介 OpenSearch 是一款开源的搜索与分析引擎,最初由亚马逊 AWS 开发,于 2021 年 9 月将其移交至 Linux 基金会旗下的 OpenSearch 软件基金会,此后实现了社区主导的治理模式。其具有高性能、可扩展性强、兼容性强等优点ÿ…...
三宽用到的网络类型
用家宽、企宽和专线运行P2P的网络类型本质要求一致,但具体配置和优化方向因宽带类型而异。以下是关键差异与共性分析: 一、核心网络类型要求(三者的共性) 公网IP 必要性:均需公网IP(非内网IP)以…...

【AS32X601驱动系列教程】PLIC_中断应用详解
平台中断控制器(Platform Level Interrupt Controller,PLIC)是国科安芯AS32系列MCU芯片的中断控制器,主要对中断源进行采样,优先级仲裁和分发。各外设中断统一连到PLIC,PLIC统一管理并输出中断请求到内核。…...
单目视觉测量及双目视觉测量
一、单目视觉测量 1.1 原理部分讲解 单目视觉系统通过采集图像,将图像转换为二维数据,然后对采集的图像进行模式识别,通过图像匹配算法识别行驶过程中的车辆、行人、交通标志等,最后依据目标物体的运动模式和定位…...

python学习打卡day34
DAY 34 GPU训练及类的call方法 知识点回归: CPU性能的查看:看架构代际、核心数、线程数GPU性能的查看:看显存、看级别、看架构代际GPU训练的方法:数据和模型移动到GPU device上类的call方法:为什么定义前向传播时可以直…...
掩码与网关是什么?
1. 子网掩码(Subnet Mask) 作用:划分“小区”范围 想象你住在一个小区(子网)里: 小区门牌号 IP地址(如 192.168.1.10) 小区边界 子网掩码(如 255.255.255.0…...

leetcode-快慢指针系列
开胃小菜 141. 环形链表 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链…...

JAVA05基本数据类型和包装类的转换,转换成其他数据类型,包装类与字符串的转换+学生类的定义实例
1.基本数据类型和包装类的转换 下面是一个自动手动的例题 2.将包装类转换成其他类型 3. 将数据类型转换成字符串 将字符串转换成数据类型 以下是一个例题 学生类的例题...

Python打卡训练营学习记录Day34
知识点回归: CPU性能的查看:看架构代际、核心数、线程数 GPU性能的查看:看显存、看级别、看架构代际 GPU训练的方法:数据和模型移动到GPU device上 类的call方法:为什么定义前向传播时可以直接写作self.fc1(x) CPU性…...

动手学习深度学习V1.1 chapter2 (2.1-2.2)
chapter2:深度学习基础 区分问题:回归问题还是分类问题? 输出结果是不明确的连续值的时候就是回归问题,比如房价预测,销售额预测等。 输出结果是明确几个离散值的时候就是分类问题,比如字符识别…...

数据结构(6)线性表-队列
一、队列的概述 队列也是一种特殊的线性表,只允许在一段插入数据,另一端删除数据。插入操作的一端称为队尾,删除操作的一端称为队头。 如图: 二、队列相关操作 1.队列结构体的声明 类似于栈,他肯定也得借助于数组或…...
NumPy 2.x 完全指南【十七】转置操作
文章目录 1. 什么是转置2. 转置操作2.1 transpose2.2 ndarray.T2.3 moveaxis2.4 rollaxis2.5 permute_dims2.6 swapaxes2.7 matrix_transpose 1. 什么是转置 在线性代数中,矩阵转置是指将矩阵的行和列进行互换,即原矩阵的第 i i i 行、第 j j j 列元素…...

【数据架构04】数据湖架构篇
✅ 10张高质量数据治理架构图 无论你是数据架构师、治理专家,还是数字化转型负责人,这份资料库都能为你提供体系化参考,高效解决“架构设计难、流程不清、平台搭建慢”的痛点! 🌟限时推荐,速速收藏&#…...
使用OpenSSL生成根证书并自签署证书
生成根CA的私钥和证书 # 生成根 CA 的私钥 [rootdeveloper ssl]# openssl genrsa -out rootCA.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ... ............................................................ e is 65537 (0x010001)# 使用私钥生…...