51单片机超声波四通道端口扫描方式测距

发布者:JoyfulSpirit最新更新时间:2015-01-07 来源: 51hei关键字:51单片机  超声波  四通道端口  扫描方式  测距 手机看文章 扫描二维码
随时随地手机看文章
超声波四通道测距:超声波测距实现分为三大块:
其一是12864带字库的液晶驱动程序:
代码如下:
/////////////////12864驱动程序///////////////////////////
//1写数据
void WriteDataLCD(unsigned char WDLCD)
{
 ReadStatusLCD(); //检测忙 
 LCD_RS = 1;
 LCD_RW = 0;
 LCD_Data = WDLCD;
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 0;
}
 
//2写指令
void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC为0时忽略忙检测
{
 if (BuysC) ReadStatusLCD(); //根据需要检测忙 
 LCD_RS = 0;
 LCD_RW = 0; 
 LCD_Data = WCLCD;
 LCD_E = 1; 
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 0;  
}
 
//3读数据
unsigned char ReadDataLCD(void)
{
 LCD_RS = 1; 
 LCD_RW = 1;
 LCD_E = 0;
 LCD_E = 0;
 LCD_E = 1;
 return(LCD_Data);
}
 
//4读状态
unsigned char ReadStatusLCD(void)
{
 LCD_Data = 0xFF; 
 LCD_RS = 0;
 LCD_RW = 1; 
 LCD_E = 1;
 while (LCD_Data & Busy); //检测忙信号
 LCD_E = 0;
 return(LCD_Data);
}
 
void LCDInit(void) //5LCM初始化
{
 WriteCommandLCD(0x30,1); //显示模式设置,开始要求每次检测忙信号
 WriteCommandLCD(0x01,1); //显示清屏
 WriteCommandLCD(0x06,1); // 显示光标移动设置
 WriteCommandLCD(0x0C,1); // 显示开及光标设置
}
void LCDClear(void) //6清屏
{
 WriteCommandLCD(0x01,1); //显示清屏
 WriteCommandLCD(0x34,1); // 显示光标移动设置
 WriteCommandLCD(0x30,1); // 显示开及光标设置
}
 
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
 if(Y<1)
  Y=1;
 if(Y>4)
  Y=4;
 X &= 0x0F; //限制X不能大于16,Y不能大于1
 switch(Y){
case 1:X|=0X80;break;
case 2:X|=0X90;break;
case 3:X|=0X88;break;
case 4:X|=0X98;break;
}
 WriteCommandLCD(X, 0); //这里不检测忙信号,发送地址码
 WriteDataLCD(DData);
}
 
