主函數
#define uchar unsigned char
#define uint unsigned int
#define ULint unsigned long int
//溫度零上與零下的標志位
char flag=0;
//超聲波
char flags=0;
//超聲波距離
char flag1s=0;
//計算定時間
uint time=0;
//計算距離
//ULint L_=0;
uchar L=0;
//溫度
uint t_=0;
//顯示模式 0正常 1最大值調整 2最小值調整
uchar mode=0;
uint Max=150;
uint Min=5;
//按鍵標志
uchar k=0;
//數值有誤
uchar FW=0;
//頭函數
#include <reg52.h>
#include <intrins.h>
#include "BJ_Key.h" //報警按鍵
#include "display.h" //顯示頭函數
#include "ultrasonic_wave.h"//超聲波頭函數
#include "DS18B20.h" //溫度傳感器頭函數
//函數聲明
void delayms(uint ms);
//主函數
void main()
{
Init_ultrasonic_wave();
//屏幕初始化
Init1602();
//溫度初始化
tmpchange();
t_=tmp();
tmpchange();
t_=tmp();
tmpchange();
t_=tmp();
//循環顯示
while(1)
{
Key();
//正常顯示
if(mode==0)
{
StartModule();//啟動超聲波
while(!RX); //當RX為零時等待
TR0=1; //開啟計數
while(RX); //當RX為1計數并等待
TR0=0; //關閉計數
delayms(20); //20MS
tmpchange(); //溫度轉換
t_=tmp(); //度溫度
Conut(t_/10); //計算距離
if(L>Max||L<Min)
{
Feng_Start();
}
else
{
if(FW!=1)
Feng_Stop();
}
Display_1602(t_/10,L);
}
//調整顯示
else if(mode!=0)
{
//最大最小值
Init_MaxMin();
while(mode!=0)
{
Key();
if(k==1&&mode==1)
{
Init_MaxMin();
write_com(0x8d);//設置位置
}
else if(k==1&&mode==2)
{
Init_MaxMin();
write_com(0x8d+0x40);//設置位置
}
k=0;
}
//界面初始化
Init1602();
}}}
void delayms(uint ms)
{
uchar i=100,j;
for(;ms;ms--)
{
while(--i)
{
j=10;
while(--j);
}}}
//T0中斷用來計數器溢出,超過測距范圍
void CJ_T0() interrupt 1
{
flags=1; //中斷溢出標志
}
超聲波函.h
sbit RX=P2^1;
sbit TX=P2^0;
//超聲波初始化
void Init_ultrasonic_wave()
{
TX=0; //關閉發射
TMOD=0x01; //設T0為方式1,GATE=1;
TH0=0;
TL0=0;
ET0=1; //允許T0中斷
EA=1; //開啟總中斷
}
//啟動超聲波
void StartModule() //啟動模塊
{
TX=1; //啟動一
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TX=0;
}
//計算不同溫度下的速度
void JS_(uchar WD)
{
//大于-30
if(WD>=30&&flag==1)
{
L=(time*3.13)/200; //算出來是CM;
}
//大于-20<-30
else if(WD>=20&&WD<30&&flag==1)
{
L=(time*3.19)/200; //算出來是CM;
}
//大于-10<-20
else if(WD>=10&&WD<20&&flag==1)
{
L=(time*3.25)/200; //算出來是CM;
}
//大于0<-10
else if(WD>=0&&WD<10&&flag==1)
{
L=(time*3.23)/200; //算出來是CM;
}
//大于0<10
else if(WD<=10&&WD>0&&flag==0)
{
L=(time*3.38)/200; //算出來是CM;
}
//大于10<20
else if(WD<=20&&WD>10&&flag==0)
{
L=(time*3.34)/200; //算出來是CM;
}
//大于20<30
else if(WD<=30&&WD>20&&flag==0)
{
L=(time*3.49)/200; //算出來是CM;
}
//大于30
else if(WD>30&&flag==0)
{
L=(time*3.86)/200; //算出來是CM;
}
}
//距離計算 SD為當時的超聲速度
void Conut(uchar WD)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
JS_(WD);
//距離大于200或者超時
if(L>450||flags==1)
{
flags=0;
//無效顯示
flag1s=0;
L=0;
FW=1;
Feng_Start();
}
//距離小于100
else if(L<=150)
{
flag1s=1;
FW=1;
Feng_Stop();
}}
DS1820.h
#define uchar unsigned char
#define uint unsigned int
//define interface 定義 DS18B20 接口
sbit DS=P1^4;
//variable of temperature
uint temp=0;
//延時子函數
//sign of the result positive or
void delay(uint count)
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
} }
//發送初始化及復位信號
void dsreset(void)
{
//DS18B20 初始化
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
//read a bit 讀一位
bit tmpreadbit(void)
{
uint i;
bit dat;
//i++ for delay 小延時一下
DS=0;i++;
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
//read a byte date 讀一個字節
uchar tmpread(void)
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
//讀出的數據最低位在最前面,這樣剛好
//一個字節在 dat 里
dat=(j<<7)|(dat>>1);
}
//將一個字節數據返回
return(dat);
}
//write a byte to ds18b20
//寫一個字節到 DS18B20 里
void tmpwritebyte(uchar dat)
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //write 1 寫 1 部分
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //write 0 寫 0 部分
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
//DS18B20 begin change 發送溫度轉換命令
void tmpchange(void)
{
dsreset(); //初始化 DS18B20
delay(1); //延時
tmpwritebyte(0xcc); //跳過序列號命令
tmpwritebyte(0x44); //發送溫度轉換命令
}
//get the temperature 獲得溫度
uint tmp()
{
float tt=0;
uchar a=0,b=0;
dsreset();
delay(1);
//發送讀取數據命令
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
//連續讀兩個字節數據
a=tmpread();
b=tmpread();
//two byte compose a int variable
//兩字節合成一個整型變量。
temp=b;
temp<<=8; //temp=temp<<=8 左移8位
temp=temp|a;
if(b==0xff)
{
flag=1;
temp=~temp+1; //負溫度表示 取補碼
}
//得到真實十進制溫度值,因為 DS18B20
tt=temp*0.0625;
//可以精確到 0.0625 度,所以讀回數據的最低位代表的是
//0.0625 度。
//放大十倍,這樣做的目的將小數點后第一位
temp=tt*10+0.5;
//也轉換為可顯示數字,同時進行一個四舍五入操作。
//返回溫度值
return temp;
}
display.h
sbit LCDRS = P2^7;
sbit LCDEN= P2^6;
//初始畫時顯示的內容
uchar code Init1[]="Temperature: C";
uchar code Init2[]="Distance:0000 CM";
//初始畫時顯示的內容
uchar code Init3[]=" Max------ CM";
uchar code Init4[]=" Min------ CM";
//LCD延時
void LCDdelay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=10;y>0;y--);
}
//寫命令
void write_com(uchar com)
{
LCDRS=0;
P0=com;
LCDdelay(5);
LCDEN=1;
LCDdelay(5);
LCDEN=0;
}
//寫數據
void write_data(uchar date)
{
LCDRS=1;
P0=date;
LCDdelay(5);
LCDEN=1;
LCDdelay(5);
LCDEN=0;
}
//1602初始化
void Init1602()
{
uchar i=0;
write_com(0x38);//屏幕初始化
write_com(0x0C);//打開顯示 無光標 無光標閃爍
write_com(0x06);//當讀或寫一個字符是指針后一一位
write_com(0x01);//清屏
write_com(0x80);//設置位置
for(i=0;i<14;i++)
{
write_data(Init1[i]);
}
write_data(0xdf);
write_data(Init1[14]);
write_com(0x80+0x40);//設置位置
for(i=0;i<16;i++)
{
write_data(Init2[i]);
}}
//溫度 距離顯示
void Display_1602(uchar W,uchar L)
{
//溫度值顯示
write_com(0x80+12);
write_data('0'+W/10);
write_data('0'+W%10);
if(L>=100)
{
write_com(0x80+0x40+0x09);
write_data(((L*10)/1000)+0x30); //百
write_data(((L*10)%1000/100)+0x30); //十
write_data(((L*10)%100/10)+0x30); //個
write_data(0x2e); //點
write_data(((L*10)%10)+0x30); //小數位1
}
else if(L>=10 && L<100)
{
write_com(0x80+0x40+0x09);
write_data((L*10/100)+0x30); //十
write_data((L*10%100/10)+0x30); //個
write_data(0x2e); //點
write_data((L*10%10)+0x30); //小數位1
}
else if(L>=0 && L<10)
{
write_com(0x80+0x40+0x09);
write_data((L*10/10)+0x30); //個
write_data(46); //點
write_data((L*10%10)+0x30); //小數位1
}
else if(flag1s==0)
{
write_com(0x80+0x40+0x0a);
write_data('-');
write_data('-');
write_data('-');
write_data('-');
}}
//1602初始化最大化最小化調整界面
void Init_MaxMin()
{
uchar i=0;
write_com(0x38);//屏幕初始化
write_com(0x0f);//打開顯示 無光標 無光標閃爍
write_com(0x06);//當讀或寫一個字符是指針后一一位
write_com(0x01);//清屏
write_com(0x80);//設置位置
for(i=0;i<16;i++)
{
write_data(Init3[i]);
}
write_com(0x80+0x40);//設置位置
for(i=0;i<16;i++)
{
write_data(Init4[i]);
}
write_com(0x8b);//設置位置
write_data('0'+Max/100);
write_data('0'+Max/10%10);
write_data('0'+Max%10);
write_com(0x80+0x40+0x0b);//設置位置
write_data('0'+Min/100);
write_data('0'+Min/10%10);
write_data('0'+Min%10);
write_com(0x8d);//設置位置
}
key.h
sbit Feng=P1^0;
sbit K1=P1^1;
sbit K2=P1^2;
sbit K3=P1^3;
//蜂鳴打開
void Feng_Start()
{
Feng=0;
}
//蜂鳴關閉
void Feng_Stop()
{
Feng=1;
}
//等待
void delay_key()
{
uchar i,j;
for(i=0;i<200;i++)
for(j=0;j<200;j++);
}
//按鍵檢測
void Key()
{
//功能鍵按下
if(K1==0)
{
Feng_Start();//蜂鳴器開
delay_key(); //消抖
while(K1==0);//等待松手
Feng_Stop(); //蜂鳴器關閉
mode++; //模式++
if(mode==3) //達到最大限度歸為
mode=0;
k=1; //按鍵標志位
}
//+鍵
else if(K2==0)
{
Feng_Start();//蜂鳴器開
delay_key(); //消抖
while(K2==0);//等待松手
Feng_Stop(); //蜂鳴器關閉
//最大值調整
if(mode==1) //在最大值調整下
{
Max++; //調整最大值
if(Max==201)//到達201歸為200
{
Max=200;
}
}
//最小值
else if(mode==2)//最小模式下調整
{
Min++; //調整最小值
if(Min>Max) //最小值不能大于最大值
{
Min=Max;
}
}
k=1;
}
//-鍵
else if(K3==0)
{
Feng_Start();
delay_key();
while(K3==0);
Feng_Stop();
//最大值調整
if(mode==1)
{
Max--;
if(Max<Min)
{
Max=Min;
}
}
//最小值
else if(mode==2)
{
Min--;
if(Min==0xff)
{
Min=0;
}
}
k=1;
}
} |