/********************DHT11.h********************/
#ifndef DHT11_H
#define DHT11_H
#include <reg52.h>
#include "common.h"
//温湿度传感器DHT11数据接口
sbit DHT11Dout = P2^0;
uchar DHT11ReceiveByte(void);
void DHT11ReadData(void);
#endif
/********************DHT11.c********************/
#include "DHT11.h"
#include "system.h"
/*uchar DHT11Data[6]
用来保存当前的温度、湿度
[0:1]湿度整数部分
[2]湿度小数部分
[3:4]温度整数部分
[5]温度小数部分
*/
uchar DHT11Data[6]={0, 0, 0, 0, 0, 0};
static void delay_25ms(void) //误差 0us
{
unsigned char a,b,c;
for(c=7;c>0;c--)
for(b=16;b>0;b--)
for(a=110;a>0;a--);
}
static void delay_30us(void) //误差 0us
{
unsigned char a,b;
for(b=3;b>0;b--)
for(a=3;a>0;a--);
}
uchar DHT11ReceiveByte(void)
{
uchar i;
uchar com_data, temp;
for(i=0; i<=7; i++)
{
while(!DHT11Dout);
delay_30us();
temp = 0;
if(DHT11Dout){temp = 1;}
while(DHT11Dout);
com_data <<= 1;
com_data |= temp;
}
return com_data;
}
void DHT11ReadData(void)
{
uint untemp=0;
uint TH_data=0, TL_data=0, RH_data=0, RL_data=0, CK_data=0;
uint TH_temp=0, TL_temp=0, RH_temp=0, RL_temp=0, CK_temp=0;
while(1){
//主机拉低必须大于18ms
DHT11Dout = 0;
delay_25ms();
DHT11Dout = 1;
//DATA总线由上拉电阻拉高主机延时30us
delay_30us();
//判断DHT11是否有低电平响应信号如不响应则跳出,响应则向下运行
if(!DHT11Dout){
//判断DHT11发出 80us 的低电平响应信号是否结束
while(!DHT11Dout);
//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
while(DHT11Dout);
//数据接收状态
RH_temp = DHT11ReceiveByte(); //8bit温度整数数据
RL_temp = DHT11ReceiveByte(); //8bit温度小数数据
TH_temp = DHT11ReceiveByte(); //8bit湿度整数数据
TL_temp = DHT11ReceiveByte(); //8bit湿度小数数据
CK_temp = DHT11ReceiveByte(); //8bit校验位
delay_30us();
delay_30us();
DHT11Dout = 1;
//数据校验
untemp = RH_temp + RL_temp + TH_temp + TL_temp;
if(untemp==CK_temp){
RH_data = RH_temp;
RL_data = RL_temp;
TH_data = TH_temp;
TL_data = TL_temp;
CK_data = CK_temp;
break;//跳出while循环
}
}
}
//湿度整数部分
DHT11Data[0] = RH_data/10;
DHT11Data[1] = RH_data%10;
//湿度小数部分 不做处理
DHT11Data[2] = RL_data ;//转为小数时除以256即可
//温度整数部分
DHT11Data[3] = TH_data/10;
DHT11Data[4] = TH_data%10;
//温度小数部分 不做处理
DHT11Data[5] = TL_data; //转为小数时除以256即可
}
/*************************system.h*****************************/
#ifndef SYSTEM_H
#define SYSTEM_H
#include "common.h"
//蜂鸣器、LED报警接口
sbit AlarmBuzzer = P2^4; //响:声报警
sbit LED4 = P3^5; //亮:光报警
//工作情况指示灯:
sbit LED3 = P3^6; //亮:启动制冷
sbit LED2 = P3^7; //亮:启动抽湿
void SystemInit(void);
void SystemControl(void);
void SystemSet(void);
void SystemInformationDisplay(void);
#endif
/***********************system.c************************/
#include "system.h"
#include "lcd1602.h"
#include "DHT11.h"
#include "key.h"
#include "eeprom.h"
uchar TemperatureLimit = 32; //温度上限值
uchar GlobeTemperature = 30;//要设置的温度
uchar TemperatureMin = 6; //温度值下限值
uchar HumidityLimit = 80; //湿度上限值
uchar GlobeHumidity = 66; //要设置的湿度
uchar HumidityMin = 10; //湿度下限值
uchar SYSTEM_FLAGS = 0; //如果系统不是第一次启动过,则设置为1,否为0
uchar flg = 0;//按键控制
extern uchar DHT11Data[6];
//系统初始化
void SystemInit(void)
{
uchar *Project = "Granary Control";
uchar *Designer = "Designer: HongDe";
AlarmBuzzer = 1;
LED4 = 0;
LED3 = 0;
LED2 = 0;
LcdInit(); //初始化LCD
DelayMs(10);
LcdSetPosition(1); //设置显示位置
while(*Project != '\0'){//在LCD1602第1行显示“Granary Control”
LcdWriteData(*Project);
Project++;
}
LcdSetPosition(0x40); //设置显示位置
while(*Designer != '\0'){//在LCD1602第1行显示“Granary Control”
LcdWriteData(*Designer);
Designer++;
}
SYSTEM_FLAGS = eepromReadByte(0x2016);//从第一扇区读系统启动参数
if(SYSTEM_FLAGS==1){//如果系统不是第一次启动过,则读取先前存储的参数值
GlobeTemperature = eepromReadByte(0x2000);//读取存放在eeprom中的温度节点值
TemperatureLimit = eepromReadByte(0x2004); //读取存放在eeprom中的温度安全节点值
GlobeHumidity = eepromReadByte(0x2008); //读取存放在eeprom中的湿度节点值
HumidityLimit = eepromReadByte(0x2012); //读取存放在eeprom中的湿度安全节点值
}
}
void SystemControl(void)
{
uchar temp=0;
uchar rh=0;
DHT11ReadData();//获取温度、湿度
temp = DHT11Data[3]*10 + DHT11Data[4]; //温度整数部分
rh = DHT11Data[0]*10 + DHT11Data[1];//湿度整数部分,小数部分未处理
if((rh>HumidityLimit)||(temp>TemperatureLimit)){//当前温度高于安全点温度或者当前湿度高于安全点湿度
while(1){
//更新当前环境温度
DHT11ReadData();//获取温度、湿度
rh= DHT11Data[0]*10 + DHT11Data[1];//湿度整数部分,小数部分未处理
temp = DHT11Data[3]*10+DHT11Data[4];
if(temp>TemperatureLimit)LED3 = 1; //启动制冷
if(rh>HumidityLimit)LED2 = 1; //启动抽湿
LED4 = ~LED4; //灯亮闪烁报警
AlarmBuzzer = ~AlarmBuzzer; //蜂鸣器鸣叫
DelayMs(5);
if((temp<TemperatureLimit)&&(temp<GlobeTemperature)){LED3 = 0; LED4 = 0; AlarmBuzzer = 1;}//停止制冷
if((rh<HumidityLimit)&&(rh<GlobeHumidity)){LED2 = 0; LED4 = 0; AlarmBuzzer = 1;}//停止抽湿
if((rh<HumidityLimit)&&(temp<TemperatureLimit)){LED4 = 0; break;}//停止报警
SystemSet();//设置
SystemInformationDisplay();//温湿度显示
}
}
if(temp>GlobeTemperature){
LED3 = 1; //启动制冷
}else{LED3 = 0;}//关闭制冷
if(rh>GlobeHumidity){
LED2 = 1; //启动抽湿
}else{LED2 = 0;}//停止抽湿
AlarmBuzzer = 1;
}
void SystemSet(void)
{
uchar key;
uchar eepromFlags = 0;
key = ScanKey();
if(key==SW2){//按下按键SW2
flg++;
if(flg==5){flg = 1;}
}
switch(flg){
case 1:{//温度节点调节(即温度节点)
if(key==SW1){ --GlobeTemperature; eepromFlags = 1;}//减操作
if(key==SW3){ ++GlobeTemperature; eepromFlags = 1;}//加操作
if(GlobeTemperature==TemperatureMin-1)GlobeTemperature = TemperatureLimit;
if(GlobeTemperature==TemperatureLimit+1)GlobeTemperature = TemperatureMin;
break;
}
case 2:{//温度安全节点调节
if(key==SW1){ --TemperatureLimit; eepromFlags = 1;}//减操作
if(key==SW3){ ++TemperatureLimit; eepromFlags = 1;}//加操作
break;
}
case 3:{//湿度节点调节
if(key==SW1){ --GlobeHumidity; eepromFlags = 1;}//减操作
if(key==SW3){ ++GlobeHumidity; eepromFlags = 1;}//加操作
if(GlobeHumidity==HumidityMin-1)GlobeHumidity = HumidityLimit;
if(GlobeHumidity==HumidityLimit+1)GlobeHumidity = HumidityMin;
break;
}
case 4:{ //湿度安全节点调节
if(key==SW1){--HumidityLimit; eepromFlags = 1;}//减操作
if(key==SW3){++HumidityLimit; eepromFlags = 1;}//加操作
break;
}
default: eepromFlags = 0; break;
}
if(eepromFlags){//系统工作参数有变动,参数存eeprom
eepromErase(0x2000);//擦除第一个扇区
eepromWriteByte(0x2000, GlobeTemperature);//存放温度节点值
eepromWriteByte(0x2004, TemperatureLimit); //存放温度安全节点值
eepromWriteByte(0x2008, GlobeHumidity); //存放湿度节点值
eepromWriteByte(0x2012, HumidityLimit); //存放湿度安全节点值
SYSTEM_FLAGS = 1;
eepromWriteByte(0x2016, SYSTEM_FLAGS); //存放系统启动过的标志
}
}
//显示温湿度信息
//显示设置的温湿度值,和当前环境的温湿度值
void SystemInformationDisplay(void)
{
char *TempStr = "t/tS/TH:";
char *RHStr = "r/rS/RH:";
uchar i=0;
LCDClear();
LcdSetPosition(0x40); //设置湿度显示在中间位置,第2行
while(*RHStr != '\0'){
LcdWriteData(*RHStr);
RHStr++;
}
LcdWriteData(DHT11Data[0]+'0');
LcdWriteData(DHT11Data[1]+'0');
LcdWriteData('/');
LcdWriteData(GlobeHumidity/10+'0');
LcdWriteData(GlobeHumidity%10+'0');
LcdWriteData('/');
LcdWriteData(HumidityLimit/10+'0');
LcdWriteData(HumidityLimit%10+'0');
LcdSetPosition(0x00); //设置温度显示在中间位置,第1行
while(*TempStr != '\0'){
LcdWriteData(*TempStr);
TempStr++;
}
LcdWriteData(DHT11Data[3]+'0');
LcdWriteData(DHT11Data[4]+'0');
LcdWriteData('/');
LcdWriteData(GlobeTemperature/10+'0');
LcdWriteData(GlobeTemperature%10+'0');
LcdWriteData('/');
LcdWriteData(TemperatureLimit/10+'0');
LcdWriteData(TemperatureLimit%10+'0');
}