//9按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
 unsigned char ListLength,X2;
  ListLength = 0;
  X2=X;
 if(Y<1)
  Y=1;
 if(Y>4)
  Y=4;
 X &= 0x0F; //限制X不能大于16,Y在1-4之内
 switch(Y){
case 1:X2|=0X80;break; //根据行数来选择相应地址
case 2:X2|=0X90;break;
case 3:X2|=0X88;break;
case 4:X2|=0X98;break;
}
 WriteCommandLCD(X2, 1); //10发送地址码
  while (DData[ListLength]>=0x20) //若到达字串尾则退出
  {
   if (X <= 0x0F) //X坐标应小于0xF
    {
     WriteDataLCD(DData[ListLength]); //
     ListLength++;
X++;
Delay5Ms();
    }
  }
}
其二是超声波模块的检测部分程序:该部分程序的超声波发射与接受程序没有采用外部中断的方式实现毕竟51单片机的外部中断稀少比较珍贵,也最多只能驱动2组,达不到预期所需要的。故在本程序中我是才用的端口扫描的方式实现的。
程序代码如下:void tran4(void)///可通过设置K数值选择执行相应的I0发射超声波
{
uchar i;
float temp;
TMOD=0XF0;
TMOD |=0X01;
TL0=0X47;
TH0=0XFF;
TR0=0;
ET0=0;//关闭timme0中断?
csb4=1;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
 
csb4=0;
TR0=0;
TH0=0;
TL0=0;
while(in4==0);
TR0=1;
while(in4==1);
TR0=0;
temp=(TH0*256+TL0)*1.08/58; //1.08为分频之后的数
//蜂鸣器响
if(temp<20)beef=0;
delay_nms(60);
beef=1;
//
if(temp>4000)temp=4000;
dis =(unsigned int)temp;//dis将直接用于显示函数
delay_nms(60);
display(dis);
shuju[0]=shuju[0]+3;
for(i=0;i<6;i++)
DisplayOneChar(i,4,shuju[i]); //显示字库中的中文数子
}
超声波测距需要:现发送一组超声波,当超声波受到障碍物被弹回后经超声波接受线路接受后根据高低电平进行计算这段时间,并将该时间与超声波传输的速度之间的关系换算成与物体之间的距离:
这就是其三:将接受到发挥的超声波所需时间转换程与物体之间的距离:
换算程序如下:
void display(uint dat)
{
 
uchar i,j,k;//定义变量
i=dat/100;//白
j=dat0/10;//十位
k=dat0;//个
 
shuju[0]=65;
shuju[1]=i+48;//根据asc码值要加48才能正确在液晶上显示字符(具体参考液晶手册)
shuju[2]='.';
shuju[3]=j+48;
shuju[4]=k+48;
shuju[5]=109;//或者shuju[4]='m';
}
 
以上三步完成程序也就相当容易了:
完整超声波四通道端口扫描方式测距程序如下:
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define nop _nop_()
#define LCD_Data P0
#define Busy    0x80 //用于检测LCD状态字中的Busy标识
 
sbit csb1=P1^0;//tr 40KHz超声波发射脚
sbit in1=P1^1;
 
sbit csb2=P1^2;
sbit in2=P1^3;
 
sbit  csb3=P2^2;
sbit  in3=P2^3;
 
sbit in4=P2^0;
sbit  csb4=P2^1;
 
sbit LCD_RS=P3^5;//定义引脚
sbit LCD_RW=P3^6;
sbit LCD_E=P3^4;
//sbit PSB =P3^7;
sbit PSB =P3^1; //PSB脚为12864-12系列的串、并通讯功能切换,我们使用8位并行接口,PSB=1
sbit beef =P2^6;
//LCD显示字符函数
void WriteDataLCD(unsigned char WDLCD);
void WriteCommandLCD(unsigned char WCLCD,BuysC);
unsigned char ReadDataLCD(void);
unsigned char ReadStatusLCD(void);
void LCDInit(void);
void LCDClear(void);
//void LCDFlash(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
//void DisplayImage (unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
/////////////////////////////超声波发射接收子函数体
 
void  delay100us();
void delay_nms(uint n);
void tran1(void);
void tran2(void);
void tran3(void);
void tran4(void);
void display(uint dat);
unsigned char  shuju[5];//////////////////////////////字符定义;
 
////////////////////////////////////////////////超声波发射接收全局变量
unsigned char flag;
unsigned int tmp,dis,high_time ,low_time ;
///////////////////////////////////////////////
/////////////////////////////////////////////////主程序函数
void main(void)
{
 
Delay400Ms(); //启动等待,等LCD讲入工作状态
 LCDInit(); //LCM初始化
 Delay5Ms(); //延时片刻(可不要)
 
while(1)
{
// uint i;
tran1( );
 
// Delay400Ms();
// Delay400Ms();//通过延时防止因csb1接收引起中断
//// display(200);
// for(i=0;i<5;i++)
// DisplayOneChar(i,1,shuju[i]); //显示字库中的中文数子
tran2( );
// Delay400Ms();
// Delay400Ms();//通过延时防止因csb1接收引起中断
tran3( );
// Delay400Ms();
// Delay400Ms();//通过延时防止因csb1接收引起中断
tran4( );
Delay400Ms();
Delay400Ms();
// Delay400Ms();
// Delay400Ms();//通过延时防止因csb1接收引起中断
// LCDClear();//清屏
// Delay400Ms();
// LCDClear();
 
}
}
////////////////////////////////////////////////////
 
