基于51單片機的溫濕度檢測設計,有藍牙向手機傳輸功能
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
1621343693(1).jpg (64.7 KB, 下載次數: 76)
下載附件
仿真圖效果
2021-5-18 21:15 上傳
電路原理圖如下:
1621343762(1).png (134.57 KB, 下載次數: 86)
下載附件
原理圖
2021-5-18 21:16 上傳
注釋很詳細的單片機源程序如下:
- #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define lcddata P0 //數據端口;
- sbit io=P1^0; //dht11data端接單片機的P1^0口//
- sbit SPK =P1^1; //蜂鳴器;
- sbit LED =P1^2; //報警燈 ;
- sbit JDQ_WenDu =P1^3; // 控制風扇的繼電器;
- sbit JDQ_ShiDu =P1^4; // 控制風扇的繼電器;
- sbit K1=P3^2; //手動/自動復位功能;
- sbit K2=P3^3; //頁面選擇;
- sbit K3=P3^4; //修改min,按鍵加1;
- sbit K4=P3^5; //修改max,按鍵加1;
- sbit RS = P2^0; //Pin4 數據命令選擇; 高電平時為數據寄存器,低電平是為選擇指令寄存器;
- sbit RW = P2^1; //Pin5 讀寫模式選擇;
- sbit E = P2^2; //Pin6 使能信號;
- bit di=1;
- bit flag_300ms ;
- unsigned char s[3]={0,0,'\0'}; //只讀取兩個字節,讀到第三個結束;
- unsigned char table[]={0,1,2,3,4,5,6,7,8,9};
- unsigned int j=40,i=0,sum=0;
- int tempeature; //整型變量 tempeature:溫度
- uchar yemian=0; //(定義變量)
- uchar flat=1;
- unsigned char WenDu=20,ShiDu=40;//報警的溫度和濕度
- typedef bit BOOL; //此聲明一個布爾型變量即真或假//
- uchar data_byte;
- uchar RH,RL,TH,TL;
- void receive(); //接收數據//
- /******************************************************************/
- void DelayUs(unsigned char us)//delay us
- {
- unsigned char uscnt;
- uscnt=us>>1; /*12MHz頻率*/
- while(--uscnt);
- }
- /******************************************************************/
- /* 毫秒函數聲明 */
- /******************************************************************/
- void DelayMs(unsigned int ms)
- {
- while(--ms)
- {
- DelayUs(250);
- DelayUs(250);
- DelayUs(250);
- DelayUs(250);
- }
- }
- //***************延時函數*************************************
- void delay(uchar ms) //延時模塊//
- {
- uchar i;
- while(ms--)
- for(i=0;i<100;i++);
- }
- void delay1() //一個for循環大概需要8個多機器周期 一個機器周期為1us 晶振為12MHz 也就是說本函數延時8us多 此延時函數必須德稍微精確一點
- {
- uchar i;
- for(i=0;i<1;i++);
- }
- // 對液晶經行寫指令;
- void wr_i_lcd(uchar content)
- {
- DelayMs(5);//操作前短暫延時,保證信號穩定
- E=0; //E端的由高電平跳變成低電平時,液晶模塊執行命令; 此處位E端清零操作
- RS=0;
- RW=0;
- E=1;
- lcddata=content;
- E=0;
- }
- // 液晶初始化,清除顯示,歸為地址;
- void lcd_csh()
- {
- // wr_i_lcd(0x01); //清除顯示;
- // wr_i_lcd(0x30); //地址歸位; 30H:設定8位控制界面;
- // // 00H:基本指令集;
- // // 34H:設定擴展指令集;
- // wr_i_lcd(0x0c); //開顯示,無光標,光標不閃爍; 0x0e:開顯示,有光標,光標不閃爍; 0x0f:開顯示,有光標,光標閃爍;
- // wr_i_lcd(0x10); //光標向左移;
- // wr_i_lcd(0x06); /*光標的移動方向 */
-
- DelayMs(15);
- wr_i_lcd(0x38);
- DelayMs(5);
- wr_i_lcd(0x38);
- DelayMs(5);
- wr_i_lcd(0x38);
- DelayMs(5);
- wr_i_lcd(0x0c);
- DelayMs(5);
- wr_i_lcd(0x06);
- DelayMs(5);
- wr_i_lcd(0x01);
- DelayMs(5);
- }
- // 對液晶進行寫數據;
- void wr_d_lcd(uchar content)
- {
- DelayMs(5); //操作前短暫延時,保證信號穩定
- E=0;
- RS=1;
- RW=0;
- E=1;
- lcddata=content;
- E=0;
- RS=0;
- }
-
- // 顯示坐標位置的函數;
- void gotoxy(uchar y,uchar x)
- {
- if(y==1) //第一行第一列;
- wr_i_lcd(0x80|x); //對液晶經行寫指令;
-
- if(y==2) //第二行第一列;
- wr_i_lcd(0xc0|x); //對液晶經行寫指令;
- }
- // printf輸入字符串操作;
- void printf(uchar *str)
- {
- while(*str!='\0')
- {
- wr_d_lcd(*str);
- str++;
- }
- }
- // 液晶顯示主程序操作; 初始顯示welcome
- void show()
- {
- gotoxy(1,4);
- printf("welcome");
- }
- void shezhi() //對里面的數值進行修改
- {
- if(!K3) //溫濕度數據大小加++;
- {
- DelayMs(50);
- if(!K3)
- {
- while(K3==0);
- if(yemian==1)
- {
- WenDu+=1;
- if(WenDu>99) { WenDu=99; } //溫度上限加
-
- }
- if(yemian==2)
- {
- ShiDu+=1;
- if(ShiDu>99) { ShiDu=99; } //濕度下限加
- }
- }
- }
- if(!K4)
- {
- DelayMs(50);
- if(!K4)
- {
- while(K4==0); //按一次,防止按下不松,加多次
- if(yemian==1)
- {
- if(WenDu<1) {WenDu=1; }
- WenDu-=1; //濕度下限減
- }
- if(yemian==2)
- {
- if(ShiDu<1) { ShiDu=1; }
- ShiDu-=1; //濕度下限減
- }
- }
- }
- }
- // 中斷初始化
- void Int()
- {
- EA=1;
- EX0=1;
- IT0=1;
-
- PX0=1; //(中斷0為最高優先級)
-
- EX1=1;
- IT1=1;
- }
- // 報警部分
- void warn()
- {
-
- // if((ShiDu>RH)||(WenDu<TH))
- // {
- // SPK=1;
- // LED=1;
- // }
- // else
- // {
- // SPK=0;
- // LED=0;
- // }
-
- if(ShiDu<RH)
- {
- JDQ_ShiDu =1; // 控制加濕器的繼電器;
- SPK=1;
- LED=1;
- }
- else
- {
- JDQ_ShiDu =0; // 控制加濕器的繼電器;
- SPK=0;
- LED=0;
- }
-
- DelayMs(200);
- if(WenDu>TH) //WenDu為設定值,TH測量值;
- {
- SPK=1;
- LED=1;
- JDQ_WenDu =1; // 控制風扇的繼電器;
- }
- else
- {
- SPK=0;
- LED=0;
- JDQ_WenDu =0; // 控制風扇的繼電器;
- }
-
- }
- /***************************選擇界面工作狀態*********************************/
- void Xuanze()
- {
- // key();
- //====================yemian==0時 進入工作狀態=================================
- if(yemian==0)
- {
- if(flat==1)
- {
- flat=0;
- lcd_csh(); //初始化
-
- gotoxy(1,0);
- printf("Temp:00");
-
- gotoxy(1,8);
- s[0]=0xdf; //由一個字符串轉化為一個字符;
- s[1]=0x43;
- printf(s);
-
- gotoxy(2,0);
- printf("Humi:00");
-
- gotoxy(2,7);
- printf("%RH");
-
- gotoxy(1,12);
- printf("T:");
-
- s[0]=WenDu/10+0x30; //由一個字符串轉化為一個字符;
- s[1]=WenDu%10+0x30;
- printf(s);
- // display(0x0e,WenDu/10+0x30); //報警溫度
- // display(0x0f,WenDu%10+0x30);
-
- gotoxy(2,12);
- printf("H:");
- s[0]=ShiDu/10+0x30; //由一個字符串轉化為一個字符;
- s[1]=ShiDu%10+0x30;
- printf(s);
- // display(0x4e,ShiDu/10+0x30); //報警濕度
- // display(0x4f,ShiDu%10+0x30);
-
- }
- // ***********DHT11讀取顯示部分************
- receive();
- gotoxy(1,5);
- s[0]=TH/10+0x30; //由一個字符串轉化為一個字符;
- s[1]=TH%10+0x30;
- printf(s);
-
- gotoxy(2,5);
- s[0]=RH/10+0x30; //由一個字符串轉化為一個字符;
- s[1]=RH%10+0x30;
- printf(s);
- }
- //====================yemian==1 溫度設置===========================
- if(yemian==1) //溫度
- {
- if(flat==1)
- {
- flat=0;
- lcd_csh(); //初始化
- // bee=1;
- gotoxy(1,0);
- printf("Temp max:");
- }
- shezhi();
- gotoxy(2,7);
- s[0]=WenDu/10+0x30; //由一個字符串轉化為一個字符;
- s[1]=WenDu%10+0x30;
- printf(s);
-
- SPK=1;
- LED=1;
- }
- //====================yemian==1濕度設置==========================
- if(yemian==2) //濕度設置
- {
- if(flat==1)
- {
- flat=0;
- // bee=1;
- lcd_csh(); //初始化
- gotoxy(1,0);
- printf("Humi min:");
- }
- shezhi();
- gotoxy(2,7);
- s[0]=ShiDu/10+0x30; //由一個字符串轉化為一個字符;
- s[1]=ShiDu%10+0x30;
- printf(s);
-
- SPK=1;
- LED=1;
- }
- }
- //**************************dht11測試某塊*************************************//
- void start() //開始信號
- {
- io=1;
- delay1();
- io=0;
- delay(30); // 主機把總線拉低必須大于18ms 保證DHT11能檢測到起始信號
- io=1; //發送開始信號結束后 拉高電平延時20-40us
-
- delay1(); //以下三個延時函數差不多為24us 符合要求
- delay1();
- delay1();
-
- delay1();
- delay1();
- }
- uchar receive_byte() //接收一個字節//
- {
- uchar i,temp;
- for(i=0;i<8;i++) //接收8bit的數據
- {
- while(!io); //等待50us的低電平開始信號結束
- delay1(); //開始信號結束之后 延時26us-28us 以下三個延時函數
- delay1();
- delay1();
- temp=0; //時間為26us-28us 表示接收的為數據'0'
- if(io==1)
- temp=1; //如果26us-28us之后 還為高電平 則表示接收的數據為'1'
- while(io); //等待數據信號高電平 '0'為26us-28us '1'為70us
- data_byte<<=1; //接收的數據為高位在前 右移
- data_byte|=temp;
- }
- return data_byte;
- }
- void receive() //接收數據//
- {
- uchar T_H,T_L,R_H,R_L,check,num_check,i;
- start(); //開始信號//
- io=1; //主機設為輸入 判斷從機 DHT11 響應信號
- if(!io) //判斷從機是否有低電平響應信號//
- {
- while(!io); //判斷從機發出 80us 的低電平響應信號是否結束//
- while(io); //判斷從機發出 80us 的高電平是否結束 如結束則主機進入數據接收狀態
- R_H=receive_byte(); //濕度高位
- R_L=receive_byte(); //濕度低位
- T_H=receive_byte(); //溫度高位
- T_L=receive_byte(); //溫度低位
- check=receive_byte(); //校驗位
- io=0; //當最后一bit數據接完畢后 從機拉低電平50us//
- for(i=0;i<7;i++) //差不多50us的延時
- delay1();
- io=1; //總線由上拉電阻拉高 進入空閑狀態
- num_check=R_H+R_L+T_H+T_L;
- if(num_check==check) //判斷讀到的四個數據之和是否與校驗位相同
- {
- RH=R_H;
- RL=R_L;
- TH=T_H;
- TL=T_L;
- check=num_check;
- }
- }
- }
- /*************************串口初始化*********************************/
- void UsartConfiguration()
- {
- SCON=0x50; //設置位方式1; REN=1(接收允許)
- TMOD=0x20; //計數器工作方式2; 計數器T1
- PCON=0x00; //SMOD=0;
- TH1=0xfd; //波特率位9600bit/s;
- TL1=0xfd;
- TR1=1; //打開計數器;
- ES=1; //打開接收中斷;
- EA=1; //打開總中斷;
- }
- /***************************主程序*********************************/
- void main()
- {
- SPK=1;
- LED=1;
- Int(); //中斷初始化;
- lcd_csh(); //LCD1602初始化;
- UsartConfiguration(); //串口初始化;
- show();
- DelayMs(1000); //3s以后,進入主程序部分,初始化部分結束;
- while(1)
- {
-
- RI=1;
- Xuanze();
- DelayMs(200);
- if(yemian==0) { warn(); }
- }
- }
- /*********************頁面選擇*****************************/
- void int0(void) interrupt 0 //
- {
-
- if(!K1) //頁面選擇;
- {
- DelayMs(20); //程序消抖;
- if(!K1)
- {
- yemian++;
- flat++;
- while(!K1);
- if(yemian>=3) { yemian=0; }
- }
- }
- }
- //************手機APP發送端*************
- void uart() interrupt 4
- {
-
- //************發送濕度部分***************************
- RI=0; // //清除收到中斷標志位;
- SBUF=RH/10+0x30; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0; //清除發送中斷標志位;
-
- RI=0; //清除收到中斷標志位;
- SBUF=RH%10+0x30; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0; //清除發送中斷標志位;
-
- RI=0; // % //清除收到中斷標志位;
- SBUF=37; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0; //清除發送中斷標志位;
-
- RI=0; // R //清除收到中斷標志位;
- SBUF=82; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0;
-
- RI=0; // H //清除收到中斷標志位;
- SBUF=72; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0; //清除發送中斷標志位;
-
- for(i=0;i<10;i++)
- {
- RI=0; //空格 //清除收到中斷標志位;
- SBUF=32; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0;
- }
- //************發送溫度部分***************************
- RI=0; // //清除收到中斷標志位;
- SBUF=TH/10+0x30; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0; //清除發送中斷標志位;
-
- RI=0; //清除收到中斷標志位;
- SBUF=TH%10+0x30; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0;
- //清除發送中斷標志位;
- RI=0; //清除收到中斷標志位;
- SBUF=96; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0; //清除發送中斷標志位;
-
- RI=0; //清除收到中斷標志位;
- SBUF=67; //將接收到的數據放回發送緩存器;
- while(!TI); //等待發送數據完成;
- TI=0; //清除發送中斷標志位;
- SBUF=10; // (換行)
- while(!TI); //等待發送數據完成;
- TI=0; //清除發送中斷標志位;
-
- }
復制代碼
所有資料51hei提供下載:
無限溫濕度檢測f(仿真).zip
(25.01 KB, 下載次數: 125)
2021-5-18 21:13 上傳
點擊文件名下載附件
仿真圖 下載積分: 黑幣 -5
溫濕度測量程序.zip
(48.43 KB, 下載次數: 130)
2021-5-18 21:13 上傳
點擊文件名下載附件
溫濕度程序 下載積分: 黑幣 -5
|