單片機源程序如下:
- //程序頭函數
- #include <reg52.h>
- //顯示函數
- #include "intrins.h"
- //宏定義
- #define uint unsigned int
- #define uchar unsigned char
- //宏定義
- #define uint unsigned int
- #define uchar unsigned char
- //管腳聲明
- sbit LED_wendu = P2^5; //溫度上限值操作端口,報警燈吸合繼電器;
- sbit LED_wendu_L = P2^4; //溫度下限報警燈
- sbit LED_humi = P2^2; //濕度上限報警燈
- sbit LED_humi_L = P2^0; //濕度下限報警燈
- sbit baojing = P3^2; //蜂鳴器接口
- //按鍵
- sbit Key1=P1^1; //設置鍵
- sbit Key2=P1^5; //加按鍵
- sbit Key3=P1^6; //減按鍵
- sbit DHT11=P1^0; //DHT11
- signed char w; //溫度值全局變量
- uint c; //溫度值全局變量
- uchar temp; //用于讀取ADC數據
- uchar yushe_wendu=60; //溫度預設值
- uchar yushe_humi=80; //濕度預設值
- uchar yushe_wendu_L=05; //溫度預設值
- uchar yushe_humi_L=10; //濕度預設值
- //按鈕模式|
- uchar Mode=0;
- uchar U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
- uchar U8FLAG,U8comdata;
- uchar U8count,U8temp;
- uchar U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
- //軟件延時函數
- void delay(uint z) //延時函數大約延時z ms
- {
- uint i,j;
- for(i=0;i<z;i++)
- for(j=0;j<121;j++);
- }
- void Delay_Ms(uint ms)
- {
- uint i,j;
- for(i=ms;i>0;i--)
- for(j=112;j>0;j--);
- }
-
-
- /*******************************************************************************************************
- LCD1602相關命令
- ********************************************************************************************************/
- //LCD管腳聲明 (RW引腳實物直接接地,因為本設計只用到液晶的寫操作,RW引腳一直是低電平)
- sbit LCDRS = P2^7;
- sbit LCDEN = P2^6;
- //初始畫時顯示的內容
- uchar code Init1[]="TA= L H ";
- uchar code Init2[]="RH= % L % H %";
- //LCD延時
- void LCDdelay(uint z) //該延時大約100us(不精確,液晶操作的延時不要求很精確)
- {
- 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<16;i++)
- {
- write_data(Init1[i]); //顯示數組1的數據
- }
- write_com(0x80+5);
- write_data(0xdf);//°
- write_com(0x80+10);
- write_data(0xdf);//°
- write_com(0x80+15);
- write_data(0xdf);//°
-
- write_com(0x80+0x40);//設置位置
- for(i=0;i<16;i++)
- {
- write_data(Init2[i]); //顯示數組2的數據
- }
-
- }
- void Display_1602(yushe_wendu,yushe_yanwu,yushe_wendu_L,yushe_yanwu_L,c,temp)
- {
- //設置最高溫度值
- write_com(0x80+13);
- write_data(0x30+yushe_wendu/10);
- write_data(0x30+yushe_wendu%10);
- //設置最低溫度值
- write_com(0x80+8);
- write_data(0x30+yushe_wendu_L/10);
- write_data(0x30+yushe_wendu_L%10);
- //設置最高濕度值
- write_com(0x80+0x40+13);
- write_data(0x30+yushe_yanwu%100/10);
- write_data(0x30+yushe_yanwu%10);
- //設置最低濕度值
- write_com(0x80+0x40+8);
- write_data(0x30+yushe_yanwu_L%100/10);
- write_data(0x30+yushe_yanwu_L%10);
- //時時溫度
- write_com(0x80+3);
- write_data(0x30+c%100/10);
- write_data(0x30+c%10);
-
- //時時濕度
- write_com(0x80+0x40+3);
- write_data(0x30+temp%100/10);
- write_data(0x30+temp%10);
- }
- //按鍵處理函數
- void Key()
- {
- //模式選擇
- if(Key1==0) //設置按鍵
- {
- while(Key1==0);
- if(Mode>=5) Mode=0;
- else
- {
- Mode++; //模式加一
- switch(Mode) //判斷模式的值
- {
- case 1://調溫度上限值模式
- {
- write_com(0x80+12);//為1時 溫度閥值的位置閃爍
- write_data('-');
- write_com(0x80+0x40+12);//為2時 濕度閥值的位置閃爍
- write_data('H');
- write_com(0x80+7);//為1時 溫度閥值的位置閃爍
- write_data('L');
- write_com(0x80+0x40+7);//為2時 濕度閥值的位置閃爍
- write_data('L');
- break; //執行后跳出switch
- }
- case 2://調濕度上限值模式
- {
- write_com(0x80+0x40+12);//為2時 濕度閥值的位置閃爍
- write_data('-');
- write_com(0x80+12);//為1時 溫度閥值的位置閃爍
- write_data('H');
- write_com(0x80+7);//為1時 溫度閥值的位置閃爍
- write_data('L');
- write_com(0x80+0x40+7);//為2時 濕度閥值的位置閃爍
- write_data('L');
- break;
- }
- case 3://調溫度下限值模式
- {
- write_com(0x80+7);//為1時 溫度閥值的位置閃爍
- write_data('-');
- write_com(0x80+12);//為1時 溫度閥值的位置閃爍
- write_data('H');
- write_com(0x80+0x40+12);//為2時 濕度閥值的位置閃爍
- write_data('H');
- write_com(0x80+0x40+7);//為2時 濕度閥值的位置閃爍
- write_data('L');
- break; //執行后跳出switch
- }
- case 4://調濕度下限值模式
- {
- write_com(0x80+0x40+7);//為2時 濕度閥值的位置閃爍
- write_data('-');
- write_com(0x80+12);//為1時 溫度閥值的位置閃爍
- write_data('H');
- write_com(0x80+0x40+12);//為2時 濕度閥值的位置閃爍
- write_data('H');
- write_com(0x80+7);//為1時 溫度閥值的位置閃爍
- write_data('L');
- break;
- }
- case 5: //當模式加到3時
- {
- write_com(0x38);//屏幕初始化
- write_com(0x0c);//打開顯示 無光標 無光標閃爍
- write_com(0x80+12);//為1時 溫度閥值的位置閃爍
- write_data('H');
- write_com(0x80+0x40+12);//為2時 濕度閥值的位置閃爍
- write_data('H');
- write_com(0x80+7);//為1時 溫度閥值的位置閃爍
- write_data('L');
- write_com(0x80+0x40+7);//為2時 濕度閥值的位置閃爍
- write_data('L');
- Mode=0; //模式清零
- break;
- }
- }
- }
- }
- if(Key2==0&&Mode!=0) //加按鍵只有在模式不等于0時有效
- {
- while(Key2==0);
- switch(Mode) //加按鍵按下時 判斷當前模式
- {
- case 1: //模式為1時
- {
- yushe_wendu++; //預設溫度上限值(閥值)加1
- if(yushe_wendu>=99) //加到大于等于99時
- yushe_wendu=99; //固定為99
- write_com(0x80+13); //選1602上顯示的位置
- write_data(0x30+yushe_wendu/10); //將溫度上限值數據分解開送入液晶顯示
- write_data(0x30+yushe_wendu%10);
- break;
- }
- case 2:
- {
- yushe_humi++; //濕度上限值,同溫度上限值設置
- if(yushe_humi>=100)
- yushe_humi=100;
- write_com(0x80+0x40+13);
- write_data(0x30+yushe_humi%100/10);
- write_data(0x30+yushe_humi%10);
- break;
- }
- case 3: //模式為3時
- {
- yushe_wendu_L++; //溫度下限值,同溫度上限值設置
- if(yushe_wendu_L>=95)
- yushe_wendu_L=95;
- write_com(0x80+8);
- write_data(0x30+yushe_wendu_L/10);
- write_data(0x30+yushe_wendu_L%10);
- break;
- }
- case 4:
- {
- yushe_humi_L++; //濕度下限值,同溫度上限值設置
- if(yushe_humi_L>=90)
- yushe_humi_L=90;
- write_com(0x80+0x40+8);
- write_data(0x30+yushe_humi_L%100/10);
- write_data(0x30+yushe_humi_L%10);
- break;
- }
- }
- }
- if(Key3==0&&Mode!=0)
- {
- while(Key3==0);
- switch(Mode)
- {
- case 1:
- {
- if(yushe_wendu<=1) //當溫度上限值減小到1時
- yushe_wendu=1; //固定為1
- yushe_wendu--; //預設溫度值減一
- write_com(0x80+13); //選1602上顯示的位置
- write_data(0x30+yushe_wendu/10); //將溫度上限值數據分解開送入液晶顯示
- write_data(0x30+yushe_wendu%10);
- break;
- }
- case 2:
- {
- if(yushe_humi<=1) //濕度上限值,同溫度上限值設置
- yushe_humi=1;
- yushe_humi--;
- write_com(0x80+0x40+13);
- write_data(0x30+yushe_humi%100/10);
- write_data(0x30+yushe_humi%10);
- break;
- }
- case 3: //模式為3時
- {
- if(yushe_wendu_L<=1) //溫度下限值,同溫度上限值設置
- yushe_wendu_L=1;
- yushe_wendu_L--;
- write_com(0x80+8);
- write_data(0x30+yushe_wendu_L/10);
- write_data(0x30+yushe_wendu_L%10);
- break;
- }
- case 4:
- {
- if(yushe_humi_L<=1) //濕度下限值,同溫度上限值設置
- yushe_humi_L=1;
- yushe_humi_L--;
- write_com(0x80+0x40+8);
- write_data(0x30+yushe_humi_L%100/10);
- write_data(0x30+yushe_humi_L%10);
- break;
- } }
- }
- delay(10); //延時去抖動
- write_com(0x38);//屏幕初始化
- write_com(0x0c);//打開顯示 無光標 無光標閃爍
- }
- /*******************************************************************************************************
- DHT11相關命令
- ********************************************************************************************************/
- void Delay1(uint j)
- {
- uchar i;
- for(;j>0;j--)
- {
- for(i=0;i<27;i++);
- }
- }
- void Delay_10us(void)
- {
- uchar i;
- i--;
- i--;
- i--;
- i--;
- i--;
- i--;
- }
- void COM(void)
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- U8FLAG=2;
- while((!DHT11)&&U8FLAG++);
- Delay_10us();
- Delay_10us();
- Delay_10us();
- U8temp=0;
- if(DHT11)U8temp=1;
- U8FLAG=2;
- while((DHT11)&&U8FLAG++);
- //超時則跳出for循環
- if(U8FLAG==1)break;
- //判斷數據位是0還是1
- // 如果高電平高過預定0高電平值則數據位為 1
- U8comdata<<=1;
- U8comdata|=U8temp; //
- }
- }
- //--------------------------------
- //-----濕度讀取子程序 ------------
- //--------------------------------
- //----以下變量均為全局變量--------
- //----溫度高8位== U8T_data_H------
- //----溫度低8位== U8T_data_L------
- //----濕度高8位== U8RH_data_H-----
- //----濕度低8位== U8RH_data_L-----
- //----校驗 8位 == U8checkdata-----
- //----調用相關子程序如下----------
- //---- Delay();, Delay_10us();,COM();
- //--------------------------------
- void RH(void)
- {
- //主機拉低18ms
- DHT11=0;
- Delay1(180);
- ET0 = 0;//關閉定時器0中斷
- DHT11=1;
- //總線由上拉電阻拉高 主機延時20us
- Delay_10us();
- Delay_10us();
- Delay_10us();
- Delay_10us();
- //主機設為輸入 判斷從機響應信號
- DHT11=1;
- //判斷從機是否有低電平響應信號 如不響應則跳出,響應則向下運行
- if(!DHT11) //T !
- {
- U8FLAG=2;
- //判斷從機是否發出 80us 的低電平響應信號是否結束
- while((!DHT11)&&U8FLAG++);
- U8FLAG=2;
- //判斷從機是否發出 80us 的高電平,如發出則進入數據接收狀態
- while((DHT11)&&U8FLAG++);
- //數據接收狀態
- COM();
- U8RH_data_H_temp=U8comdata;
- COM();
- U8RH_data_L_temp=U8comdata;
- COM();
- U8T_data_H_temp=U8comdata;
- COM();
- U8T_data_L_temp=U8comdata;
- COM();
- U8checkdata_temp=U8comdata;
- DHT11=1;
- ET0 = 1;//開啟定時器0中斷
- //數據校驗
- U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
- if(U8temp==U8checkdata_temp)
- {
- U8RH_data_H=U8RH_data_H_temp;
- U8RH_data_L=U8RH_data_L_temp;
- U8T_data_H=U8T_data_H_temp;
- U8T_data_L=U8T_data_L_temp;
- U8checkdata=U8checkdata_temp;
- }//
- }//
- }
-
- /*****主函數*****/
- void main()
- {
- uint i=0;
- Delay_Ms(100);//上電延時100ms,等待DHT11啟動
- Init1602(); //調用初始化顯示函數
- U8T_data_H=30;
- U8RH_data_H=60;
- while(1) //進入循環
- {
- Key(); //調用按鍵函數 掃描按鍵
- if(Mode==0) //只有當模式為0時才會執行以下的閥值判斷部分
- {
- if(i<1)
- {
- i=10;
- RH();//溫濕度檢測
- }
- i--;
- Display_1602(yushe_wendu,yushe_humi,yushe_wendu_L,yushe_humi_L,U8T_data_H,U8RH_data_H);
- //顯示預設溫度上限值,預設濕度上限值,預設溫度下限值,預設濕度下限值,當前溫度值,當前濕度值
- if(U8RH_data_H>=yushe_humi) //濕度值大于等于預設上限值時
- {
- LED_humi=0; //濕度上限繼電器
- baojing=0; //蜂鳴器報警
- }
- else if(U8RH_data_H<=yushe_humi_L) //濕度值小于等于預設值下限值時
- {
- LED_humi_L=0; //濕度下限繼電器
- baojing=0; //蜂鳴器報警
- }
- else //濕度值處于上限界限之間時
- {
- LED_humi=1; //關掉濕度上限繼電器
- LED_humi_L=1; //關掉濕度下限繼電器
- }
- if(U8T_data_H>=(yushe_wendu)) //溫度值大于等于預設上限值時
- {
- baojing=0; //打開蜂鳴器報警
- LED_wendu=0; //打開溫度上限繼電器
- }
- else if(U8T_data_H<=yushe_wendu_L) //溫度值小于等于預設值下限值時
- {
- LED_wendu_L=0; //溫度下限繼電器
- baojing=0; //蜂鳴器報警
- }
- else //溫度值處于上限界限之間時
- {
- LED_wendu=1; //關閉溫度上限繼電器
- LED_wendu_L=1; //關閉溫度下限繼電器
- }
- if(yushe_humi_L<U8RH_data_H&&U8RH_data_H<yushe_humi&&yushe_wendu_L<U8T_data_H&&U8T_data_H<yushe_wendu)
- //當濕度和溫度都處于正常值時 (&&:邏輯與,左右兩邊的表達式都成立(都為真,也就是1)時,該if語句才成立)
- {
- baojing=1; //停止報警
- }
- }
- else
- {
- ET0 = 1;//開啟定時器0中斷
- }
- }
- }
復制代碼
|