//延时函数体
void  delay100us()
{
    uchar i;
        for(i=0;i<50;i++)
            ;
}
void delay_nms(uint n)
{
uchar i; 
while(n--)
{
for(i=123;i>0;i--);
}
}
//////超声波发射程序
void tran1(void)///可通过设置K数值选择执行相应的I0发射超声波
{
uchar i;
float temp;
TMOD=0XF0;
TMOD |=0X01;
TL0=0X47;
TH0=0XFF;
TR0=0;
ET0=0;//关闭timme0中断?
csb1=1;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
 
csb1=0;
TR0=0;
TH0=0;
TL0=0;
while(in1==0);
TR0=1;
while(in1==1);
TR0=0;
temp=(TH0*256+TL0)*1.08/58; //1.08为分频之后的数
//蜂鸣器响
if(temp<20)beef=0;
delay_nms(60);
beef=1;
//
if(temp>4000)temp=4000;
dis =(unsigned int)temp;//dis将直接用于显示函数
delay_nms(60);
display(dis);
for(i=0;i<6;i++)
DisplayOneChar(i,1,shuju[i]); //显示字库中的中文数子
}
 
void tran2(void)///可通过设置K数值选择执行相应的I0发射超声波
{
uchar i;
float temp;
TMOD=0XF0;
TMOD |=0X01;
TL0=0X47;
TH0=0XFF;
TR0=0;
ET0=0;//关闭timme0中断?
csb2=1;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
 
csb2=0;
TR0=0;
TH0=0;
TL0=0;
while(in2==0);
TR0=1;
while(in2==1);
TR0=0;
temp=(TH0*256+TL0)*1.08/58; //1.08为分频之后的数
//蜂鸣器响
if(temp<20)beef=0;
delay_nms(60);
beef=1;
//
if(temp>4000)temp=4000;
dis =(unsigned int)temp;//dis将直接用于显示函数
delay_nms(60);
display(dis);
shuju[0]=shuju[0]+1;
for(i=0;i<6;i++)
DisplayOneChar(i,2,shuju[i]); //显示字库中的中文数子
}
void tran3(void)///可通过设置K数值选择执行相应的I0发射超声波
{
uchar i;
float temp;
TMOD=0XF0;
TMOD |=0X01;
TL0=0X47;
TH0=0XFF;
TR0=0;
ET0=0;//关闭timme0中断?
csb3=1;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
 
csb3=0;
TR0=0;
TH0=0;
TL0=0;
while(in3==0);
TR0=1;
while(in3==1);
TR0=0;
temp=(TH0*256+TL0)*1.08/58; //1.08为分频之后的数
//蜂鸣器响
if(temp<20)beef=0;
delay_nms(60);
beef=1;
//
if(temp>4000)temp=4000;
dis =(unsigned int)temp;//dis将直接用于显示函数
delay_nms(60);
display(dis);
shuju[0]=shuju[0]+2;
for(i=0;i<6;i++)
DisplayOneChar(i,3,shuju[i]); //显示字库中的中文数子
}
void tran4(void)///可通过设置K数值选择执行相应的I0发射超声波
{
uchar i;
float temp;
TMOD=0XF0;
TMOD |=0X01;
TL0=0X47;
TH0=0XFF;
TR0=0;
ET0=0;//关闭timme0中断?
csb4=1;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
nop;
 
csb4=0;
TR0=0;
TH0=0;
TL0=0;
while(in4==0);
TR0=1;
while(in4==1);
TR0=0;
temp=(TH0*256+TL0)*1.08/58; //1.08为分频之后的数
//蜂鸣器响
if(temp<20)beef=0;
delay_nms(60);
beef=1;
//
if(temp>4000)temp=4000;
dis =(unsigned int)temp;//dis将直接用于显示函数
delay_nms(60);
display(dis);
shuju[0]=shuju[0]+3;
for(i=0;i<6;i++)
DisplayOneChar(i,4,shuju[i]); //显示字库中的中文数子
}
///////////////////////////////////
void display(uint dat)
{
 
uchar i,j,k;//定义变量
i=dat/100;//白
j=dat0/10;//十位
k=dat0;//个
 
shuju[0]=65;
shuju[1]=i+48;
shuju[2]='.';
shuju[3]=j+48;
shuju[4]=k+48;
shuju[5]=109;//或者shuju[4]='m';
}
 
 
 
