#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
/*======LCD位定義==========*/
sbit RS=P2^6;
sbit RW=P2^5;
sbit E=P2^7;
sfr LCDData=0x80;
/*按鍵定位*/
sbit set = P1^4;//調(diào)時按鍵移位
sbit jia = P1^5;//加一按鍵
sbit jian = P1^6;//減一按鍵
sbit back = P1^7;//退出調(diào)時按鍵
/*蜂鳴器定位*/
sbit BEEP = P2^0;
/*熱釋電紅外檢測定位*/
sbit HW_check = P2^1;
/*指示燈定位*/
sbit LED_ZG = P3^2; //遮光指示燈
sbit LED_BG = P3^3; //補光指示燈
sbit LED_ZL = P3^4; //制冷指示燈
sbit LED_JR = P3^5; //加熱指示燈
sbit LED_ZS = P3^6; //增濕指示燈
sbit LED_GZ = P3^7; //干燥指示燈
/*光照強度檢測,AD轉(zhuǎn)換芯片引腳定位*/
unsigned char Read_ADC0832(unsigned char Ch);
sbit ADC0832_CS =P1^0; //將CS位定義為P2.5引腳
sbit ADC0832_CLK=P1^1; //將CLK位定義為P2.6引腳
sbit ADC0832_DIO=P1^2; //將DIO位定義為P2.7引腳
uchar AD_Value=0;
uchar result,result0;/*存放測試結(jié)果*/
uchar count;
bit flash; //刷新頻率參數(shù)
sbit TRH = P2^2; //溫濕度傳感器DHT11數(shù)據(jù)接入
uchar TH_data,TL_data,TH,TL,RH_data,RH_data0,RL_data,CK_data;
uchar TH_temp,TL_temp,RH_temp,RL_temp,CK_temp;
uchar com_data,untemp,temp;
uchar respond;
uchar T_SETDOWN,T_SETTOP,R_SETDOWN,R_SETTOP,L_SETDOWN, L_SETTOP;//溫濕度光照強度最大最小值
/***液晶驅(qū)動******/
void Delay(uint i)
{while(i--);}
// 毫秒級延時子程序
/*********************************************************************************/
void delay_ms(unsigned char ms)
{
unsigned char i;
while(ms--)
{
for(i = 0; i< 150; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/****************************************************************************/
//收發(fā)信號檢測,數(shù)據(jù)讀取
/****************************************************************************/
//5us級延時程序
/*********************************************************************************/
void delay_5us()
{
uchar i;
i--;
i--;
i--;
i--;
i--;
i--;
}
char receive()
{
uchar i;
com_data=0;
for(i=0;i<=7;i++)
{
respond=2;
while((!TRH)&&respond++);
delay_5us();
delay_5us();
delay_5us();
if(TRH)
{
temp=1;
respond=2;
while((TRH)&&respond++);
}
else
temp=0;
com_data<<=1;
com_data|=temp;
}
return(com_data);
}
/**********溫濕度檢測程序*********/
//溫度高8位== TL_data,溫度低8位== TH_data,濕度高8位== RH_data,濕度低8位== RH_data,校驗 8位 == CK_data
void read_TRH()
{
//主機拉低18ms
TRH=0;
delay_ms(18);
TRH=1;
//DATA總線由上拉電阻拉高 主機延時20us
delay_5us();
delay_5us();
delay_5us();
delay_5us();
//delay_us();
//delay_us();delay_us();delay_us();delay_us();
//主機設(shè)為輸入 判斷從機響應信號
TRH=1;
//判斷DHT11是否有低電平響應信號 如不響應則跳出,響應則向下運行
if(!TRH)
{
respond=2; //判斷DHT11發(fā)出 80us 的低電平響應信號是否結(jié)束
while((!TRH)&& respond++);
respond=2; //判斷從機是否發(fā)出 80us 的高電平,如發(fā)出則進入數(shù)據(jù)接收狀態(tài)
while(TRH && respond++); //數(shù)據(jù)接收狀態(tài)
RH_temp = receive();
RL_temp = receive();
TH_temp = receive();
TL_temp = receive();
CK_temp = receive();
TRH=1; //數(shù)據(jù)校驗
untemp=(RH_temp+RL_temp+TH_temp+TL_temp);
if(untemp==CK_temp)
{
RH_data = RH_temp; //濕度整數(shù)部分
// RL_data = RL_temp; //濕度小數(shù)部分
TH_data = TH_temp; //溫度整數(shù)部分
// TL_data = TL_temp; //溫度小數(shù)部分
CK_data = CK_temp;
}
}
}
/*********************************************************************************/
void Write_Instruction(uchar x)
{
Delay(1000);
E=0;
RW=0;
RS=0;
LCDData=x;
E=1;
Delay(20);
E=0;
}
void Write_Data(uchar x)
{
Delay(1000);
E=0;
RW=0;
RS=1;
E=1;
LCDData=x;
E=0;
}
void InitLCD(void)
{
Write_Instruction(0x38);
Delay(200);
Write_Instruction(0x0e);
Delay(200);
Write_Instruction(0x06);
Delay(200);
}
void Write_String(uchar x,uchar *p)
{ Write_Instruction(x);
while(*p!=0x00)
{ Write_Data(*p);
p++;
if (x++==0x8f)
{ Write_Instruction(0xc0);}
}
}
void Write_t(uchar i,uchar k)//數(shù)據(jù)寫入
{
Write_Instruction(i);
Write_Data(k|0x30);
}
void Write_d(uchar i,uchar k)//℃寫入
{
Write_Instruction(i);
Write_Data(k);
}
/****************************************************************************/
/****數(shù)據(jù)顯示*****/
void Display( uchar y,uchar x )
{
Write_t(y+0,(x/10)|0x30);
Write_t(y+1,(x%10)|0x30);
}
/****按鍵檢測*****/
void key_test( )
{
uchar place,num,number,x;
place=0x8b;
number = R_SETDOWN;
num = 1;
x=1;
while(num!=0)
{
if(set==0)
{
delay_ms(5);
if(set==0)
{
x++;
if(x>6)x=1;
while(!set);
switch(x)
{
case 1:{
Write_Instruction(0x01);//清屏
Write_String(0x80,"R:");
Write_String(0xc0,"T:");
Write_String(0x84,"%R");
Write_d(0xc4,0xdf); //顯示℃
Write_String(0xc5,"C");
Write_String(0x87,"SET:");
Write_String(0xc7,"SET:");
Write_String(0x8d,"-");
Write_String(0xcd,"-");
Display(0x8b,R_SETDOWN);
Display(0x8e,R_SETTOP);
Display(0xcb,T_SETDOWN);
Display(0xce,T_SETTOP);
Display(0x82,RH_data);
Display(0xc2,TH_data);
place=0x8b; number = R_SETDOWN;
break; }
case 2:{ place=0x8e; number = R_SETTOP; break; }
case 3:{ place=0xcb; number = T_SETDOWN; break; }
case 4:{ place=0xce; number = T_SETTOP; break; }
case 5:{
Write_Instruction(0x01);//清屏
Write_String(0x80,"L:");
Write_String(0x84,"Lx");
Write_String(0x87,"SET:");
Display(0x8b,L_SETDOWN);
Write_String(0x8d,"-");
Display(0x8e,L_SETTOP);
Display(0x82,result);
place=0x8b; number = L_SETDOWN;
break; }
case 6:{ place=0x8e; number = L_SETTOP; break; }
default:{ break; }
}
}
}
Write_Instruction( place+1 );
if(jia==0||jian==0)
{
if(jia==0)
{
delay_ms(5);
if(jia==0)
{
while(!jia);
number++;
if(number>99)number=0;
Display(place,number);
}
}
if(jian==0)
{
delay_ms(5);
if(jian==0)
{
while(!jian);
if(number==0)
{
number=99;
goto ap;
}
number--;
ap: Display(place,number);
}
}
switch(x)
{
case 1:{ R_SETDOWN = number; break; }
case 2:{ R_SETTOP = number; break; }
case 3:{ T_SETDOWN = number; break; }
case 4:{ T_SETTOP = number; break; }
case 5:{ L_SETDOWN = number; break; }
case 6:{ L_SETTOP = number; break; }
default: break;
}
}
if(back==0)
{
delay_ms(5);
if(back==0)
{
num=0;
while(!back);
TR1=1;
}
}
}
}
/**********************AD轉(zhuǎn)換**********************************************
* 名稱 : dRead_ADC0832()
* 功能 : 將模擬信號轉(zhuǎn)換成數(shù)字信號
* 輸入 : Ch-通道選擇
* 輸出 : dat-轉(zhuǎn)換值
*********************************************************************/
unsigned char Read_ADC0832(unsigned char Ch)
{
unsigned char i,dat; //定義變量
ADC0832_CS=1; //一個轉(zhuǎn)換周期開始
ADC0832_CLK=0; //為第一個脈沖作準備
ADC0832_CS=0; //CS置0,片選有效
ADC0832_DIO=1; //DIO置1,規(guī)定的起始信號
ADC0832_CLK=1; //第一個脈沖
ADC0832_CLK=0; //第一個脈沖的下降沿,此前DIO必須是高電平
ADC0832_DIO=1; //DIO置1, 通道選擇信號
ADC0832_CLK=1; //第二個脈沖,第2、3個脈沖下沉之前,DI必須跟別輸入兩位數(shù)據(jù)用于選擇通道,這里選通道CH0
ADC0832_CLK=0; //第二個脈沖下降沿
ADC0832_DIO=Ch; //DI置0,選擇通道0
ADC0832_CLK=1; //第三個脈沖
ADC0832_CLK=0; //第三個脈沖下降沿
ADC0832_DIO=1; //第三個脈沖下沉之后,輸入端DIO失去作用,應置1
ADC0832_CLK=1; //第四個脈沖
for(i=0;i<8;i++) //高位在前
{
ADC0832_CLK=1; //第四個脈沖
ADC0832_CLK=0;
dat<<=1; //將下面儲存的低位數(shù)據(jù)向右移
dat|=(unsigned char)ADC0832_DIO; //將輸出數(shù)據(jù)DIO通過或運算儲存在dat最低位
}
ADC0832_CS=1; //片選無效
return dat; //將讀書的數(shù)據(jù)返回
}
/****初始化子函數(shù)*****/
void init() //通過定時器模擬PWM輸出程序,控制電機的轉(zhuǎn)速
{
TMOD=0x10; //設(shè)置單片機定時器工作方式
EA=1; //打開單片機總中斷
ET1=1; //定時器T1中斷允許
count=0;
TH1=(65536-43863)/256; //定時器T1的高8位設(shè)置初值,每50ms產(chǎn)生一次中斷
TL1=(65536-43863)%256; //定時器T1的低8位設(shè)置初值,每50ms產(chǎn)生一次中斷
TR1=0; //關(guān)閉定時器T1
// 。
}
/****************************************************************************/
//主函數(shù)
//TH,TL,RH,RL分別代表溫濕度的整數(shù)和小數(shù)部分
void main()
{
uchar n;
BEEP=0;
R_SETDOWN = 40;
R_SETTOP = 70;
T_SETDOWN = 20;
T_SETTOP = 40;
L_SETDOWN=5;
L_SETTOP=40;
InitLCD(); //液晶初始化
init(); //定時器初始化
Write_Instruction(0x0c); //關(guān)光標
TR1=1;
while(1)
{
if(HW_check==0) { BEEP=1; } //熱釋電紅外未檢測到人體信號
else { BEEP=0; } //熱釋電紅外檢測到人體信號
if(count==0)
{
if(flash==0) //第一屏顯示濕度、溫度
{
Write_Instruction(0x01); //清屏
Write_String(0x80,"R:");
Write_String(0xc0,"T:");
Write_String(0x84,"%R");
Write_d(0xc4,0xdf); //顯示℃
Write_String(0xc5,"C");
Write_String(0x87,"SET:");
Write_String(0xc7,"SET:");
Write_String(0x8d,"-");
Write_String(0xcd,"-");
Display(0x8b,R_SETDOWN); //顯示濕度下限
Display(0x8e,R_SETTOP); //顯示濕度上限
Display(0xcb,T_SETDOWN); //顯示溫度下限
Display(0xce,T_SETTOP); //顯示溫度上限
read_TRH(); //啟動溫濕度傳感器檢測
}
else //第二屏顯示光照強度
{
Write_Instruction(0x01); //清屏
Write_String(0x80,"L:");
Write_String(0x84,"Lx");
Write_String(0x87,"SET:");
Display(0x8b,L_SETDOWN); //顯示光照強度下限
Write_String(0x8d,"-");
Display(0x8e,L_SETTOP); //顯示光照強度上限
}
TR1=1;
}
RH_data=RH_data; //獲取濕度
if( RH_data<=R_SETDOWN ) { LED_ZS=0; LED_GZ=1;} //濕度低,增濕啟動
else if( RH_data>=R_SETTOP ){ LED_ZS=1; LED_GZ=0;} //濕度高,干燥啟動
else { LED_ZS=1; LED_GZ=1; } //濕度合適,停止增濕,停止干燥
TH_data=TH_data; //獲取溫度
if( TH_data<=T_SETDOWN ) { LED_JR=0; LED_ZL=1;} //溫度低,加熱啟動
else if( TH_data>=T_SETTOP ){ LED_JR=1; LED_ZL=0;} //溫度高,制冷啟動
else { LED_JR=1; LED_ZL=1; } //溫度合適,停止加熱,停止制冷
for(n=1;n<7;n++)
{
AD_Value = Read_ADC0832(0); //獲取光照強度
result0=(uchar)(((float)AD_Value+5)*50/251);
result=result+result0;
}
result=result/6;
if(result<=38)result=38-result;
else result=0;
if( result<=L_SETDOWN) { LED_BG=0;LED_ZG=1; } //光照強度值低,啟動照明補光
else if(result>=L_SETTOP) { LED_BG=1;LED_ZG=0;}
else {LED_BG=1;LED_ZG=1;}
if(flash==0)
{
Display(0x82,RH_data); //顯示濕度
Display(0xc2,TH_data); //顯示溫度
}
else
{
Display(0x82,result); //顯示光照強度
}
if(jia==0) //在輪流顯示模式,按【加】按鍵可以保持顯示模式,按多一次取消保持顯示模式
{
delay_ms(5);
if(jia==0)
{
while(!jia);
TR1=~TR1;
}
}
if(set==0)
{
delay_ms(5);
if(set==0)
{
while(!set);
Write_Instruction(0x0f); //開光標
TR1=0;
Write_Instruction(0x01);//清屏
Write_String(0x80,"R:");
Write_String(0xc0,"T:");
Write_String(0x84,"%R");
Write_d(0xc4,0xdf); //顯示℃
Write_String(0xc5,"C");
Write_String(0x87,"SET:");
Write_String(0xc7,"SET:");
Write_String(0x8d,"-");
Write_String(0xcd,"-");
Display(0x8b,R_SETDOWN);
Display(0x8e,R_SETTOP);
Display(0xcb,T_SETDOWN);
Display(0xce,T_SETTOP);
Display(0x82,RH_data);
Display(0xc2,TH_data);
key_test();
Write_Instruction(0x0c); //關(guān)光標
}
}
}
}
/*******************************************************
函數(shù)功能:定時器T1的中斷服務函數(shù)
********************************************************/
void Time1() interrupt 3 using 2 //定時器T1的中斷編號為3,使用第2組工作寄存器
{
count++; //T1每中斷1次,count加1
if(count==50) //若累計滿20次,即計滿1秒鐘
{
count=0;
flash=~flash;
TR1=0;
}
TH1=(65536-43863)/256; //定時器T1高8位賦初值
TL1=(65536-43863)%256; //定時器T1低8位賦初值
}
|