利用51單片機和溫度傳感器DS18B20和濕度傳感器DHT11,STC89C52R作為處理器,通過單總線將采集數據實時顯示于本地LCD顯示屏端。用電機風扇轉速,溫度控制風扇調整高時風扇轉速加快,溫度低時風扇轉速減小,濕度高時風扇轉速加快,濕度低時風扇轉速減小。四個按鍵分別控制:切換控制溫度/濕度;增大要控制的溫度/濕度的標準;減小要控制的溫度/濕度的標準;切換控制方式(PID算法/檔位)。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
單片機程序
- #include <REG52.H>
- #include "intrins.h"
- #include "LCD1602.h" //包含LCD1602頭文件
- #include "Delay.h" //包含Delay頭文件
- #include "DS18B20.h"
- #include "DHT11.h"
- #include "Timer0.h"
- sbit Motor=P0^0;
- sbit P34 = P3^4;
- sbit P35 = P3^5;
- sbit P36 = P3^6;
- sbit P37 = P3^7;
- float T = 0;
- extern unsigned char hum;//濕度
- unsigned char k1 = 5, k2 = 1, k3 = 10;
- int sbz = 38, speed = 0, wbz = 25;
- float bz = 0, xz = 0;
- float p = 0,i = 0,d = 0;
- float pid = 0;
- int Compare = 0;
- unsigned char DHTC = 0,DHTF = 0;
- unsigned char sw = 0; //0濕度 , 1溫度
- unsigned char kz = 0; //0檔位控制, 1pid
- unsigned char key = 0, key_keyNumber = 0;
- void main()
- {
- Motor = 0;
- LCD_Init();
- DHT11_Init();
- DS18B20_ConvertT();
- Delay(1000);
- Timer0Init();
- Timer1Init();
- TR0 = 1; //定時器0開始計時
- ET0=1;
- TR1 = 1;
- ET1 = 1;
- EA=1;//開啟總中斷
- while(1)
- {
- LCD_ShowString(1,1,"Tem:");
- LCD_ShowString(2,1,"Hum:");
- LCD_ShowChar(1,8,'.');
- LCD_ShowChar(2,7,'%');
- TR0 = 0;
- TR1 = 0;
- DS18B20_ConvertT(); //轉換溫度
- T=DS18B20_ReadT(); //讀取溫度
- if(DHTF == 1)
- {
- DHT11_receive();
- DHTF = 0;
- }
- TR0 = 1;
- TR1 = 1;
- LCD_ShowNum(1,5,T,3); //顯示溫度整數部分
- LCD_ShowNum(1,9,(unsigned long)(T*10000)%10000,4);//顯示溫度小數部分
- LCD_ShowNum(2,5,hum,2);
- //LCD_ShowNum(1,5,Compare,4);
- //LCD_ShowNum(1,10,hu,2);LCD_ShowSignedNum(2,1,p,4);LCD_ShowSignedNum(2,6,i,4);LCD_ShowSignedNum(2,11,d,4);
- key = key_keyNumber;
- key_keyNumber = 0;
- {
- if(key == 1)
- {
- sw = 1 - sw;
- }
- else if(key == 2)
- {
- if(sw == 0)
- sbz++;
- else
- wbz++;
- }
- else if(key == 3)
- {
- if(sw == 0)
- sbz--;
- else
- wbz--;
- }
- else if(key == 4)
- {
- kz = 1 - kz;
- }
- }
- if(sw == 1)
- {
- LCD_ShowNum(1,14,wbz,3);
- LCD_ShowString(2,14," ");
- xz = T;
- bz = wbz;
- }
- else
- {
- LCD_ShowNum(2,14,sbz,3);
- LCD_ShowString(1,14," ");
- xz = hum;
- bz = sbz;
- }
- if(kz)
- {
- LCD_ShowString(2,10,"PID");
- d = xz - bz - p;
- p = xz - bz;
- i += p;
- pid += (k1*p + k2*i + k3*d);
- if(pid>=0 && pid<=1000)
- {
- Compare = pid;
- }
- else if(pid<0)
- {
- Compare = 0;
- pid = 0;
- }
- else
- {
- Compare = 1000;
- pid = 1000;
- }
- }
- else
- {
- LCD_ShowString(2,10," ");
- p = 0;i = 0; d = 0; pid = 0;
- if(xz - bz >=10)
- {
- speed = 1000;
- }
- else if(xz - bz <=0)
- {
- speed = 0;
- }
- else
- {
- speed = (int)((xz - bz)*100);
- }
- Compare = speed ;
- }
- Delay(50);
- }
- }
- unsigned char Key_GetState()
- {
- unsigned char keynum = 0;
- if(P34 == 0){keynum=1;} //一有按鍵被按下,標志位keynum立即置位并返回,給key_loop函數處理
- if(P35 == 0){keynum=2;}
- if(P36 == 0){keynum=3;}
- if(P37 == 0){keynum=4;}
- return keynum;
- }
- void key_loop()
- {
- static unsigned char before_state,now_state;
- before_state = now_state;
- now_state = Key_GetState(); //獲取按鍵標志位
- if(before_state == 1 && now_state == 0)
- {
- key_keyNumber = 1; //全局變量key_keyNumber置1,使用key_return函數返回給main函數使用
- }
- if(before_state == 2 && now_state == 0)
- {
- key_keyNumber = 2;
- }
- if(before_state == 3 && now_state == 0)
- {
- key_keyNumber = 3;
- }
- if(before_state == 4 && now_state == 0)
- {
- key_keyNumber = 4;
- }
- }
- void Timer0_Routine() interrupt 1
- {
- static unsigned int T0Count;
- TL0 = 0xA4; //設置定時初始值
- TH0 = 0xFF;
- T0Count++;
- if(T0Count < Compare)
- {
- Motor = 1;
- }
- else
- {
- Motor = 0;
- }
- if (T0Count >= 1000)
- {
- T0Count = 0;
- }
- }
- void Timer1_Routine() interrupt 3
- {
- static unsigned int T1Count;
- TL1 = 0x00;
- TH1 = 0xDC;
- T1Count++;
- DHTC ++;
- if(T1Count>=20)
- {
- key_loop();
- T1Count = 0;
- }
- if(DHTC >=75)
- {
- DHTC = 0;
- DHTF = 1;
- }
- }
復制代碼 Proteus8.13仿真程序下載:
仿真 代碼 keil文件.7z
(79.93 KB, 下載次數: 109)
2023-12-20 15:00 上傳
點擊文件名下載附件
|