////////////////////////////////////////////
//1写数据
void WriteDataLCD(unsigned char WDLCD)
{
 ReadStatusLCD(); //检测忙 
 LCD_RS = 1;
 LCD_RW = 0;
 LCD_Data = WDLCD;
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 0;
}
 
//2写指令
void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC为0时忽略忙检测
{
 if (BuysC) ReadStatusLCD(); //根据需要检测忙 
 LCD_RS = 0;
 LCD_RW = 0; 
 LCD_Data = WCLCD;
 LCD_E = 1; 
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 0;  
}
 
//3读数据
unsigned char ReadDataLCD(void)
{
 LCD_RS = 1; 
 LCD_RW = 1;
 LCD_E = 0;
 LCD_E = 0;
 LCD_E = 1;
 return(LCD_Data);
}
 
//4读状态
unsigned char ReadStatusLCD(void)
{
 LCD_Data = 0xFF; 
 LCD_RS = 0;
 LCD_RW = 1; 
 LCD_E = 1;
 while (LCD_Data & Busy); //检测忙信号
 LCD_E = 0;
 return(LCD_Data);
}
 
void LCDInit(void) //5LCM初始化
{
 WriteCommandLCD(0x30,1); //显示模式设置,开始要求每次检测忙信号
 WriteCommandLCD(0x01,1); //显示清屏
 WriteCommandLCD(0x06,1); // 显示光标移动设置
 WriteCommandLCD(0x0C,1); // 显示开及光标设置
}
void LCDClear(void) //6清屏
{
 WriteCommandLCD(0x01,1); //显示清屏
 WriteCommandLCD(0x34,1); // 显示光标移动设置
 WriteCommandLCD(0x30,1); // 显示开及光标设置
}
 
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
 if(Y<1)
  Y=1;
 if(Y>4)
  Y=4;
 X &= 0x0F; //限制X不能大于16,Y不能大于1
 switch(Y){
case 1:X|=0X80;break;
case 2:X|=0X90;break;
case 3:X|=0X88;break;
case 4:X|=0X98;break;
}
 WriteCommandLCD(X, 0); //这里不检测忙信号,发送地址码
 WriteDataLCD(DData);
}
 
//9按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
 unsigned char ListLength,X2;
  ListLength = 0;
  X2=X;
 if(Y<1)
  Y=1;
 if(Y>4)
  Y=4;
 X &= 0x0F; //限制X不能大于16,Y在1-4之内
 switch(Y){
case 1:X2|=0X80;break; //根据行数来选择相应地址
case 2:X2|=0X90;break;
case 3:X2|=0X88;break;
case 4:X2|=0X98;break;
}
 WriteCommandLCD(X2, 1); //10发送地址码
  while (DData[ListLength]>=0x20) //若到达字串尾则退出
  {
   if (X <= 0x0F) //X坐标应小于0xF
    {
     WriteDataLCD(DData[ListLength]); //
     ListLength++;
X++;
Delay5Ms();
    }
  }
}
//125ms延时
void Delay5Ms(void)
{
 unsigned int TempCyc = 5552;
 while(TempCyc--);
}
 
