带温度补偿的超声波测距程序之欧阳科创编.docx

上传人:b****8 文档编号:11241079 上传时间:2023-02-26 格式:DOCX 页数:18 大小:19.07KB
下载 相关 举报
带温度补偿的超声波测距程序之欧阳科创编.docx_第1页
第1页 / 共18页
带温度补偿的超声波测距程序之欧阳科创编.docx_第2页
第2页 / 共18页
带温度补偿的超声波测距程序之欧阳科创编.docx_第3页
第3页 / 共18页
带温度补偿的超声波测距程序之欧阳科创编.docx_第4页
第4页 / 共18页
带温度补偿的超声波测距程序之欧阳科创编.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

带温度补偿的超声波测距程序之欧阳科创编.docx

《带温度补偿的超声波测距程序之欧阳科创编.docx》由会员分享,可在线阅读,更多相关《带温度补偿的超声波测距程序之欧阳科创编.docx(18页珍藏版)》请在冰豆网上搜索。

带温度补偿的超声波测距程序之欧阳科创编.docx

带温度补偿的超声波测距程序之欧阳科创编

/**程序:

基于HC-SR04的超声波测距系统

时间:

2021.02.05

创作:

欧阳科

*单片机型号:

STC90C51612MHz

*说明:

开始连续进行7次超声波测距,每次测距间隔80ms,

*完成后对7次结果排序并将最大的2个数值和最小的2个数值去除,对剩余的

*3个数值取平均值。

完成后指示灯灭,输出结果到LCD1602上。

测量超出范围则发出报警声。

*使用两个IO端口控制HC-SR04触发信号输入和回响信号输出,

*以及一个T0定时器用于时间计数。

*使用DS18B20测量环境温度,声速公式:

V=334.1m/s+Temperature*0.61,

*单片机晶振为12Mhz(11.953M),计数时为T=1us

*计算公式:

S=(334.1m/s+Temperature*0.61)*N*T/2,N为计数值=TH0*256+TL0*/

/*包含头文件*/

#include

#include

#defineDelay4us(){_nop_();_nop_();_nop_();_nop_();}

/*宏定义*/

#defineucharunsignedchar//无符号8位

#defineuintunsignedint//无符号16位

#defineulongunsignedlong//无符号32位

/*全局变量定义*/

sbitBEEP=P1^5;//报警测量超出范围

sbitTrig=P3^4;//HC-SR04触发信号输入

sbitEcho=P3^2;//HC-SR04回响信号输出

floatxdataDistanceValue=0.0;//测量的距离值

floatxdataSPEEDSOUND;//声速

floatxdataXTALTIME;//单片机计数周期

ucharxdatastringBuf[6];//数值转字符串缓冲

//LCD1602提示信息

ucharcodePrompts[][16]=

{

{"MeasureDistance"},//测量距离

{"-OutofRange-"},//超出测量范围

{"MAXrange400cm"},//测距最大值400cm

{"MINrange2cm"},//测距最小值2cm

{""},//清屏

};

ucharxdataDistanceText[]="Range:

";//测量结果字符串

ucharxdataTemperatureText[]="Temperature:

";//测量温度值

/*外部函数声明*/

externvoidLCD_Initialize();//LCD初始化

externvoidLCD_Display_String(uchar*,uchar);

externvoidReadTemperatureFromDS18B20();

externintxdataCurTempInteger;

voidDelayMS(uintms);//毫秒延时函数

voidDelay20us();//20微秒延时函数

voidHCSR04_Initialize();//HCSR04初始化

floatMeasuringDistance();//测量距离

floatDistanceStatistics();//测距的数值排序求平均

voidDisplayDistanceValue(floatdat);//输出距离值到LCD1602上

ucharUnsigedIntToString(uintvalue);//将无符号的整数转成字符串,返回字符串长度,不包括'\0'结束符

voidBeep(uchartime);//蜂鸣器

voidDisplayTemperatureValue();//显示温度值

/***测量距离***/

