超声波测距作为非接触式距离测量的经典方案,在工业自动化、智能家居、机器人导航等领域有着广泛应用。这次我们要用51单片机搭建一个完整的超声波测距系统,并通过Proteus仿真验证其可行性。这个项目特别适合电子专业学生和单片机爱好者作为入门实践,既能掌握硬件电路设计,又能学习超声波传感器的工作原理和编程技巧。
我曾在多个智能小车项目中应用过类似方案,实测在20cm-4m范围内误差可以控制在1%以内。相比红外测距,超声波受环境光干扰小;相比激光测距,成本又低得多,是性价比极高的距离检测方案。下面我就把完整的实现过程拆解给大家,包括硬件选型、电路设计、程序编写和仿真调试的全流程。
市面上常见的HC-SR04模块价格仅10元左右,测量范围2cm-4m,精度3mm,完全满足一般需求。其工作原理是:
注意:实际使用时建议在VCC和GND之间加0.1μF去耦电容,可有效减少电源干扰导致的误触发。
选用STC89C52RC芯片,主要考虑:
最小系统电路包含:
使用4位共阳数码管显示距离,通过74HC595串行驱动节省I/O口。电路连接方式:
c复制void Timer0_Init() {
TMOD |= 0x01; // 定时器0模式1
TH0 = 0; // 初值清零
TL0 = 0;
ET0 = 1; // 允许定时器0中断
EA = 1; // 开总中断
}
定时器用于测量回响信号高电平时间,选择模式1(16位定时器)可最大测量65.535ms,对应约11米距离(声速340m/s)。
c复制float GetDistance() {
Trig = 1; // 触发信号
Delay20us(); // 持续20μs
Trig = 0;
while(!Echo); // 等待回响信号
TR0 = 1; // 启动定时器
while(Echo); // 等待回响结束
TR0 = 0; // 停止定时器
time = (TH0<<8)|TL0; // 计算总时间
distance = time*0.017; // 距离(cm)=时间(us)*340/2/10000
TH0 = TL0 = 0; // 定时器清零
return distance;
}
关键点:声速在20℃时为343m/s,计算时要考虑超声波往返距离需除以2。温度变化时声速会改变,如需更高精度应加入温度补偿。
c复制void Display(float dis) {
unsigned char buf[4];
buf[0] = dis/1000; // 千位
buf[1] = (dis/100)%10; // 百位
buf[2] = (dis/10)%10; // 十位
buf[3] = (int)dis%10; // 个位
for(int i=0; i<4; i++) {
HC595_Send(seg[buf[i]] | (i<<4)); // 段码+位选
HC595_Latch();
Delay1ms();
}
}
添加元器件:
关键连接:
设置超声波模块参数:
虚拟示波器用法:
常见问题排查:
c复制for(int i=0; i<5; i++) {
sum += GetDistance();
Delay100ms();
}
distance = sum/5;
c复制float sound_speed = 331.4 + 0.6*temperature;
distance = time*sound_speed/2/10000;
软件滤波:
硬件改进:
可能原因及对策:
HC-SR04的2cm盲区是由物理特性决定的,如需更小距离:
超过4m时信号衰减严重,改进方案:
我在实际项目中发现,超声波模块朝向对测量影响很大。最佳做法是将传感器轴线与待测表面呈15-30度夹角,这样可以减少镜面反射造成的信号丢失。另外,毛绒表面(如窗帘)的吸声特性会导致最大测距缩短,这是物理限制,需要通过软件设置合理的超时阈值。