首先介绍硬件配置
超声波模板:
HC-SR04
单片机型号:
STC89C52RC
液晶显示屏:
LCD1602
接线:
Trig 接P2.0Echo接P2.1,VCC接VCC,GND接GND
介绍基本原理:
(图片来源:知乎小师弟)
然后直接上代码:
#include "reg52.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define out P0
***it RW=P2^5;
***it RS=P2^6;
***it E=P2^7;
***it Trig = P2^1;
***it Echo = P2^0;
uchar flag=0;
//LCD编码区:读状态-写命令-写数据-自动显示-------------------------------------------------------
//-----------------------------------------------------------------------------------------------
void delay(uint j) //1ms
{
while(j--)
{
uchar i;
for(i=0;i<125;i++);
}
}
void cbusy() //检查忙标志位函数
{
uchar dt;
do
{
dt=0xff;
E=0;
RS=0; //单片机原理P123页读状态
RW=1;
E=1;
dt=out; //状态输出给dt
}while(dt&0x80); //如果不忙结束
E=0; //E需要一个正脉冲
}
void wcommand(uchar com) //写命令
{
cbusy();
E=0;
RS=0;
RW=0;
out=com; //将命令com写入P0口中
E=1; //形成正脉冲
_nop_();
E=0; //高变低,LCD执行命令
delay(1); //等待硬件反应
}
void wdata(uint dat) //写数据函数
{
cbusy();
E=0;
RS=1;
RW=0;
out=dat; //数据从P0口输出写入LCD
E=1;
_nop_();
E=0; //高变低,写数据操作结束
delay(1);
}
void init() //初始化
{
wcommand(0x38); //命令6 P124
wcommand(0x0c); //命令4
wcommand(0x06); //命令3
wcommand(0x01); //命令1
wcommand(0x80); //设置数据指针起点
}
void string(uchar ad,uchar *s) //LCD显示,s指针指向字符串常量,内容无法更改
{
wcommand(ad);
while(*s>0)
{
wdata(*s++);
delay(50); //延迟50ms观察数字
}
}
void tring(uchar ad,uchar s) //LCD显示数字,s指向字符常量,内容可以更改
{
wcommand(ad);
wdata(s);
delay(50);
}
void lcdshow() //LCD初显示
{
init();
string(0x80,"distance:");
string(0xc0,"texting");
}
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
void zd() interrupt 1 //T0中断
{
flag=1;
}
void count()
{
uchar a[4]={0,0,0,0};
uint time=0;
unsigned long dist=0;
uchar code as[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','m'};
time=TH0*256+TL0; //TH0+TL0
TH0=0;
TL0=0;
dist=(time*1.72)/100; //340×0.000001=0.00034米=0.034厘米,除以2就是所测距离:0.017=1.7/100
if((dist>1127)||flag==1) //最大定时时间65536us*0.0172=1127cm=11.27m
{
flag=0;
string(0xc0,">_< "); //显示超过最大距离
}
else
{
string(0xc0," ");
a[0]=dist%1000/100; //百位
a[1]=dist%100/10; //十位
a[2]=dist%10; //个位
tring(0xc0,as[a[0]]); //显示距离,a[0]是数字,as[0]是字符串
string(0xc1,".");
tring(0xc2,as[a[1]]);
tring(0xc3,as[a[2]]);
tring(0xc4,as[12]);
}
}
void start()
{
Trig=1; //启动超声波
_nop_(); //_nop_的延时时间是一个机器周期1us,用nop进行精准控制时间,delay无法精准定时
_nop_(); //存在20us的高电平
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Trig=0;
}
void main()
{
TMOD=0x01; //初始化定时器T0为方式1
TH0=0;
TL0=0;
EA=1;
ET0=1;
init();
lcdshow();
while(1)
{
start();
while(!Echo); //等待引脚成高电平,相当于发出超声波信号
TR0=1;
while(Echo); //等待引脚成低电平,相当于收到超声波信号
TR0=0;
count();
delay(100);
}
}
出现的页数教材是电子工业出版社单片机原理与应用设计第三版里面基础的原理,需要的私聊。
最终运行结果是个动态刷新过程。
超声波测距其实是比较差的方式,这是由于本身硬件结构所造成的
(图片来自百度)
倘若障碍物表面是倾斜的对应超声波接受探头(Echo)接收数据就存在偏差。
理论上应该能接受最远距离11.27,但经过我实验最远只能到达9.68,原因我暂时还未弄清
超声波这个模板常用于小车避障和附件障碍物检测,加上舵机,会很有意思。
代码部分个人编写感觉不够精简,特此希望大家提出宝贵意见。
首先介绍硬件配置
超声波模板:
HC-SR04
单片机型号:
STC89C52RC
液晶显示屏:
LCD1602
接线:
Trig 接P2.0Echo接P2.1,VCC接VCC,GND接GND
介绍基本原理:
(图片来源:知乎小师弟)
然后直接上代码:
#include "reg52.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define out P0
***it RW=P2^5;
***it RS=P2^6;
***it E=P2^7;
***it Trig = P2^1;
***it Echo = P2^0;
uchar flag=0;
//LCD编码区:读状态-写命令-写数据-自动显示-------------------------------------------------------
//-----------------------------------------------------------------------------------------------
void delay(uint j) //1ms
{
while(j--)
{
uchar i;
for(i=0;i<125;i++);
}
}
void cbusy() //检查忙标志位函数
{
uchar dt;
do
{
dt=0xff;
E=0;
RS=0; //单片机原理P123页读状态
RW=1;
E=1;
dt=out; //状态输出给dt
}while(dt&0x80); //如果不忙结束
E=0; //E需要一个正脉冲
}
void wcommand(uchar com) //写命令
{
cbusy();
E=0;
RS=0;
RW=0;
out=com; //将命令com写入P0口中
E=1; //形成正脉冲
_nop_();
E=0; //高变低,LCD执行命令
delay(1); //等待硬件反应
}
void wdata(uint dat) //写数据函数
{
cbusy();
E=0;
RS=1;
RW=0;
out=dat; //数据从P0口输出写入LCD
E=1;
_nop_();
E=0; //高变低,写数据操作结束
delay(1);
}
void init() //初始化
{
wcommand(0x38); //命令6 P124
wcommand(0x0c); //命令4
wcommand(0x06); //命令3
wcommand(0x01); //命令1
wcommand(0x80); //设置数据指针起点
}
void string(uchar ad,uchar *s) //LCD显示,s指针指向字符串常量,内容无法更改
{
wcommand(ad);
while(*s>0)
{
wdata(*s++);
delay(50); //延迟50ms观察数字
}
}
void tring(uchar ad,uchar s) //LCD显示数字,s指向字符常量,内容可以更改
{
wcommand(ad);
wdata(s);
delay(50);
}
void lcdshow() //LCD初显示
{
init();
string(0x80,"distance:");
string(0xc0,"texting");
}
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
void zd() interrupt 1 //T0中断
{
flag=1;
}
void count()
{
uchar a[4]={0,0,0,0};
uint time=0;
unsigned long dist=0;
uchar code as[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','m'};
time=TH0*256+TL0; //TH0+TL0
TH0=0;
TL0=0;
dist=(time*1.72)/100; //340×0.000001=0.00034米=0.034厘米,除以2就是所测距离:0.017=1.7/100
if((dist>1127)||flag==1) //最大定时时间65536us*0.0172=1127cm=11.27m
{
flag=0;
string(0xc0,">_< "); //显示超过最大距离
}
else
{
string(0xc0," ");
a[0]=dist%1000/100; //百位
a[1]=dist%100/10; //十位
a[2]=dist%10; //个位
tring(0xc0,as[a[0]]); //显示距离,a[0]是数字,as[0]是字符串
string(0xc1,".");
tring(0xc2,as[a[1]]);
tring(0xc3,as[a[2]]);
tring(0xc4,as[12]);
}
}
void start()
{
Trig=1; //启动超声波
_nop_(); //_nop_的延时时间是一个机器周期1us,用nop进行精准控制时间,delay无法精准定时
_nop_(); //存在20us的高电平
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Trig=0;
}
void main()
{
TMOD=0x01; //初始化定时器T0为方式1
TH0=0;
TL0=0;
EA=1;
ET0=1;
init();
lcdshow();
while(1)
{
start();
while(!Echo); //等待引脚成高电平,相当于发出超声波信号
TR0=1;
while(Echo); //等待引脚成低电平,相当于收到超声波信号
TR0=0;
count();
delay(100);
}
}
出现的页数教材是电子工业出版社单片机原理与应用设计第三版里面基础的原理,需要的私聊。
最终运行结果是个动态刷新过程。
超声波测距其实是比较差的方式,这是由于本身硬件结构所造成的
(图片来自百度)
倘若障碍物表面是倾斜的对应超声波接受探头(Echo)接收数据就存在偏差。
理论上应该能接受最远距离11.27,但经过我实验最远只能到达9.68,原因我暂时还未弄清
超声波这个模板常用于小车避障和附件障碍物检测,加上舵机,会很有意思。
代码部分个人编写感觉不够精简,特此希望大家提出宝贵意见。
举报