floatMeasuringDistance()

{

//最大定时时间约65ms

TH0=0;

TL0=0;

//生成20us的脉冲宽度的触发信号

Trig=1;

Delay20us();

Trig=0;

while(!

Echo);//等待回响信号变高电平

TR0=1;//启动定时器0

while(Echo);//等待回响信号变低电平

TR0=0;//关闭定时器0

return(SPEEDSOUND*XTALTIME*((float)TH0*256+(float)TL0))/2000;//返回距离值(mm)

}

/***HCSR04初始化***/

voidHCSR04_Initialize()

{

XTALTIME=12/12;//计算单片机计数周期晶振=12M单位us

SPEEDSOUND=334.1+25*0.61;//温度25度时声速的值

Trig=0;

Echo=0;

TMOD=0x01;

}

/***输出距离值到LCD1602上***/

voidDisplayDistanceValue(floatdat)

{

uchari=0,j=0,len;

uintvalue;

value=(uint)dat;

//范围检查大于4000mm和小于20mm都为超出测量范围

if(value>4000)

{

LCD_Display_String(Prompts[1],0x00);

LCD_Display_String(Prompts[2],0x40);

Beep

(2);

}

elseif(value<20)

{

LCD_Display_String(Prompts[1],0x00);

LCD_Display_String(Prompts[3],0x40);

Beep

(2);

}

else

{

len=UnsigedIntToString(value);//将数值转换成字符串

//保留1位小数

while(stringBuf[i]!

='\0')

{

if(len-j==1)

{

DistanceText[6+j]='.';

j++;

}else

{

DistanceText[6+j]=stringBuf[i];

i++;

j++;

}

}

DistanceText[6+j]='c';

j++;

DistanceText[6+j]='m';

i=7+j;

//剩余位置补空格

while(i<16)

{

DistanceText[i]='';

i++;

}

LCD_Display_String(DistanceText,0x40);//LCD_Display_String(Prompts[0],0x00);

}

}

/***显示温度值***/

voidDisplayTemperatureValue()

{

TemperatureText[13]=CurTempInteger/10+'0';

TemperatureText[14]=CurTempInteger%10+'0';

TemperatureText[15]='C';

LCD_Display_String(TemperatureText,0x00);

}

/***将无符号的整数转成字符串,返回字符串长度***/

ucharUnsigedIntToString(uintvalue)

{

uchari=0,t,length;

//从个位开始转换

do

{

stringBuf[i]='0'+value%10;

value=value/10;

i++;

}while(value!

=0);

length=i;

//将字符串颠倒顺序

for(i=0;i<(length/2);i++)

{

t=stringBuf[i];

stringBuf[i]=stringBuf[length-i-1];

stringBuf[length-i-1]=t;

}

stringBuf[length]='\0';

returnlength;

}

/***蜂鸣器***/

voidBeep(uchartime)

{

uchari;

for(i=0;i<100;i++)

{

BEEP=!

BEEP;

DelayMS(time);

}

BEEP=0;

DelayMS(100);

}

/***延时函数毫秒@12.000MHz***/

voidDelayMS(uintms)

{

uchari,j;

while(ms--)

{

_nop_();

i=2;

j=239;

do

{

while(--j);

}while(--i);

}

}

/***延时函数20微秒@12.000MHz***/

voidDelay20us()

{

uchari;

_nop_();

i=7;

while(--i);

}

/***定时器0中断***/

voidTimer0()interrupt1

{

}

//DS18B20代码:

/*----------------------------------------------

*程序功能:

DS18B20温度检测程序

*单片机型号:

STC89C5212MHz

*晶振:

12Mhz

------------------------------------------------*/

/*包含头文件*/

#include

#include

/*宏定义*/

#defineucharunsignedchar//无符号8位

#defineuintunsignedint//无符号16位

sbitDS18B20_DQ=P3^3;//定义DS18B20端口DS18B20_DQ

intxdataCurTempInteger;//当前采集的温度值整数部分

