51單片機課程設計:基於DHT11的溫溼度報警器
本程序適用於51系列單片機,主要用於讀取DHT11溫溼度模塊數值,顯示在數碼管上,同時還具備溫溼度報警功能,當超出預設值,蜂鳴器報警,可在吉林農業大學單片機開發板上完美運行,其他朋友可以修改部分代碼移植的其他型號的開發板上。工程文件以及開發板電路圖可到附件下載,同時DHT11部分資料在附件也可以下載。
關於粘貼複製亂碼的問題:如果程序複製到Keil編譯器上出現註釋亂碼,可以先建一個.c文件,也就是說不在keil裏面編輯,然後用記事本打開.c文件,將源碼複製進去,再在keil中添加文件即可。
/************************************說明*************************************** 程序運行時 會對模塊進行預熱 保證讀取第一個數值的精確 預熱時間大概爲4秒左右 程序初始化時將會提示你設置最大溫溼度 H1 最高溫度 L1 最低溫度 H2 最高溼度 L2 最低溼度 按鈕K1溫度加 按鈕K2溫度減 設置完成後 按K3 即確定按鈕 開始監控報警 (適用於吉農51單片機開發板) 2016-12-29----------------------------SWorld ********************************************************************************/ #include <reg52.h> #define OK 1 #define ERROR 0 #define NUMBER 20 #define SIZE 5 /*-----------------------------顯示部分接線方法-------------------------------*/ #define GPIO_DIG P0 sbit WEC=P2^3; //段選 sbit DUC=P2^2; //位選 /*----------------------------模塊引腳連接-------------------------------------*/ sbit dht11 = P2^0; //dht 接口 只要接一個就行 接dht11 data0接口 NC不用管 /*-----------------------------按鍵引腳方法------------------------------------*/ sbit add=P2^5;//增加 連接K2 sbit sub=P2^4;//減少 連接K1 sbit ok=P2^6;//確定 連接K3 /*----------------------------報警引腳連接-------------------------------------*/ sbit bell=P2^7;//蜂鳴器接口 連接蜂鳴器 /*------------------------------全局變量---------------------------------------*/ unsigned char flag; /*---------------分別代表數碼管上的0~9共10位數以及字母L、H----------------------*/ unsigned char code array[12]= { 0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f,0x38,0x76//L H }; unsigned char DisplayData[8]; //用來存放要顯示的8位數的值 unsigned int HTemp,LTemp,HHumi,LHumi,setok; //用來存放最大溫溼度 以及是否設置好溫溼度 int temp_value, humi_value; //溫溼度數值存放 unsigned char status; unsigned char value_array[5]; /*------------------------------函數聲明---------------------------------------*/ void Delay_1ms(unsigned int ms); unsigned char ReadTempAndHumi(void); void InitTime(void); void Delay_1ms(unsigned int ms); void SMG_Display(unsigned int value,unsigned int way ) ; //顯示部分 unsigned char ReadValue(void); /*------------------------------延時函數 延時1ms ---------------------------------------*/ void Delay_1ms(unsigned int ms) { unsigned int x, y; for(x = ms; x > 0; x--) { for(y = 124; y > 0; y--); } } /*------------------------------延時函數 延時10ns ---------------------------------------*/ void Delay_10us(void) { unsigned char i; i--; i--; i--; i--; i--; i--; } /*------------------------------讀取模塊數值 ---------------------------------------*/ unsigned char ReadValue(void) { unsigned char count, value = 0, i; status = OK; for(i = 8; i > 0; i--) { value <<= 1; count = 0; while(dht11 == 0 && count++ < NUMBER); if(count >= NUMBER) { status = ERROR; return 0; } Delay_10us(); Delay_10us(); Delay_10us(); if(dht11 != 0) { value++; while(dht11 != 0 && count++ < NUMBER) { dht11 = 1; } if(count >= NUMBER) { status = ERROR; return 0; } } } return (value); } /*------------------------------獲取模塊溫溼度 ---------------------------------------*/ unsigned char ReadTempAndHumi(void) { unsigned char i = 0, check_value = 0,count = 0; EA = 0; dht11 = 0; Delay_1ms(20); dht11 = 1; Delay_10us(); Delay_10us(); Delay_10us(); Delay_10us(); if(dht11 != 0) { EA = 1; return ERROR; } else { while(dht11 == 0 && count++ < NUMBER); if(count >= NUMBER) { dht11 = 1; EA = 1; return ERROR; } count = 0; dht11 = 1; while(dht11 != 0 && count++ < NUMBER); if(count >= NUMBER) { dht11 = 1; EA = 1; return ERROR; } for(i = 0; i < SIZE; i++) { value_array[i] = ReadValue(); if(status == ERROR) { dht11 = 1; EA = 1; return ERROR; } if(i != SIZE - 1) { check_value += value_array[i]; } } if(check_value == value_array[SIZE - 1]) { humi_value = value_array[0] * 10; temp_value = value_array[2] * 10; dht11 = 1; EA = 1; return OK; } else { EA = 1; return ERROR; } } } /************************************************************** 鍵盤掃描子程序 **************************************************************/ unsigned char Key_Scan() { unsigned char keyValue = 0 , i; //保存鍵值 //--檢測按鍵1--// if (ok != 1)//檢測按鍵K3是否按下 { Delay_1ms(10);//消除抖動 if (ok != 1)//再次檢測按鍵是否按下 { keyValue = 3; i = 0; while ((i<50) && (ok != 1)) //檢測按鍵是否鬆開 { Delay_1ms(10); i++; } } } //--檢測按鍵1--// if (add != 1)//檢測按鍵K1是否按下 { Delay_1ms(10);//消除抖動 if (add!= 1)//再次檢測按鍵是否按下 { keyValue = 2; i = 0; while ((i<50) && (add != 1)) //檢測按鍵是否鬆開 { Delay_1ms(10); i++; } } } //--檢測按鍵1--// if (sub != 1)//檢測按鍵K2是否按下 { Delay_1ms(10);//消除抖動 if (sub!= 1)//再次檢測按鍵是否按下 { keyValue = 1; i = 0; while ((i<50) && (sub != 1)) //檢測按鍵是否鬆開 { Delay_1ms(10); i++; } } } return keyValue; //將讀取到鍵值的值返回 } /******************************************************************************* * 函 數 名 : DigDisplay * 函數功能 : 使用數碼管顯示 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void DigDisplay() { unsigned char i; unsigned int j; for(i=0;i<8;i++) { WEC=1;DUC=0; switch(i) //位選,選擇點亮的數碼管, { case(0): GPIO_DIG=0x7F; break;//顯示第0位 case(1): GPIO_DIG=0xBF; break;//顯示第1位 case(2): GPIO_DIG=0xDF; break;//顯示第2位 case(3): GPIO_DIG=0xEF; break;//顯示第3位 case(4): GPIO_DIG=0xF7; break;//顯示第4位 case(5): GPIO_DIG=0xFB; break;//顯示第5位 case(6): GPIO_DIG=0xFD; break;//顯示第6位 case(7): GPIO_DIG=0xFE; break;//顯示第7位 } WEC=0;DUC=1; GPIO_DIG=DisplayData[i];//發送段碼 j=50; //掃描間隔時間設定 while(j--); GPIO_DIG=0x00;//消隱 } } /*------------------------------主函數 主函數共分爲5部分,有switch語句執行相關操作 case 1:設置最高溫度,完成設置後跳到下一循環 case 2:設置最低溫度,完成設置後跳到下一循環 case 3:設置最高溼度,完成設置後跳到下一循環 case 4:設置最低溼度,完成設置後跳到下一循環 case 5:溫溼度監控主循環,當低於後者超過預設值, 觸發警報。所讀取的數值同時顯示於數碼管 ---------------------------------------*/ void main(void) { unsigned char mark = 0; Delay_1ms(1000); ReadTempAndHumi(); Delay_1ms(3000); InitTime(); WEC=0;DUC=0; HTemp=30,LTemp=20; HHumi=100,LHumi=20; bell=1,setok=1; while(1) { switch(setok) { case 1: DisplayData[7]=array[11]; DisplayData[6]=array[1]; DisplayData[4]=array[HTemp/10]; DisplayData[3]=array[HTemp%10]; switch(Key_Scan()) { case 1: HTemp-=2; break; case 2: HTemp+=2; break; case 3: setok=2; break; } break; case 2: DisplayData[7]=array[10]; DisplayData[6]=array[1]; DisplayData[4]=array[LTemp/10]; DisplayData[3]=array[LTemp%10]; switch(Key_Scan()) { case 1: LTemp-=2; break; case 2: LTemp+=2; break; case 3: setok=3; break; } break; case 3: DisplayData[7]=array[11]; DisplayData[6]=array[2]; DisplayData[4]=array[HHumi/100]; DisplayData[3]=array[HHumi%100/10]; DisplayData[2]=array[HHumi%10]; switch(Key_Scan()) { case 1: HHumi-=2; break; case 2: HHumi+=2; break; case 3: setok=4; break; } break; case 4: DisplayData[7]=array[10]; DisplayData[6]=array[2]; DisplayData[4]=array[LHumi/100]; DisplayData[3]=array[LHumi%100/10]; DisplayData[2]=array[LHumi%10]; switch(Key_Scan()) { case 1: LHumi-=2; break; case 2: LHumi+=2; break; case 3: setok=5; break; } break; case 5: DisplayData[4]=0x00; if(flag == 30) { flag = 0; mark++; ReadTempAndHumi(); if(temp_value<LTemp*10||temp_value>HTemp*10||humi_value<LHumi*10||humi_value>HHumi*10) { bell=0; } else { bell=1; } } SMG_Display(temp_value,0); SMG_Display(humi_value,1); break; } DigDisplay(); } } /*------------------------------定時器初始化 ---------------------------------------*/ void InitTime(void) { TH0 = (unsigned char)((65535U - 50000) >> 8); TL0 = (unsigned char)(65535U - 50000) ; TMOD = 0X01; TR0 = 1; ET0 = 1; EA = 1; } /*------------------------------數值轉換 將讀取到的數值轉換爲數碼管可顯示的數值 ---------------------------------------*/ void SMG_Display(unsigned int value,unsigned int way ) { unsigned char ge, bai, shi; ge = value % 10; shi = value % 100 / 10; bai = value % 1000 / 100; if(way==0) { DisplayData[7]=array[bai]; DisplayData[6]=array[shi]|0x80; DisplayData[5]=array[ge]; } else { DisplayData[3]=array[bai]; DisplayData[2]=array[shi]|0x80; DisplayData[1]=array[ge]; } } /*------------------------------定時器0 ---------------------------------------*/ void timer(void) interrupt 1 { TH0 = (unsigned char)((65535 - 50000) >> 8); TL0 = (unsigned char)(65535 - 50000); flag++; }