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

51单片机超声波测距程序详解

超声波四通道测距:超声波测距实现分为三大块:

其一是12864带字库的液晶驱动程序:

51单片机超声波测距程序详解

代码如下:

/////////////////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

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

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