intxdataCurTempDecimal;//当前采集的温度值小数部分

/***功能:

延时函数STC89C52@12MHz12T模式参数:

无返回:

无***/

voidDelayus(uintcount)

{

while(--count);

}

/***功能:

DS18B20复位及状态检测参数:

无返回:

0或1,1表示未准备好,0表示准备好***/

ucharReset_DS18B20()

{

ucharstatus;

DS18B20_DQ=1;

Delayus

(1);

//开始复位过程

DS18B20_DQ=0;//数据线拉低

Delayus(100);//延时480us-960us

DS18B20_DQ=1;//数据线拉高

Delayus(10);//延时15us-60us

status=DS18B20_DQ;//读取数据线上的状态

Delayus(120);

returnstatus;

}

/***功能:

写一字节到DS18B20中参数:

dat=数据返回:

无***/

voidWriteByteToDS18B20(uchardat)

{

uchari;

for(i=0;i<8;i++)

{

DS18B20_DQ=0;

DS18B20_DQ=dat&0x01;//发送1位数据

Delayus(15);//延时60us以上

DS18B20_DQ=1;//释放总线,等待总线恢复

dat>>=1;//准备下一位数据

}

}

/***功能:

从DS18B20中读一字节参数:

无返回:

读取的数据***/

ucharReadByteFromDS18B20()

{

uchari,dat=0;

for(i=0;i<8;i++)

{

DS18B20_DQ=0;//拉低总线,产生读信号

dat>>=1;

DS18B20_DQ=1;//释放总线,准备读1位数据

Delayus

(2);//延时4us

if(DS18B20_DQ)dat|=0x80;//合并每位数据

Delayus(15);//延时60us

DS18B20_DQ=1;//拉高总线,准备读下1位数据

}

returndat;

}

/***功能:

读取温度值并转换成有符号的数值形式参数:

无返回:

无***/

voidReadTemperatureFromDS18B20()

{

ucharflag=0;//正负符号标志

//存储当前采集的温度值

ucharTempValue[]={0,0};

if(Reset_DS18B20())//DS18B20复位

{

CurTempInteger=255;

CurTempDecimal=0;

}

else

{

WriteByteToDS18B20(0xCC);//跳过ROM命令

WriteByteToDS18B20(0x44);//温度转换命令

Reset_DS18B20();//复位

WriteByteToDS18B20(0xCC);//跳过ROM命令

WriteByteToDS18B20(0xBE);//读取温度暂存器命令

TempValue[0]=ReadByteFromDS18B20();//先读低字节温度值

TempValue[1]=ReadByteFromDS18B20();//后读高字节温度值

Reset_DS18B20();//复位

//计算温度值:

先进行正温度与负温度判断,高5位全为1(0xF8)则为负数

if((TempValue[1]&0xF8)==0xF8)

{

//负温度计算:

取反加1,低字节为0时,高字节取反加1,否则不需要。

TempValue[1]=~TempValue[1];

TempValue[0]=~TempValue[0]+1;

if(TempValue[0]==0x00)TempValue[1]++;

flag=1;//负数标志

}

//将温度值分为整数和小数两部分存储(默认为12位精度)

CurTempInteger=((TempValue[1]&0x07)<<4)|((TempValue[0]&0xF0)>>4);

if(flag)CurTempInteger=-CurTempInteger;

CurTempDecimal=(TempValue[0]&0x0F)*625;

}

}

//LCD1602程序代码:

/*程序功能:

1602液晶显示程序单片机型号:

STC90C16012MHz*/

/***1602液晶显示器控制端口分配,数据使用P0端口***/

sbitLCD_RS=P2^0;

sbitLCD_RW=P2^1;

sbitLCD_EN=P2^2;

/***功能:

毫秒级延时函数参数:

ms=毫秒数值返回:

无***/

voidLCDDelay(uintms)

{

uchari,j;

while(ms--)

{

_nop_();

i=2;

j=239;

do

{

while(--j);

}while(--i);

}

}

