历史上的今天
今天是:2026年01月05日(星期一)
2023年01月05日 | 单片机设计 超声波测距仿真(AT89C51)
2023-01-05 来源:zhihu
一、电路设计
由于超声波指向性强,能量消耗缓慢,在介质中传播的距离较远,因而超声波经常用于距离的测量,利用超声波检测往往比较迅速、方便、计算简单、易于做到实时控制,并且在测量精度方面能达到工业实用的要求,因此得到了广泛的应用。如图5即为HC-SR04超声波测距模块

1、基本工作原理:
如图6为超声波测距传感器HC-SR04模块,VCC 接 5V 电源,GND 为地 线,TRIG 为触发控制信号输入,ECHO为回响信号输出。超声波在传播时碰到障碍物即返回,HC-SR04模块收到回波信号后Echo口输出一个高电平。
2.、HC-SR04电气参数:

HC-SR04超声波测距模块可提供2cm至400cm的非接触式距离感测功能,测距精度可达3mm;模块自身包括超声波发射器、接收器与控制电路。

3、操作步骤为:
HC-SR04的Trig端口和Echo端口接入单片机的I/O口接,初始化时将trig和echo端口都置低,首先向给 trig 端发送至少10 us的高电平脉冲(模块自动向外发送8个40K的方波),如图6,然后等待,捕捉 echo 端输出一个高电平,当单片机检测到上升沿(或高电平)的同时,打开定时器开始计时,再次等待,直到单片机检测到echo变成下降沿(或低电平)时,结束计数,读出计时器的时间,计数器的计数值乘以单片机计数周期就是超声波从发射到接收的往返时间,即按照
*测试距离(S)=高电平时间(t)声速(v=340m/s)/2
就可以算出超声波到障碍物的距离。
二、运行结果

