|
超聲波測(cè)距(超聲波模塊+18B20+1602液晶)
#include"reg52.h"
#include"math.h"
#define uchar unsigned char
#define uint unsigned int
#define LcdData P0 //1602數(shù)據(jù)端口
sbit LCD_RS=P3^5; //1602 RS端口
sbit LCD_RW=P2^5; //1602 RW端口
sbit LCD_EN=P3^4; //1602 EN端口
sbit Echo=P1^6; //HC-SR04 接收端口
sbit Trig=P1^7; //HC-SR04 發(fā)射端口
sbit Resets_Key=P3^3; //復(fù)位清零按鍵
sbit Single_Key=P3^2; //單次測(cè)量按鍵 誤差較大
sbit Contin_Key=P1^3; //連續(xù)測(cè)量按鍵 誤差小
sbit Averag_Key=P1^2; //連續(xù)(平均測(cè)量)按鍵 誤差較小
sbit DQ=P2^2; //DS18B20單總線接口
bit Temp_Flag; //正負(fù)溫度標(biāo)志:溫度為正Temp_Flag=0,否則為1
uint temp=25; //溫度值
bit flag_flow=0,flag_one=0,flag_clear=0,flag_con1=0,flag_con2=0,flag_temp=0;
uchar i=0,m,j,k;
uint time=0,S=0,S1=0,totle=0;
float V=346.0;
uint Sav[11]; //連續(xù)測(cè)量時(shí)10次平均值數(shù)組
uchar Line1[16]={"T: C V:346m/s"}; //1602第一行初始字符顯示數(shù)組
uchar Line2[16]={"S= m "}; //1602第二行初始字符顯示數(shù)組
void Delayms(uchar xms); //延時(shí)xms函數(shù)
void WriteLcd(uchar Dat,bit x); //1602寫(xiě)函數(shù)
void InitLcd(void); //1602初始化函數(shù)
void DisplayLcd(); //1602顯示函數(shù)
void init(); //初始化函數(shù)
void keyscan(); //鍵掃描函數(shù)
void StartModule(); //啟動(dòng)模塊函數(shù)
void Conut(void); //測(cè)量計(jì)算函數(shù)
void Delayus(uchar xus); //us級(jí)延時(shí)函數(shù)
bit Init_DS18B20(void); //初始化DS18B20函數(shù)
uchar Read_DS18B20(void); //讀DS18B20函數(shù)
void Write_DS18B20(uchar Dat); //寫(xiě)DS18B20函數(shù)
void GetTemp(); //取溫度函數(shù)
void CalcTestTemp(); //溫度處理函數(shù)
void main(void) //主函數(shù)
{
init();
InitLcd();
while(1)
{
keyscan(); //鍵掃描函數(shù)
DisplayLcd();
if(flag_temp==0)
{
GetTemp();
CalcTestTemp();
}
if(flag_one==1||flag_con1==1||flag_con2==1)
{
StartModule(); //開(kāi)始發(fā)射超聲波
while(!Echo); //當(dāng)RX為零時(shí)等待
TR0=1; //開(kāi)啟計(jì)數(shù)
while(Echo); //當(dāng)RX為1計(jì)數(shù)并等待
TR0=0; //關(guān)閉計(jì)數(shù)
Conut(); //計(jì)算
Delayus(200);
flag_one=0;
}
}
}
void Delayms(uchar xms) //延時(shí)ms函數(shù)
{
uchar i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void WriteLcd(uchar Dat,bit x) //1602寫(xiě)函數(shù)(寫(xiě)指令時(shí)x=0,寫(xiě)數(shù)據(jù)時(shí)x=1)
{
LCD_EN=0;
LcdData=Dat;
LCD_RS=x;
LCD_RW=0;
LCD_EN=1;
Delayms(1);
LCD_EN=0;
}
void InitLcd(void) //1602初始化函數(shù)
{
WriteLcd(0x38,0); //功能設(shè)定(38H),8位數(shù)據(jù),2行顯示,5*7點(diǎn)陣
WriteLcd(0x0C,0); //顯示開(kāi)、關(guān)設(shè)定(0CH),開(kāi)顯示,不顯示光標(biāo),光標(biāo)不閃爍
WriteLcd(0x06,0); //輸入模式設(shè)定(06H),讀寫(xiě)一個(gè)字符后,地址指針加1,且光標(biāo)加1
WriteLcd(0x01,0); //清除顯示(01H),清除數(shù)據(jù)RAM中的數(shù)據(jù)
}
void DisplayLcd() //液晶屏顯示函數(shù)
{
uchar y;
V=(331.4+temp*0.607);
Line1[2]=temp/10+0x30;
Line1[3]=temp%10+0x30;
Line1[4]=0xDF; //顯示℃中C前面的小圓
Line1[10]=(uint)V/100+0x30;
Line1[11]=(uint)V%100/10+0x30;
Line1[12]=(uint)V%10+0x30;
if(flag_clear==1)
S1=0;
if((S1>=7000)||flag_flow==1) //超出測(cè)量范圍顯示“-”
{
flag_flow=0;
Line2[2]='-';
Line2[3]='.';
Line2[4]='-';
Line2[5]='-';
Line2[6]='-';
}
else
{
Line2[2]=S1/10;
Line2[2]=S1/1000+0x30;
Line2[3]='.';
Line2[4]=S1%1000/100+0x30;
Line2[5]=S1%100/10+0x30;
Line2[6]=S1%10+0x30;
}
WriteLcd(0x80,0); //設(shè)定第一行地址
for(y=0; y<16; y++)
WriteLcd(Line1[y],1);
WriteLcd(0xc0,0); //設(shè)定第二行地址
for(y=0; y<16; y++)
WriteLcd(Line2[y],1);
}
void init() //初始化函數(shù)
{
TMOD=0x01; //設(shè)T0為方式1,GATE=1;
TH0=0;
TL0=0;
ET0=1; //允許T0中斷
EA=1; //開(kāi)啟總中斷
}
void keyscan() //鍵掃描函數(shù)
{
if(Resets_Key==0) //復(fù)位清零鍵
{
Delayms(5);
if(Resets_Key==0)
{
while(Resets_Key==0);
flag_clear=1;
}
}
if(Single_Key==0) //單次測(cè)量鍵
{
Delayms(5);
if(Single_Key==0)
{
while(Single_Key==0);
flag_one=1;
flag_con1=0;
flag_con2=0;
flag_clear=0;
}
}
if(Contin_Key==0) //連續(xù)瞬時(shí)測(cè)量鍵
{
Delayms(5);
if(Contin_Key==0)
{
while(Contin_Key==0);
flag_con1=~flag_con1;
if(flag_con1==1)
{
flag_one=0;
flag_con2=0;
flag_clear=0;
}
}
}
if(Averag_Key==0) //連續(xù)平均測(cè)量鍵
{
Delayms(5);
if(Averag_Key==0)
{
while(Averag_Key==0);
flag_con2=~flag_con2;
if(flag_con2==1)
{
flag_one=0;
flag_con1=0;
flag_clear=0;
}
}
}
}
void StartModule() //啟動(dòng)模塊函數(shù)(觸發(fā)一次,提供大于10us的高電平)
{
Trig=1; //啟動(dòng)一次模塊
Delayus(15); //延時(shí)2i+5=35us
Trig=0;
}
void Conut(void) //測(cè)量計(jì)算函數(shù)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
V=(331.4+temp*0.607); //由溫度計(jì)算速度值,單位是m/s
S=(uint)(time*V/2000); //算出來(lái)是mm
if(flag_con2==1) //如果是連續(xù)測(cè)量,則取10次的平均值
{
if(k<=10)
k++;
if(k>=11)
k=1;
Sav[k]=S;
j++;
if(j<10)
S1=S;
if(j>=10)
{
j=10;
for(m=1;m<=10;m++)
totle=totle+Sav[m];
S1=(uint)(totle/10); //取10次的平均值
totle=0;
}
}
if(flag_one==1||flag_con1==1) //如果是單次測(cè)量或連續(xù)瞬時(shí)測(cè)量,則取1次的值
{
S1=S;
}
}
void Delayus(uchar xus) //晶振為12MHz,延時(shí)時(shí)間為2i+5 us
{
while(--xus);
}
bit Init_DS18B20(void)
{
bit x;
DQ=1;
DQ=0;
Delayus(250);
DQ=1;
Delayus(20);
if(!DQ) x=0;
else x=1;
Delayus(250);
DQ=1;
return x;
}
//讀DS18B20函數(shù)
uchar Read_DS18B20(void)
{
uchar i=0,Dat=0;
for(i=0;i<8;i++)
{
DQ=1;
DQ=0;
Dat>>=1;
DQ=1;
if(DQ) Dat |= 0x80;
DQ=1;
Delayus(30);
}
return Dat;
}
//寫(xiě)DS18B20函數(shù)
void Write_DS18B20(uchar Dat)
{
uchar i=0;
for(i=0;i<8;i++)//循環(huán)8次,寫(xiě)入一個(gè)字節(jié)
{
DQ=1;//未發(fā)送前的狀態(tài)
Dat >>= 1;//將要傳送的最低位放入CY
DQ=0;//將總線拉低,產(chǎn)生寫(xiě)時(shí)序
DQ=CY;//將要傳送的位狀態(tài)送到總線上
Delayus(30);//延時(shí)50us,即保持總線狀態(tài),待DS18B20采樣
DQ=1;//恢復(fù)期,總線置1
}
}
void GetTemp(void) //獲取溫度函數(shù)
{
uchar a=0,b=0;
Init_DS18B20();
Write_DS18B20(0xcc); //跳過(guò)ROM
Write_DS18B20(0x44); //開(kāi)啟溫度轉(zhuǎn)換
Init_DS18B20();
Write_DS18B20(0xcc); //跳過(guò)ROM
Write_DS18B20(0xbe); //讀暫存器
a=Read_DS18B20(); //讀取高速暫存字節(jié)0,溫度低8位
b=Read_DS18B20(); //讀取高速暫存字節(jié)1,溫度高8位
temp=b;
temp<<=8;
temp=temp|a; //將高、低位溫度編碼合在一起
if(b>=8) //判斷溫度值是否為負(fù),如果溫度高字節(jié)大于等于8說(shuō)明溫度值為負(fù)
{
temp=~temp+1; //將補(bǔ)碼轉(zhuǎn)換成原碼
Temp_Flag=1; //溫度標(biāo)志為1,表示溫度為負(fù)
}
else
{
Temp_Flag=0; //溫度標(biāo)志為0,表示溫度為正
}
temp=temp*0.0625+0.5;//將溫度編碼轉(zhuǎn)換成溫度值,加0.5是為了四舍五入
}
void CalcTestTemp() //溫度處理函數(shù)
{
if(temp<100) Line1[2]=' '; //如果溫度值小于10,十位顯示空白(不顯示0)
else Line1[2]=temp%100/10+0x30; //取溫度十位并轉(zhuǎn)換成ASCII碼
Line1[3]=temp%10+0x30; //取溫度個(gè)位并轉(zhuǎn)換成ASCII碼
}
|
|