当前位置:首页 > 芯闻号 > 基础知识科普站
[导读]51单片机超声波测距程序详解 超声波四通道测距:超声波测距实现分为三大块: 其一是12864带字库的液晶驱动程序:

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); //显示清屏

WriteCo

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

STM32与51单片机之间有什么差异呢?两者可以说是一场科技与性能的较量了。在科技飞速发展的今天,微控制器(MCU)已广泛应用于各类电子设备和系统中,发挥着举足轻重的作用。其中,STM32和51单片机作为两种常见的微控制...

关键字: STM32 51单片机 MCU

超声波测距原理将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对超声波测距的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 超声波 超声波测距 测距仪

51单片机将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对51单片机的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 单片机 51单片机

在嵌入式系统开发中,单片机是不可或缺的重要组成部分。其中,STM32单片机和51单片机是两种常见的单片机芯片。本文将对比分析这两种单片机的区别,并探讨STM32单片机的优势。

关键字: stm32单片 51单片机

51单片机是指由美国INTEL公司生产的一系列单片机的总称,这一系列单片机包括了许多品种,如8031,8051,8751,8032,8052,8752等,其中8051是最早最典型的产品,该系列其它单片机都是在8051的基...

关键字: 51单片机 串行通信

51单片机是一种常见的微控制器,它具有串行通信接口(Serial Communication Interface,SCI)。通过串口通信接口,51单片机可以与其他设备或系统进行串行通信,实现数据传输和控制。

关键字: 51单片机 串口通信

Pic单片机和51单片机是两种应用广泛的微控制器,它们各自具有不同的特点和优势,选择哪种单片机取决于具体应用需求。下面将对Pic单片机和51单片机进行详细的介绍和对比。

关键字: PIC单片机 51单片机 单片机

随着电子信息技术的快速发展,串行通信在各种应用中得到了广泛的应用。其中,51单片机作为一种常见的嵌入式系统,具有低功耗、高性能、易于编程等特点,常用于各种自动化控制、数据采集等系统中。而PC机具有强大的数据处理能力和丰富...

关键字: 51单片机 PC机 串行通信

51 单片机内部有一个全双工串行接口。什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行;既可接收又可发送,但不能同时进行的称为半双工;能同时接收和发送的串行口称为全双工串行口。

关键字: 51单片机 串口通信 半双工

步进电机是一种无刷电机,可将电脉冲转换为机械旋转。顾名思义,它根据输入脉冲逐步旋转,是现代数字程序控制系统中的主要执行元件。

关键字: 51单片机 步进电机 无刷电机
关闭
关闭