当前位置: 首页 > news >正文

【Protues仿真】基于AT89C52单片机的超声波测距

目录

1 HCSR04超声波测距传感器

1.1 基本参数

1.2 引脚说明

1.3 工作原理(时序图)

2 基于AT89C52单片机的超声波测距电路原理图

2.1 硬件连接说明

2.2 工作原理

3 基于AT89C52单片机的超声波测距控制程序

3.1.1 初始化设置

3.1.2 超声波测距原理

3.1.3 显示功能

3.1.4 注意事项

3.1.6 实现程序

3.1.7 _nop_()函数


摘要:

本文介绍基于AT89C52单片机的HC-SR04超声波测距系统实现方案。HC-SR04模块工作电压5V,测量范围2-400cm,精度±3mm,通过40kHz超声波实现测距。系统硬件连接包括单片机与传感器的Trig、Echo引脚对接,以及LCD显示模块。软件采用定时器测量回波高电平时间,按距离=时间×0.017cm/μs公式计算距离值,并通过LCD实时显示。程序实现包含初始化、超声波触发、时间测量和显示功能,测量周期建议大于60ms。该系统具有结构简单、成本低的特点,适合短距离测距应用,若需提高精度可增加温度补偿算法。

1 HCSR04超声波测距传感器

HC-SR04 是一款非常经典的低成本超声波测距模块,通过发射超声波并接收回波来测量前方障碍物的距离。

1.1 基本参数

参数

数值/说明

工作电压

DC 5V

工作电流

< 15mA

测距范围

2cm ~ 400cm(理论)

测距精度

±3mm(典型)

工作频率

40kHz

触发信号

10μs 高电平脉冲

回波信号

高电平持续时间表示距离

测量角度

~15° 锥形波束

尺寸

约 45 × 20 × 15 mm

1.2 引脚说明

引脚

名称

功能说明

VCC

电源

接 5V

GND

接地

Trig

触发

输入触发信号

Echo

回波

输出回波信号(5V)

注意:Echo 引脚输出的是 5V 信号,如果接 3.3V 单片机(如 ESP8266/ESP32),建议加电阻分压或电平转换器,避免烧坏 GPIO。

1.3 工作原理(时序图)

1 向Trig 引脚发送一个 ≥10μs 的高电平脉冲;

2 模块自动发射 8 个 40kHz 超声波脉冲;

3 Echo 引脚输出高电平,持续时间与超声波往返时间成正比;

4 距离计算公式:

距离(cm)=(Echo高电平时间/2)*声音传播速度

2 基于AT89C52单片机的超声波测距电路原理图

功能:AT89C52控制HC-SR04超声波传感器和LCD显示

2.1 硬件连接说明

HC-SR04 VCC → 5V

HC-SR04 GND → GND

HC-SR04 Trig → P2.0

HC-SR04 Echo → P2.1

LCD数据线 → P0口

LCD RS → P2.2

LCD RW → P2.3

LCD EN → P2.4

2.2 工作原理

首先,给Trig引脚一个至少10us的高电平脉冲,然后模块会自动发送8个40kHz的超声波脉冲,并检测回波。

当检测到回波时,Echo引脚会输出高电平,高电平的持续时间就是超声波从发射到返回的时间。

距离 = (高电平时间 * 声速(340m/s)) / 2

注意:由于声速随温度变化,但这里我们忽略温度补偿,使用340m/s。

3 基于AT89C52单片机的超声波测距控制程序

如上图所示,示波器中黄色线表示Trig引脚信号,用于产生至少10us的高电平脉冲。蓝色线表示Echo引脚会输出高电平,高电平的持续时间与测量距对应。

    1. 程序功能说明

3.1.1 初始化设置

配置LCD显示

初始化定时器0用于测量时间间隔

3.1.2 超声波测距原理

向TRIG引脚发送至少10μs的高电平脉冲

超声波模块自动发送8个40kHz的脉冲

检测ECHO引脚的高电平持续时间

根据时间计算距离:距离 = (时间 × 声速) / 2

3.1.3 显示功能

在LCD上显示测量得到的距离值

3.1.4 注意事项

测量周期最好大于60ms,以防止发射信号对回响信号的影响

实际应用中可能需要添加温度补偿以提高精度

如果测量环境复杂,可能需要添加滤波算法

3.1.6 实现程序

