目录
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引脚会输出高电平,高电平的持续时间与测量距对应。
-
- 程序功能说明
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。