基于 LCD1602 的超声波测距仪设计与实现:从原理到应用
具体材料可在主页资源里下载
超声波测距技术作为非接触式测量的重要手段,在工业检测、智能家居、机器人避障等领域有着广泛应用。本文将详细介绍一款基于 STC89C51 单片机与 LCD1602 显示屏的超声波测距系统,从硬件架构到软件实现,完整呈现一个兼具实用性与学习价值的嵌入式系统项目。
项目背景与功能概述
在工业自动化和智能设备领域,精准的距离测量是许多系统的核心需求。传统的接触式测量方法存在磨损、效率低等问题,而超声波测距凭借非接触、响应快、成本低的优势成为理想选择。本项目设计的测距仪具备以下核心功能:
- 实时测距:利用 HC-SR04 模块实现 2cm-400cm 范围的距离测量,精度控制在 1cm 以内
- 信息显示:通过 LCD1602 实时显示测量距离,支持自定义报警阈值显示
- 智能报警:当距离小于设定阈值(默认 5cm)时触发声光报警
- 人机交互:通过按键实现报警阈值的灵活调整(1cm-50cm)
系统设计架构与工作原理
模块化设计思想
整个系统采用模块化架构,将复杂功能分解为独立可维护的单元,主要包括:
- 主控模块:STC89C51RD + 单片机作为核心控制器
- 测距模块:HC-SR04 超声波传感器实现距离测量
- 显示模块:LCD1602 液晶显示屏呈现测量结果
- 报警模块:蜂鸣器与红绿 LED 实现声光提示
- 输入模块:独立按键支持阈值调整
超声波测距原理
HC-SR04 的工作基于超声波的传播特性,其核心公式为:
距离(cm) = 回波时间(μs) × 0.034 / 2
- 单片机向 Trig 引脚发送 10μs 高电平触发超声波发射
- 传感器自动发射 8 个 40kHz 超声波脉冲并等待回波
- Echo 引脚高电平持续时间即为声波往返时间
- 利用定时器测量时间差,结合声速计算实际距离
硬件电路设计与实现
核心硬件选型
模块 | 型号 | 功能描述 |
---|---|---|
主控芯片 | STC89C51RD+ | 8 位单片机,8KB Flash,512B RAM |
测距模块 | HC-SR04 | 超声波传感器,测量范围 2-400cm |
显示模块 | LCD1602 | 16×2 字符液晶,支持 ASCII 字符显示 |
报警模块 | 有源蜂鸣器 + LED | 声音报警与状态指示 |
按键模块 | 独立按键 | 阈值加减与确认功能 |
关键电路设计
主控模块电路
STC89C51RD + 的最小系统包括:
- 12MHz 晶振电路提供时钟信号
- 上电复位与手动复位结合的复位电路
- P0 口作为数据总线连接 LCD1602
- P1/P2/P3 口用于外设控制
超声波模块接口
HC-SR04 与单片机的连接:
- Trig 引脚 → P1.0(触发信号输出)
- Echo 引脚 → P1.1(回波信号输入)
- 采用上拉电阻提高抗干扰能力
LCD1602 驱动电路
LCD1602 的控制接口:
- RS → P2.6(寄存器选择)
- RW → P2.5(读写控制)
- E → P2.7(使能信号)
- D0-D7 → P0 口(8 位数据传输)
硬件连接方案
模块 | 单片机引脚 | 功能说明 |
---|---|---|
HC-SR04 | Trig→P1.0 | 超声波触发信号 |
Echo→P1.1 | 回波接收信号 | |
LCD1602 | RS→P2.6 | 寄存器选择 |
RW→P2.5 | 读写控制 | |
EN→P2.7 | 使能端 | |
D0-D7→P0 | 数据端口 | |
蜂鸣器 | P2.1 | 报警声音输出 |
绿灯 | P2.0 | 安全距离指示 |
红灯 | P2.2 | 危险距离指示 |
加键 | P3.0 | 阈值 + 1cm |
减键 | P3.1 | 阈值 - 1cm |
确认键 | P3.2 | 恢复显示 |
软件设计与核心代码
软件开发环境
- 集成开发环境:Keil C51
- 下载工具:STC-ISP
- 编程语言:C 语言
关键功能实现
主程序流程
主程序作为系统的控制核心,负责各模块的协调工作:
void main(void)
{Timer0_Init(); // 初始化定时器0LCD1602_Init(); // 初始化LCDLCD1602_DisString(0,5,"LCD1602"); // 显示欢迎信息GreenLED = 0; // 初始化绿灯亮Buzzer = 1; // 蜂鸣器关闭RedLED = 1; // 红灯关闭while(1) // 主循环{ Key_Scan(); // 扫描按键Start_HCSR04(); // 触发超声波测距LCD1602_DisDistance(); // 显示距离结果delay_xms(100); // 延时100ms}
}
超声波测距实现
距离测量的核心在于精确计时:
void Start_HCSR04(void)
{Trig=1; // 发送10us高电平触发信号delay_xus(20);Trig=0;while(!Echo); // 等待回波信号变高TR0=1; // 启动定时器计数while(Echo); // 等待回波信号变低TR0=0; // 停止定时器
}float Count(void)
{uint time = TH0 * 256 + TL0; // 计算总定时时间TH0 = TL0 = 0; // 定时器清零return time*0.017f; // 距离=时间/58(声速340m/s换算)
}
LCD1602 显示控制
实现字符与数字的精准显示:
void LCD1602_DisData(uchar hang,uchar lie,float dat)
{uchar int_part = (uchar)dat; // 整数部分uchar dec_part = (uchar)((dat - int_part) * 10); // 小数部分LCD1602_DisChar(hang,lie,int_part / 10 + '0');LCD1602_DisChar(hang,lie+1,int_part % 10 + '0');LCD1602_DisChar(hang,lie+2,'.');LCD1602_DisChar(hang,lie+3,dec_part + '0');
}
按键处理与报警功能
实现人机交互与安全提示:
void Key_Scan(void)
{if(Key_Plus == 0) // 加键处理{ ultrasound_enabled = 0; //暂停超声波delay_xms(10); // 消抖if(Key_Plus == 0 && key_flag == 0){key_flag = 1; if(threshold_cm < 50) threshold_cm++; // 显示新阈值LCD1602_DisString(0,2,"TH:");LCD1602_DisData(0,5,threshold_cm);LCD1602_DisString(0,9,"cm ");}}// 减键与确认键处理逻辑类似...
}void Alarm_5Times() {uchar i;for (i = 0; i < 5; i++) {Buzzer = 0; // 蜂鸣器响RedLED = 0; // 红灯亮delay_xms(200);Buzzer = 1; // 蜂鸣器停RedLED = 1; // 红灯灭delay_xms(200);}
}
总代码
#include<reg52.h>
#include<intrins.h> //包含_nop_()函数#define uint unsigned int // 类型重定义
#define uchar unsigned char
#define LCD1602_Port P0 // LCD数据端口/* 硬件引脚定义 */sbit GreenLED = P2^0; // 绿灯(正常状态指示)
sbit Buzzer = P2^1; // 蜂鸣器(报警用)
sbit RedLED = P2^2; // 红灯(报警指示)
sbit LCD1602_RS=P2^6; // LCD寄存器选择
sbit LCD1602_RW=P2^5; // LCD读写控制
sbit LCD1602_EN=P2^7; // LCD使能端
sbit Key_Plus = P3^0; // 阈值增加按键
sbit Key_Minus = P3^1; // 阈值减少按键
sbit Key_OK=P3^2; // 确认/返回按键//超声波模块HC-SR04引脚定义
sbit Trig=P1^0;
sbit Echo=P1^1;/* 全局变量 */
bit flag;
bit key_flag = 0; // 按键防抖标志
uint key_delay = 0; // 按键延时计数器
unsigned int threshold_cm = 5; // 默认阈值5cm
bit ultrasound_enabled = 1; // 全局启用标志/* 函数声明 */
void delay_xus(uint t); //延时xus
void delay_xms(uint t); //延时xmsvoid Timer0_Init(); //定时器0初始化void LCD1602_BusyCheck(void); //LCD1602判忙函数void LCD1602_WriteCmd(uchar cmd); //LCD1602写指令
void LCD1602_WriteData(uchar dat); //LCD1602写数据void LCD1602_Init(void); //LCD1602初始化void LCD1602_DisChar(uchar hang,uchar lie,uchar ch); //显示字符
void LCD1602_DisString(uchar hang,uchar lie,uchar *str); //显示字符串
void LCD1602_DisData(uchar hang,uchar lie,float dat); //显示数据void Start_HCSR04(void); //启动超声波模块
float Count(void); //计算距离值void LCD1602_DisDistance(void); //把距离显示在LCD1602上
void Alarm_5Times(); //蜂鸣器报警
void Key_Scan(); // 按键扫描/* 主函数 */
void main(void)
{ uint s;Timer0_Init(); // 初始化定时器0LCD1602_Init(); // 初始化LCDLCD1602_DisString(0,5,"LCD1602"); // 显示欢迎信息GreenLED = 0; // 初始化绿灯亮Buzzer = 1; // 蜂鸣器关闭RedLED = 1; // 红灯关闭while(1) // 主循环{ Key_Scan(); // 扫描按键Start_HCSR04(); // 触发超声波测距LCD1602_DisDistance(); // 显示距离结果delay_xms(100); // 延时100ms(控制测量频率)}
}/* 微秒级延时(基于_nop_指令)*/
void delay_xus(uint t) // 微秒级延时(基于_nop_指令)
{uint i;for(i=t;i>0;i--)_nop_();
}/* 毫秒级延时(软件循环)*/
void delay_xms(uint t)
{uint i,j;for(i=t;i>0;i--)for(j=123;j>0;j--);
}/* 定时器0初始化(模式1,16位定时器)*/
void Timer0_Init(void)
{TMOD=0x01; // 设置定时器模式TH0=0; // 初值清零TL0=0;EA=1; // 开启总中断ET0=1; // 允许定时器0中断
}/* 定时器0中断服务函数 */
void Timer0() interrupt 1
{flag=1; // 设置溢出标志
}/* 启动超声波测距 */
void Start_HCSR04(void)
{Trig=1; // 发送10us高电平触发信号delay_xus(20);Trig=0;while(!Echo); // 等待回波信号变高TR0=1; // 启动定时器计数while(Echo); // 等待回波信号变低TR0=0; // 停止定时器
}/* LCD忙检测(检查BF标志位)*/
void LCD1602_BusyCheck()
{uchar LCD1602_Temp;LCD1602_Port=0xff;LCD1602_RS=0;LCD1602_RW=1;while(1){ LCD1602_EN=1; // 使能LCD1602_Temp=LCD1602_Port; // 读取状态LCD1602_EN=0;if((LCD1602_Temp & 0x80)==0)break; // 检查忙标志}
}/* LCD写指令 */
void LCD1602_WriteCmd(uchar cmd) // 写指令到LCD1602
{LCD1602_BusyCheck(); // 等待LCD空闲LCD1602_EN=0;LCD1602_RS=0; // 命令模式LCD1602_RW=0; // 写模式LCD1602_Port=cmd; // 发送命令delay_xms(1); LCD1602_EN=1; // 使能脉冲delay_xms(1);LCD1602_EN=0;
}/* LCD写数据 */
void LCD1602_WriteData(uchar dat) // 写数据到LCD1602
{ LCD1602_BusyCheck();LCD1602_EN=0;LCD1602_RS=1; // 数据模式LCD1602_RW=0;LCD1602_Port=dat;delay_xms(1);LCD1602_EN=1;delay_xms(1);LCD1602_EN=0;
}/* LCD初始化序列 */
void LCD1602_Init()
{delay_xms(15); //延时15msLCD1602_WriteCmd(0x38);delay_xms(5); //延时5msLCD1602_WriteCmd(0x38);delay_xms(5); //延时5msLCD1602_WriteCmd(0x38);LCD1602_WriteCmd(0x08); //显示关闭LCD1602_WriteCmd(0x01); //显示清屏LCD1602_WriteCmd(0x06); //显示光标移动设置,光标右移LCD1602_WriteCmd(0x0C); //显示开及光标设置,光标关,闪烁关
}/* 在指定位置显示字符 */
void LCD1602_DisChar(uchar hang,uchar lie,uchar ch)//在指定位置显示字符hang:0-1,lie:0-15
{if(hang==0){ LCD1602_WriteCmd(0x80+lie);}if(hang==1){ LCD1602_WriteCmd(0xC0+lie);}LCD1602_WriteData(ch);
}/* 显示数字(1个小数点)*/
void LCD1602_DisData(uchar hang,uchar lie,float dat)
{uchar int_part = (uchar)dat; // 整数部分uchar dec_part = (uchar)((dat - int_part) * 10); // 小数部分(1位)LCD1602_DisChar(hang,lie,int_part / 10 + '0');LCD1602_DisChar(hang,lie+1,int_part % 10 + '0');LCD1602_DisChar(hang,lie+2,'.');LCD1602_DisChar(hang,lie+3,dec_part + '0');
}/* 显示字符串 */
void LCD1602_DisString(uchar hang,uchar lie,uchar *str)
{uchar a;if(hang==0)a=0x80; // 第一行起始地址if(hang==1)a=0xC0; // 第二行起始地址a=a+lie; // 计算实际地址LCD1602_WriteCmd(a);while(*str!='\0') // 遍历字符串{LCD1602_WriteData(*str);str++;}
}/* 计算距离值(单位:cm)*/
float Count(void)
{uint time = TH0 * 256 + TL0; // 计算总定时时间TH0 = TL0 = 0; // 定时器清零return time*0.017f; // 距离=时间/58(声速340m/s换算)
}/* 显示距离结果(带错误检测)*/
void LCD1602_DisDistance(void) // 显示距离结果(带错误检测)
{ float s;if(!ultrasound_enabled) return;s=Count(); // 获取距离值if(s<threshold_cm||s>50||flag==1) // 距离过近/过远/超时{flag=0;LCD1602_DisString(1,5," error ");GreenLED =1; // 绿灯灭Alarm_5Times(); // 触发报警}else {LCD1602_DisData(1,5,s); // 显示距离LCD1602_DisString(1,9,"cm");GreenLED = 0; // 绿灯亮Buzzer = 1; // 关闭蜂鸣器RedLED = 1; // 关闭红灯}
}/* 蜂鸣器报警(响5次)*/
void Alarm_5Times() {uchar i;for (i = 0; i < 5; i++) {Buzzer = 0; // 蜂鸣器响RedLED = 0; // 红灯亮delay_xms(200);Buzzer = 1; // 蜂鸣器停RedLED = 1; // 红灯灭delay_xms(200);}
}/* 按键扫描函数 */
void Key_Scan(void)
{if(Key_Plus == 0) // 加键处理{ ultrasound_enabled = 0; //暂停超声波delay_xms(10); // 消抖if(Key_Plus == 0 && key_flag == 0){key_flag = 1; // 防抖标志if(threshold_cm < 50) threshold_cm++; // 增加阈值// 显示新阈值LCD1602_DisString(0,2,"TH:");LCD1602_DisData(0,5,threshold_cm);LCD1602_DisString(0,9,"cm ");}}else if(Key_Minus == 0) // 减键处理(逻辑同上){ ultrasound_enabled = 0; //暂停超声波delay_xms(10); // 消抖if(Key_Minus == 0 && key_flag == 0){key_flag = 1;if(threshold_cm > 1) threshold_cm--;// 显示新阈值LCD1602_DisString(0,2,"TH:");LCD1602_DisData(0,5,threshold_cm);LCD1602_DisString(0,9,"cm ");}}else if(Key_OK == 0) // 确认键处理{ LCD1602_DisString(0,2," LCD1602"); // 恢复初始显示ultrasound_enabled = 1; //继续显示距离}else{key_flag = 0; // 按键释放}}
效果展示
实物连接图
系统调试与测试分析
硬件调试挑战
在硬件调试过程中遇到的主要问题:
- 超声波模块无响应:发现电源连接错误,重新确认供电电路
- LCD 显示乱码:检查引脚定义错误,对比标准电路重新配置
- 报警功能异常:函数调用位置错误导致报警持续,调整逻辑顺序
软件调试优化
软件调试中的关键优化点:
- 阈值显示问题:添加确认键实现显示模式切换
- 测量中断问题:引入
ultrasound_enabled
标志控制测距状态 - 精度优化:将数据类型改为浮点型,确保小数点后一位显示
测试结果分析
经过全面测试,系统性能如下:
- 测量范围:2cm-400cm(符合 HC-SR04 规格)
- 测量精度:全量程误差≤1cm(如图 13、14 所示)
- 响应时间:单次测量约 100ms
- 阈值调整:1cm-50cm 连续可调,实时生效
- 稳定性:持续运行 8 小时无异常
应用场景与扩展方向
实际应用场景
该超声波测距仪可应用于:
- 工业自动化:物料高度检测、生产线定位
- 智能家居:自动门感应、垃圾桶开盖控制
- 机器人技术:避障系统、地形感知
- 安防领域:入侵检测、距离警戒
功能扩展方向
未来可优化的方向:
- 精度提升:加入温度补偿算法(声速受温度影响)
- 显示增强:升级为 OLED 显示屏或彩色 LCD
- 通信接口:增加蓝牙 / WiFi 模块实现数据远程传输
- 多传感器融合:结合红外、视觉传感器提升测量可靠性
总结与技术价值
本项目通过 STC89C51 单片机与 HC-SR04 传感器的结合,实现了一个功能完整的超声波测距系统。从硬件电路设计到软件模块化编程,充分体现了嵌入式系统开发的全流程。项目的核心价值在于:
- 技术学习:涵盖单片机编程、传感器接口、显示控制等核心技术
- 工程实践:掌握从需求分析到系统调试的完整开发流程
- 应用价值:提供了可直接应用于多种场景的测距解决方案
超声波测距作为智能设备的 "眼睛",其技术原理和实现方法具有广泛的借鉴意义。通过本项目的实践,不仅加深了对嵌入式系统的理解,也为更复杂的智能设备开发奠定了基础。