//库函数与位定义
#include <reg52.h>
#include <intrins.h>#define uint unsigned int
#define uchar unsigned char// LCD引脚定义
sbit LCD_RS = P2^2;
sbit LCD_RW = P2^3;
sbit LCD_EN = P2^4;// HC-SR04引脚定义
sbit TRIG = P2^0;
sbit ECHO = P2^1;// 全局变量
uint distance = 0;
uint time = 0;// LCD延时函数
void lcd_delay(uint ms) {uint i, j;for(i = 0; i < ms; i++)for(j = 0; j < 120; j++);
}// LCD写命令函数
void lcd_write_cmd(uchar cmd) {LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;P0 = cmd;LCD_EN = 1;lcd_delay(1);LCD_EN = 0;lcd_delay(1);
}// LCD写数据函数
void lcd_write_data(uchar dat) {LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;P0 = dat;LCD_EN = 1;lcd_delay(1);LCD_EN = 0;lcd_delay(1);
}// LCD初始化函数
void lcd_init() {lcd_write_cmd(0x38); // 16x2显示,5x7点阵,8位数据接口lcd_write_cmd(0x0C); // 显示开,光标关,闪烁关lcd_write_cmd(0x06); // 写入新数据后光标右移lcd_write_cmd(0x01); // 清屏lcd_delay(2);
}// 显示字符串函数
void lcd_display_string(uchar *str) {while(*str != '\0') {lcd_write_data(*str++);}
}// 显示数字函数
void lcd_display_number(uint num) {uchar i;uchar digits[4];if(num > 999) {digits[0] = num / 1000 + '0';digits[1] = (num % 1000) / 100 + '0';digits[2] = (num % 100) / 10 + '0';digits[3] = num % 10 + '0';for(i = 0; i < 4; i++) {lcd_write_data(digits[i]);}}else if(num > 99) {digits[0] = num / 100 + '0';digits[1] = (num % 100) / 10 + '0';digits[2] = num % 10 + '0';for(i = 0; i < 3; i++) {lcd_write_data(digits[i]);}}else if(num > 9) {digits[0] = num / 10 + '0';digits[1] = num % 10 + '0';for(i = 0; i < 2; i++) {lcd_write_data(digits[i]);}}else {lcd_write_data(num + '0');}
}// 定时器0初始化
void timer0_init() {TMOD = 0x01; // 定时器0工作方式1TH0 = 0;TL0 = 0;ET0 = 1; // 允许定时器0中断EA = 1;  // 开启总中断
}// 超声波测距函数
uint ultrasonic_measure() {TRIG = 1;_nop_();//空格起延时作用_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();TRIG = 0;while(!ECHO); // 等待ECHO变高TR0 = 1; // 启动定时器0while(ECHO); // 等待ECHO变低TR0 = 0; // 停止定时器0time = TH0 * 256 + TL0;//计时TH0 = 0;TL0 = 0;// 计算距离 (cm) = (时间 * 声速) / 2// 声速 = 340m/s = 0.034cm/μs// 定时器每计数1次为1μsdistance = time * 0.017; // 简化计算: 0.034/2 = 0.017return distance;
}// 主函数
void main() {lcd_init();timer0_init();lcd_write_cmd(0x80); // 设置LCD显示位置lcd_display_string("Distance:");while(1) {distance = ultrasonic_measure();lcd_write_cmd(0x89); // 设置显示位置lcd_display_number(distance);lcd_display_string("cm   ");// 延时一段时间再进行下一次测量lcd_delay(5);}
}// 定时器0中断服务函数
void timer0_isr() interrupt 1 {// 定时器溢出处理TH0 = 0;TL0 = 0;
}

3.1.7 _nop_()函数

_nop_()是8051单片机中的一个内联函数,它产生一个NOP(空操作)指令,消耗一个机器周期的时间。在12MHz晶振的系统中,一个NOP指令执行时间为1μs。

http://www.dtcms.com/a/346502.html

相关文章:

  • 关于微服务下的不同服务之间配置不能通用的问题
  • `strdup` 字符串复制函数
  • 自控笔记 控制框图简化+梅森公式复习
  • Spring Boot 实时广播消息
  • 分布式蜜罐系统的部署安装
  • TypeScript 类中提供的 public、private 和 protected 修饰符的作用理解
  • C++程序嵌入python脚本调试
  • 搜索算法在实际场景中的应用
  • 系统思考:突破复杂困境
  • Python 十进制转二进制
  • 使用隧道(Tunnel)连接PostgreSQL数据库(解决防火墙问题)(含Java实现代码)
  • GIS实现综合应急管理平台及应用
  • Linux系统 --- 指令
  • CMake link_directories()详细介绍与使用指南
  • 算法题(188):团伙
  • 【0基础PS】蒙版与剪贴蒙版详解
  • `strchr` 字符串查找函数
  • 信息结构统一论:物理世界与人类感知、认知及符号系统的桥梁
  • 嵌入式-时钟树和时钟树编程-Day20
  • 大宗商品、股票指数及ETF期权五档买卖分时tick级历史交易数据深度解析
  • zynq的vitis工程烧录到Winbond(华邦)型号W25Q256JVEQ的QSPI FLAHS
  • 2025最新版mgg格式转MP3,mflac转mp3,mgg格式如何转mp3?
  • FastText 词向量全景指南(没那么全)
  • 【论文】Zotero文献管理
  • [e3nn] docs | 不可约表示(Irreps)
  • AI 大模型 “进化史”:从参数竞赛到场景落地,技术突破藏着哪些逻辑?
  • C#_异步编程范式
  • kvcache比赛记录
  • JavaScript Object 操作方法及 API
  • GEO优化专家孟庆涛发布:《GEO内容优化的四大黄金标准》