/***功能:

1602液晶忙状态检测参数:

无返回:

0或1,1表示状态忙,0表示状态闲***/

bitLCD_Busy_Check()

{

bitresult;

LCD_RS=0;LCD_RW=1;LCD_EN=1;

Delay4us();

result=(bit)(P0&0x80);

LCD_EN=0;

returnresult;

}

/***功能:

1602液晶写指令参数:

cmd=1602LCD指令返回:

无***/

voidWrite_LCD_Command(ucharcmd)

{

while(LCD_Busy_Check());

LCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();

P0=cmd;Delay4us();

LCD_EN=1;Delay4us();LCD_EN=0;

}

/***功能:

1602液晶写数据参数:

dat=一个字节数据返回:

无***/

voidWrite_LCD_Data(uchardat)

{

while(LCD_Busy_Check());

LCD_RS=1;LCD_RW=0;LCD_EN=0;

P0=dat;Delay4us();

LCD_EN=1;Delay4us();LCD_EN=0;

}

/***功能:

设置1602液晶显示位置参数:

pos=位置地址值返回:

无***/

voidLCD_Set_POS(ucharpos)

{

Write_LCD_Command(pos|0x80);

}

/*功能:

1602液晶初始化参数:

无返回:

无***/

voidLCD_Initialize()

{

Write_LCD_Command(0x01);LCDDelay(5);

Write_LCD_Command(0x38);LCDDelay(5);

Write_LCD_Command(0x0C);LCDDelay(5);

Write_LCD_Command(0x06);LCDDelay(5);

}

/***功能:

在1602液晶指定的行上显示字符串(共两行,一行16个字符)

参数:

*str=字符串指针,LineNo=行首地址(第一行0x00,第二行0x40)

返回:

无***/

voidLCD_Display_String(uchar*str,ucharLineNo)

{

uchark;

LCD_Set_POS(LineNo);

for(k=0;k<16;k++)

{

Write_LCD_Data(str[k]);

}

}

/***功能:

在1602液晶指定位置显示一个字符(共两行,一行16个字符)

参数:

Dat=一个字符,X=列位置(0-15)Y=行位置(0,1)返回:

无***/

voidLCD_Display_OneChar(ucharDat,ucharX,ucharY)

{

Y&=0x01;//限制Y不能大于1(2行,0-1)

X&=0x0F;//限制X不能大于15(16个字符,0-15)

if(Y){X|=0x40;}//当要在第二行显示时地址码+0x40;

X|=0x80;//算出指令码

Write_LCD_Command(X);

Write_LCD_Data(Dat);

}

/***主函数***/

voidmain()

{

LCD_Initialize();//1602初始化

LCD_Display_String(Prompts[0],0x00);

LCD_Display_String(Prompts[5],0x40);

ReadTemperatureFromDS18B20();//测温度

HCSR04_Initialize();//HC-SR04初始化

while

(1)

{

Beep

(1);

ReadTemperatureFromDS18B20();//测温度

DisplayTemperatureValue();

if(CurTempInteger<14)

CurTempInteger=14;

elseif(CurTempInteger>26)

CurTempInteger=26;

SPEEDSOUND=334.1+CurTempInteger*0.61;//计算声速

DistanceValue=DistanceStatistics();//测距并返回距离值

DisplayDistanceValue(DistanceValue);//显示距离值

}

}

//测距的数值排序求平均

floatDistanceStatistics()

{

uchari,j;

floatdisData[7],t;

//连续测距

for(i=0;i<7;i++)

{

disData[i]=MeasuringDistance();

DelayMS(80);

}

//排序

for(j=0;j<=6;j++)

{

for(i=0;i<7-j;i++)

{

if(disData[i]>disData[i+1])

{

t=disData[i];

disData[i]=disData[i+1];

disData[i+1]=t;

}

}

}

return(disData[2]+disData[3]+disData[4])/3;

}

时间:

2021.02.05

创作:

欧阳科

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 哲学历史

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1