三、部分代码
#include "task.h"
//全局变量定义
//段码表,适用于共阴数码管
unsigned int code duan_ma[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0~9
0x77,0x7c,0x39,0x5e,0x79,0x71}; //A~F
unsigned int dis_buf[4]; //显示缓存
unsigned int S = 0; //距离缓存变量
unsigned long time = 0; //时间缓存变量
unsigned int S_H = 400, S_L = 10; //S_H:报警上限值,默认400cm,S_L:报警下限值,默认10cm
/* 延时,单位:ms */
void delayms(unsigned int ms)
{
unsigned char a,b,c;
while(--ms)
{
for(c=1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
}
/* 计算测距 */
void count(void)
{
start_ranging(); //启动一次超声波
while(!Echo); //等待超声波模块输出IO拉高
TR0 = 1; //开启定时器计时
while(Echo); //等待超声波模块输出IO拉低
TR0 = 0; //关闭定时器计时
/* 计算距离 */
time = TH0 * 256 + TL0; //得到的时间,专业写法应该是这样:time = TH0 << 8 | TL0
TH0 = 0; //定时计数器清零
TL0 = 0;
S = (time * 1.7) / 100; //算出来是M
}
/* 显示距离 */
void dis_distance(void)
{
dis_buf[3] = 0x00;
dis_buf[2] = duan_ma[S / 100 %10]; //取出百位数,并在数码管的第3位显示,从右往左数
dis_buf[1] = duan_ma[S / 10 %10]; //取出十位数,并在数码管的第2位显示,从右往左数
dis_buf[0] = duan_ma[S % 10]; //取出个位数,并在数码管的第1位显示,从右往左数
}
/* 设置报警功能 */
void key_fuction(void)
{
unsigned char mode_flag = 1; //模式切换标记位,1:设置上限值,2:设置下限值,3:退出
while(1)
{
if(key_scan() == 1)
{
BEEP = 0; //按键提示音
delayms(50);
BEEP = 1;
delayms(1000);
++mode_flag;
if(mode_flag >= 3) //如果满3了,则退出
break;
}
if(key_scan() == 2) //如果加键按下
{
BEEP = 0; //按键提示音
delayms(50);
BEEP = 1;
delayms(1000);
if(mode_flag == 1) //设置上限值
{
++S_H;
if(S_H > 400)
S_H = 2;
}
if(mode_flag == 2) //设置下限值
{
++S_L;
if(S_L > 400)
S_L = 2;
}
}
if(key_scan() == 3) //如果减键按下
{
BEEP = 0; //按键提示音
delayms(50);
BEEP = 1;
delayms(1000);
if(mode_flag == 1) //设置上限值
{
--S_H;
if(S_H < 2)
S_H = 400;
}
if(mode_flag == 2) //设置下限值
{
--S_L;
if(S_L < 2)
S_L = 400;
}
}
/* 报警设置显示 */
if(mode_flag == 1) //显示设置上限值内容
{
dis_buf[3] = 0x76; //第4位数码管显示字母 H
dis_buf[2] = duan_ma[S_H / 100 % 10]; //显示百位数
dis_buf[1] = duan_ma[S_H / 10 % 10]; //显示十位数
dis_buf[0] = duan_ma[S_H % 10]; //显示个位数
}
if(mode_flag == 2) //显示设置下限值内容
{
dis_buf[3] = 0x38; //第4位数码管显示字母 L
dis_buf[2] = duan_ma[S_L / 100 % 10]; //显示百位数
dis_buf[1] = duan_ma[S_L / 10 % 10]; //显示十位数
dis_buf[0] = duan_ma[S_L % 10]; //显示个位数
}
}
}
史海拾趣
|
大家好,上传一个单片机开发板的原理图,如果有错误请大家修改后再上传。 希望和大家共同研究,后面我将会上传有关LED电子显示屏的PCB图。希望大家多多指导! [ 本帖最后由 caihong0217 于 2008-11-1 15:07 编辑 ]… 查看全部问答> |
|
用单片机一个口接一个光耦TLP521,然后光耦接三极管,三极管驱动继电器,继电器和光耦的右端都是一个电源,单片机和光耦的左端是一个电源。 问题1:这样的设计对提高系统稳定性有效果么 问题2:其中光耦是不是多此一举,可以去掉呢 这里ZC0是接 ...… 查看全部问答> |
|
[原创].使用Nios II 9.1 SP1 SBTE的Flash Programmer的几点注意事项.[Nios II] 自从Altera公司推出Nios II 9.1 Software Build Tools for Eclipse(简称Nios II 9.1 SBTE),许多新特性的引入,令众多使用者感到欣慰,尤其是在编译的速度上。但是Nios II 9.1 SBTE并不完美,譬如说无法调用用户自定义外设的HAL文件、无 ...… 查看全部问答> |
|
module decoder2(c,y,clk);output[6:0] c; //c 为输出码字,c[6]为高次项input[6:0] y; //y 为接收码字,y[6]为高次项input clk;reg[6:0] c,c_buf,buffer;reg temp;reg s0,s1,s2; //伴随式电路寄存器reg e; //错误检测输出信号integer i;always @(p ...… 查看全部问答> |
|
我的CAMERA中断怎么使能了就不能禁止了?我把使能位清掉了还是关不了中断,虽然关不了,但不能进行实时捕捉了,什么原因? 我的CAMERA中断怎么使能了就不能禁止了?我把使能位清掉了还是关不了中断,虽然关不了,但不能进行实时捕捉了,什么原因?… 查看全部问答> |
|
各位大侠: 我是一位刚接触VxWorks不久的菜鸟,想要在VxWorks下实现ftp服务器功能,仅希望能把一些文件放在指定的目录里供其它机器下载使用,现下载了两个文件ftpdlib.c文件和ftpdlib.h文件,但不太知道怎么使用,我试着自己建了个 ...… 查看全部问答> |
|
WINCE在开机后自动弹出来一个WIFI无线配置的窗口,但是这个窗口比LCD高了,有没有好办法把这个窗口缩小一点呀!如果单改代码来缩小窗口,那窗口上的控件也要调整,比较麻烦,改资源文件又好像只有英文版的才有效,哪位前辈能给小弟一点建议呀?!… 查看全部问答> |
|
在浏览版块时候,看到了版主驿站,细细品读了一下soso姐写的东西,才知道还有这么多的东西需要注意学习,对自己的这则也有了很清楚的认识,感觉自己突然想有了工作的人似的还有工资 但是更重要的是对eeworld的理解更进一步的加深了,在奖惩方面,e ...… 查看全部问答> |
|
我看书上的C语言例程是调用了printf函数的。 但我编的一个小程序里却因为调用了printf函数,而链接不成功。 我的程序框架是这样的: #include "regs2407.h" #include "stdio.h" void main(void) { &nbs ...… 查看全部问答> |




