带温度补偿的超声波测距程序

带温度补偿的超声波测距程序
带温度补偿的超声波测距程序

/**程序:基于HC-SR04得超声波测距系统

*单片机型号: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 〈reg51。h>

#include 〈intrins。h>

#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}

/*宏定义*/

#define uchar unsignedchar?//无符号8位

#define uint?unsigned int//无符号16位

#define ulongunsigned long ?//无符号32位

/*全局变量定义*/

sbit BEEP=P1^5;??//报警测量超出范围

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

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

float xdataDistanceValue=0。0;?//测量得距离值

float xdata SPEEDSOUND; ??//声速

float xdataXTALTIME; ?//单片机计数周期

uchar xdata stringBuf[6];??//数值转字符串缓冲

//LCD1602提示信息

uchar codePrompts[][16]=

?{"Measure Distance"}, //测量距离

{"-Out of Range -"}, //超出测量范围

?{"MAX range400cm "}, //测距最大值400cm

{”MIN range 2cm"},?//测距最小值2cm

{”"},?//清屏

};

uchar xdata DistanceText[]="Range: ";//测量结果字符串

uchar xdata TemperatureText[]="Temperature:";//测量温度值

/*外部函数声明*/

extern voidLCD_Initialize(); //LCD初始化

extern void LCD_Display_String(uchar*, uchar);

externvoid ReadTemperatureFromDS18B20();

extern int xdataCurTempInteger;

void DelayMS(uint ms);?//毫秒延时函数

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

voidHCSR04_Initialize();//HCSR04初始化

float MeasuringDistance();?//测量距离

float DistanceStatistics();?//测距得数值排序求平均

void DisplayDistanceValue(float dat); //输出距离值到LCD1602上

uchar UnsigedIntToString(uintvalue);?//将无符号得整数转成字符串,返回字符串长度,不包括'\0'结束符void Beep(uchar time); //蜂鸣器

void DisplayTemperatureValue(); //显示温度值

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

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初始化***/

void HCSR04_Initialize()

{

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

?SPEEDSOUND=334。1+25*0、61;?//温度25度时声速得值??

?Trig=0;

Echo=0;

TMOD=0x01;

}

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

void DisplayDistanceValue(floatdat)

{

uchari=0,j=0,len;

?uint value;

value=(uint)dat;

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

if(value〉4000)

?{

?LCD_Display_String(Prompts[1],0x00);

LCD_Display_String(Prompts[2],0x40);

Beep(2);?

?else if(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); ?}

}

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

void DisplayTemperatureValue()

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

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

TemperatureText[15]='C';

LCD_Display_String(TemperatureText,0x00);?

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

ucharUnsigedIntToString(uint value)

uchar i=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’;

?return length;

}

/***蜂鸣器***/

void Beep(uchar time)

?uchar i;

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

?{

?BEEP=!BEEP;

?DelayMS(time);?

?}

BEEP=0;

DelayMS(100);

}

/***延时函数毫秒@12、000MHz***/ void DelayMS(uint ms)

{

?uchar i, j;

while(ms—-)

?_nop_();

??i=2;

j=239;

do

??{

while(—-j);

??}while (--i);

?}

/***延时函数20微秒12、000MHz***/ void Delay20us()

uchar i;

_nop_();

?i=7;

while (--i);

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

void Timer0() interrupt 1

{

//DS18B20代码:

/*—------—-——-------——--—----—---——-———--—--—--—

*程序功能: DS18B20温度检测程序

*单片机型号:STC89C5212MHz

* 晶振: 12Mhz

-—----—--—-——-—--—-——--—------—-------—-------——*/

/*包含头文件*/

#include<reg51。h>

#include

/*宏定义*/

#defineuchar?unsigned char ?//无符号8位

#define uint?unsigned int//无符号16位

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

int xdata CurTempInteger; //当前采集得温度值整数部分

int xdata CurTempDecimal;//当前采集得温度值小数部分

/***功能:延时函数STC89C52 12MHz12T模式参数:无返回:无***/

void Delayus(uintcount) ?

{

?while (--count);

/***功能:DS18B20复位及状态检测参数:无返回:0或1,1表示未准备好,0表示准备好***/ uchar Reset_DS18B20()

?uchar status;

?DS18B20_DQ=1;

?Delayus(1);

//开始复位过程

DS18B20_DQ=0;?//数据线拉低

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

?DS18B20_DQ=1; ?//数据线拉高

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

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

?Delayus(120);

?return status;

/***功能:写一字节到DS18B20中参数:dat=数据返回:无***/

void WriteByteToDS18B20(uchar dat)

{

?uchar i;

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

?{

??DS18B20_DQ=0;

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

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

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

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

?}

}

/***功能:从DS18B20中读一字节参数:无返回:读取得数据***/

uchar ReadByteFromDS18B20()

?uchar i,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;

}

/***功能:读取温度值并转换成有符号得数值形式参数:无返回:无***/ void ReadTemperatureFromDS18B20()

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端口***/

sbit LCD_RS=P2^0;

sbit LCD_RW=P2^1;

sbit LCD_EN=P2^2;

/*** 功能:毫秒级延时函数参数:ms=毫秒数值?返回:无***/

void LCDDelay(uintms)

{

?uchar i, j;

while(ms-—)

??_nop_();

??i =2;

j=239;

?do

??{

??while (——j);

?}while (--i);

?}?

/***功能:1602液晶忙状态检测参数:无返回:0或1,1表示状态忙,0表示状态闲***/

bit LCD_Busy_Check()

{

bit result;

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

?Delay4us();

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

?LCD_EN=0;

returnresult;

}

/***功能:1602液晶写指令参数:cmd=1602LCD指令返回:无***/ void Write_LCD_Command(uchar cmd)

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=一个字节数据返回:无***/void Write_LCD_Data(uchar dat)

?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=位置地址值返回:无***/void LCD_Set_POS(uchar pos)

Write_LCD_mand(pos|0x80);

}

/*功能:1602液晶初始化参数:无返回:无***/

void LCD_Initialize()

{

Write_LCD_Command(0x01);?LCDDelay(5);

?Write_LCD_mand(0x38);?LCDDelay(5);

Write_LCD_Command(0x0C);?LCDDelay(5);

Write_LCD_Command(0x06);?LCDDelay(5);

/***功能:在1602液晶指定得行上显示字符串(共两行,一行16个字符) 参数:*str=字符串指针,LineNo=行首地址(第一行0x00,第二行0x40)

返回:无***/

void LCD_Display_String(uchar*str, uchar LineNo)

{

uchar k;

?LCD_Set_POS(LineNo);

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

Write_LCD_Data(str[k]);

?}?

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

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

void LCD_Display_OneChar(uchar Dat, uchar X, 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);

/***主函数***/

void main()

?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;

??else if(CurTempInteger〉26)

???CurTempInteger=26;

??SPEEDSOUND=334.1+CurTempInteger*0、61;//计算声速??DistanceValue=DistanceStatistics();//测距并返回距离值??DisplayDistanceValue(DistanceValue);//显示距离值?}

?}

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

float DistanceStatistics()

?uchar i,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; }

相关主题
相关文档
最新文档