//13400ms延时
void Delay400Ms(void)
{
 unsigned char TempCycA = 5;
 unsigned int TempCycB;
 while(TempCycA--)
 {
  TempCycB=7269;
  while(TempCycB--);
 };
}
 
以上代码经本人亲自测试基本功能都能实现最大测量距离是5米,精度达到1厘米:
关键字:51单片机  超声波  四通道端口  扫描方式  测距 引用地址:51单片机超声波四通道端口扫描方式测距

上一篇:C52通用的头文件REG52.H详解
下一篇:基于AT89S52的无线温度报警系统

推荐阅读最新更新时间:2024-03-16 13:50

基于51单片机的酒精浓度监测仪
一.系统概述 系统使用的模块有AT89C51单片机+LCD1602显示屏+MQ-3酒精检测模块+小灯+ADC0832。 本设计采用51单片机为核心控制,通过调节电位器可以模拟MQ-3酒精浓度的变化,MQ-3采集到的模拟电压信号会通过ADC0832转换为数字电压信号,单片机会将电压信号进行处理和分析并得到我们想要的酒精浓度信号,通过LCD1602显示屏显示酒精浓度,当检测到的酒精浓度高于设置的阈值,小灯就会直接进行报警。 二.仿真概述 1.通过LCD1602显示实时检测到的酒精浓度和设置的酒精浓度阈值。 2.通过MQ-3乙醇模块进行酒精浓度的检测。 3.当检测到的酒精浓度值超过设定阈值后就会通过小灯进行报警。 三
[单片机]
基于<font color='red'>51单片机</font>的酒精浓度监测仪
基于51单片机的高性能直流稳压电源
引言 众所周知,许多科学实验都离不开电,并且在这些实验中经常会对通电时间、电压高低、电流大小以及动态指标有着特殊的要求,因此,如果实验电源不仅具有良好的输出质量而且还具有多功能以及一定的智能化,那么就省去了许多不精确的人为操作,取而代之的是精确的微机控制,而我们所要做的就是在实验开始前对一些参数进行预设。这将会给各个领域中的实验研究带来不同程度的便捷与高效。因此,直流电源今后的发展目标之一就是不仅要在性能上做到效率高、噪声低、高次谐波低、既节能又不干扰环境,还要在功能上力求实现数控化、多功能化与智能化。本文所介绍的就是一个将开关电源和线性电源有机地结合起来,兼具二者优点的高性能直流稳压电源。由于在该电源中引入了单片机控制,故该
[单片机]
基于<font color='red'>51单片机</font>的高性能直流稳压电源
51单片机不断电下载程序
stc单片机支持串口isp程序下载,不必使用专用下载器,仅使用串口就能下载程序。但每次下载程序都要断电再上电,比较麻烦。 下面介绍一种不需断电就能下载程序的方法,在程序调试时比较方便。 基本原理: stc单片机有专用的复位寄存器,通过对该寄存器写入不同的数值可以实现单片机热启动复位。 寄存器功能如下图所示: 由上图可以看出只要满足某个条件,向ISP_CONTR写入0x60,就可以实现从ISP监控区软启动启动 某个条件设置为:当串口接收到0xaa数据时,单片机执行ISP_CONTR=0x60; 指令,从ISP监控区软启动启动。 演示程序如下: //*************************STC12C5410AD软启
[单片机]
<font color='red'>51单片机</font>不断电下载程序
超声波打孔机电路图
=756) window.open('/up_files/image/2007-3-19/36860411.gif');" border=0 alt="" src="http://www.elecfans.com/article/UploadPic/2009-4/20094818258321.gif" width=672 onload="if(this.width>'756')this.width='756';" height=526> 超声波打孔机可用于水晶、宝石、玛瑙、翡翠、玻璃制品、陶瓷器具及锗、硅、铁氧体等一些高硬度材料钻孔和雕刻。此机由超声波发生器和加工机头(包括换能器、变幅杆等)组成。超声波发生器电路见附图。此电路简
[模拟电子]
51单片机项目设计:超声波测距、智能小车(keil+proteus)
项目展示: 仿真展示 : 一、项目要求 (一)项目内密 本课题的主要内容是,将超声波传感器安装在一台沿直线行走的小车上,由AT89C51 控制超声波传感器,发出超声信号,记录超声液从发射到接收的所需要的时间,得到其与|被测物体之间的能离。在小车行走的过程中,不断重复测距,得到一组距离数据。由单片机记录测得的距离,经过数据处理,将其显示在液晶屏上。同时,将一组距离数据,由串口传到上位机,由VB程序保存距离数据,并画出曲线,就得到了被测物体的单边轮廓。 (二)课题研究方需 超声波测距仪系统主要由单片机最小系统、超声波模块、LCO显示电路及电源电路组成。系统的主要功能如下: 超声波传感器发射和接收超声波,依据计时
[单片机]
<font color='red'>51单片机</font>项目设计:<font color='red'>超声波</font><font color='red'>测距</font>、智能小车(keil+proteus)
51单片机系列知识3--存储器(2)
3、 内部数据存储器的低128单元(00H~7FH) 51单片机的内部数据存储器总容量为256字节,地址由00H~FFH.这256字节的地址空间可以分成功能不同的低128字节单元和高128字节单元。 在256字节的内部数据存储器中,还有一个“位地址”空间(不是独立的)。其中一部分位在低128单元中,另一部分在高128单元中。所以内部数据存储器中有一些单元既可以对其执行按字节操作,也可以对该单元中的某一位单独进行为操作。 高128字节存放了特殊功能寄存器,但也有许多单元是空着的,这些单元是为51系类单片机的新型号保留的,一些已出现的新型号单片机因内部功能器件的增加而增加了不少特殊功能寄存器。为了使软件与新型单片机兼容,用
[单片机]
<font color='red'>51单片机</font>系列知识3--存储器(2)
MaxBotix系列超声波传感器在车内检测中的应用
随着时代的发展,车辆变成了家庭的必备交通工具。外面各型各色的汽车中,或许只有驾驶员一人,或许有一家老小,或许后排还有个小朋友在睁大眼睛看着“移动中的世界”,或者宠物透过玻璃窗户再跟周围的行人“打招呼”。然而,即使如今的汽车技术越来越先进,也加入了诸多安全技术。但,却不能驾驶员的记忆力。驾驶员遗忘后排的老人、儿童、宠物的事件依旧不断发生着。 据有关报告显示,自1998年以来,美国已有超过800名儿童死于车内中暑。大概平均每年有38名儿童被困于车辆内而亡,并与高温有关。在2018年,这一死亡数据达到52人。据不安全统计,在中国,2010年到2015年之间,至少发生20起儿童被遗忘在车内的事件,事件不只是发生于私家车,也发生在校车内
[汽车电子]
MaxBotix系列<font color='red'>超声波</font>传感器在车内检测中的应用
从零开始51单片机教程——连载6 延时程序分析
掌握汇编中的延时程序 上一次课中,我们已经知道,程序中的符号R7、R6是代表了一个个的RAM单元,是用来放一些数据的,下面我们再来看一下其它符号的含义。 DELAY: MOV R7,#250   ;(6) D1: MOV R6,#250   ;(7) D2: DJNZ R6,D2    ;(8) DJNZ R7,D1   ;(9)    RET        ;(10) 〈单片机延时程序〉 MOV:这是一条指令,意思是传递数据。说到传递,我们都很清楚,传东西要从一本人的手上传到另一本人的手上,也就是说要有一个接受者,一个传递者和一样东西。从指令MOV R7,#250中来分析,R7是一个接
[单片机]
从零开始<font color='red'>51单片机</font>教程——连载6 延时程序分析
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved