#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
/*======LCD位定义==========*/
sbit RS=P2^6;
sbit RW=P2^5;
sbit E=P2^7;
sfr LCDData=0x80;
/*按键定位*/
sbit set = P1^4;//调时按键移位
sbit jia = P1^5;//加一按键
sbit jian = P1^6;//减一按键
sbit back = P1^7;//退出调时按键
/*蜂鸣器定位*/
sbit BEEP = P2^0;
/*热释电红外检测定位*/
sbit HW_check = P2^1;
/*指示灯定位*/
sbit LED_ZG = P3^2; //遮光指示灯
sbit LED_BG = P3^3; //补光指示灯
sbit LED_ZL = P3^4; //制冷指示灯
sbit LED_JR = P3^5; //加热指示灯
sbit LED_ZS = P3^6; //增湿指示灯
sbit LED_GZ = P3^7; //干燥指示灯
/*光照强度检测,AD转换芯片引脚定位*/
unsigned char Read_ADC0832(unsigned char Ch);
sbit ADC0832_CS =P1^0; //将CS位定义为P2.5引脚
sbit ADC0832_CLK=P1^1; //将CLK位定义为P2.6引脚
sbit ADC0832_DIO=P1^2; //将DIO位定义为P2.7引脚
uchar AD_Value=0;
uchar result,result0;/*存放测试结果*/
uchar count;
bit flash; //刷新频率参数
sbit TRH = P2^2; //温湿度传感器DHT11数据接入
uchar TH_data,TL_data,TH,TL,RH_data,RH_data0,RL_data,CK_data;
uchar TH_temp,TL_temp,RH_temp,RL_temp,CK_temp;
uchar com_data,untemp,temp;
uchar respond;
uchar T_SETDOWN,T_SETTOP,R_SETDOWN,R_SETTOP,L_SETDOWN, L_SETTOP;//温湿度光照强度最大最小值
/***液晶驱动******/
void Delay(uint i)
{while(i--);}
// 毫秒级延时子程序
/*********************************************************************************/
void delay_ms(unsigned char ms)
{
unsigned char i;
while(ms--)
{
for(i = 0; i< 150; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/****************************************************************************/
//收发信号检测,数据读取
/****************************************************************************/
//5us级延时程序
/*********************************************************************************/
void delay_5us()
{
uchar i;
i--;
i--;
i--;
i--;
i--;
i--;
}
char receive()
{
uchar i;
com_data=0;
for(i=0;i<=7;i++)
{
respond=2;
while((!TRH)&&respond++);
delay_5us();
delay_5us();
delay_5us();
if(TRH)
{
temp=1;
respond=2;
while((TRH)&&respond++);
}
else
temp=0;
com_data<<=1;
com_data|=temp;
}
return(com_data);
}
/**********温湿度检测程序*********/
//温度高8位== TL_data,温度低8位== TH_data,湿度高8位== RH_data,湿度低8位== RH_data,校验 8位 == CK_data
void read_TRH()
{
//主机拉低18ms
TRH=0;
delay_ms(18);
TRH=1;
//DATA总线由上拉电阻拉高 主机延时20us
delay_5us();
delay_5us();
delay_5us();
delay_5us();
//delay_us();
//delay_us();delay_us();delay_us();delay_us();
//主机设为输入 判断从机响应信号
TRH=1;
//判断DHT11是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!TRH)
{
respond=2; //判断DHT11发出 80us 的低电平响应信号是否结束
while((!TRH)&& respond++);
respond=2; //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
while(TRH && respond++); //数据接收状态
RH_temp = receive();
RL_temp = receive();
TH_temp = receive();
TL_temp = receive();
CK_temp = receive();
TRH=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;
}
}
}
/*********************************************************************************/
void Write_Instruction(uchar x)
{
Delay(1000);
E=0;
RW=0;
RS=0;
LCDData=x;
E=1;
Delay(20);
E=0;
}
void Write_Data(uchar x)
{
Delay(1000);
E=0;
RW=0;
RS=1;
E=1;
LCDData=x;
E=0;
}
void InitLCD(void)
{
Write_Instruction(0x38);
Delay(200);
Write_Instruction(0x0e);
Delay(200);
Write_Instruction(0x06);
Delay(200);
}
void Write_String(uchar x,uchar *p)
{ Write_Instruction(x);
while(*p!=0x00)
{ Write_Data(*p);
p++;
if (x++==0x8f)
{ Write_Instruction(0xc0);}
}
}
void Write_t(uchar i,uchar k)//数据写入
{
Write_Instruction(i);
Write_Data(k|0x30);
}
void Write_d(uchar i,uchar k)//℃写入
{
Write_Instruction(i);
Write_Data(k);
}
/****************************************************************************/
/****数据显示*****/
void Display( uchar y,uchar x )
{
Write_t(y+0,(x/10)|0x30);
Write_t(y+1,(x%10)|0x30);
}
/****按键检测*****/
void key_test( )
{
uchar place,num,number,x;
place=0x8b;
number = R_SETDOWN;
num = 1;
x=1;
while(num!=0)
{
if(set==0)
{
delay_ms(5);
if(set==0)
{
x++;
if(x>6)x=1;
while(!set);
switch(x)
{
case 1:{
Write_Instruction(0x01);//清屏
Write_String(0x80,"R:");
Write_String(0xc0,"T:");
Write_String(0x84,"%R");
Write_d(0xc4,0xdf); //显示℃
Write_String(0xc5,"C");
Write_String(0x87,"SET:");
Write_String(0xc7,"SET:");
Write_String(0x8d,"-");
Write_String(0xcd,"-");
Display(0x8b,R_SETDOWN);
Display(0x8e,R_SETTOP);
Display(0xcb,T_SETDOWN);
Display(0xce,T_SETTOP);
Display(0x82,RH_data);
Display(0xc2,TH_data);
place=0x8b; number = R_SETDOWN;
break; }
case 2:{ place=0x8e; number = R_SETTOP; break; }
case 3:{ place=0xcb; number = T_SETDOWN; break; }
case 4:{ place=0xce; number = T_SETTOP; break; }
case 5:{
Write_Instruction(0x01);//清屏
Write_String(0x80,"L:");
Write_String(0x84,"Lx");
Write_String(0x87,"SET:");
Display(0x8b,L_SETDOWN);
Write_String(0x8d,"-");
Display(0x8e,L_SETTOP);
Display(0x82,result);
place=0x8b; number = L_SETDOWN;
break; }
case 6:{ place=0x8e; number = L_SETTOP; break; }
default:{ break; }
}
}
}
Write_Instruction( place+1 );
if(jia==0||jian==0)
{
if(jia==0)
{
delay_ms(5);
if(jia==0)
{
while(!jia);
number++;
if(number>99)number=0;
Display(place,number);
}
}
if(jian==0)
{
delay_ms(5);
if(jian==0)
{
while(!jian);
if(number==0)
{
number=99;
goto ap;
}
number--;
ap: Display(place,number);
}
}
switch(x)
{
case 1:{ R_SETDOWN = number; break; }
case 2:{ R_SETTOP = number; break; }
case 3:{ T_SETDOWN = number; break; }
case 4:{ T_SETTOP = number; break; }
case 5:{ L_SETDOWN = number; break; }
case 6:{ L_SETTOP = number; break; }
default: break;
}
}
if(back==0)
{
delay_ms(5);
if(back==0)
{
num=0;
while(!back);
TR1=1;
}
}
}
}
/**********************AD转换**********************************************
* 名称 : dRead_ADC0832()
* 功能 : 将模拟信号转换成数字信号
* 输入 : Ch-通道选择
* 输出 : dat-转换值
*********************************************************************/
unsigned char Read_ADC0832(unsigned char Ch)
{
unsigned char i,dat; //定义变量
ADC0832_CS=1; //一个转换周期开始
ADC0832_CLK=0; //为第一个脉冲作准备
ADC0832_CS=0; //CS置0,片选有效
ADC0832_DIO=1; //DIO置1,规定的起始信号
ADC0832_CLK=1; //第一个脉冲
ADC0832_CLK=0; //第一个脉冲的下降沿,此前DIO必须是高电平
ADC0832_DIO=1; //DIO置1, 通道选择信号
ADC0832_CLK=1; //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别输入两位数据用于选择通道,这里选通道CH0
ADC0832_CLK=0; //第二个脉冲下降沿
ADC0832_DIO=Ch; //DI置0,选择通道0
ADC0832_CLK=1; //第三个脉冲
ADC0832_CLK=0; //第三个脉冲下降沿
ADC0832_DIO=1; //第三个脉冲下沉之后,输入端DIO失去作用,应置1
ADC0832_CLK=1; //第四个脉冲
for(i=0;i<8;i++) //高位在前
{
ADC0832_CLK=1; //第四个脉冲
ADC0832_CLK=0;
dat<<=1; //将下面储存的低位数据向右移
dat|=(unsigned char)ADC0832_DIO; //将输出数据DIO通过或运算储存在dat最低位
}
ADC0832_CS=1; //片选无效
return dat; //将读书的数据返回
}
/****初始化子函数*****/
void init() //通过定时器模拟PWM输出程序,控制电机的转速
{
TMOD=0x10; //设置单片机定时器工作方式
EA=1; //打开单片机总中断
ET1=1; //定时器T1中断允许
count=0;
TH1=(65536-43863)/256; //定时器T1的高8位设置初值,每50ms产生一次中断
TL1=(65536-43863)%256; //定时器T1的低8位设置初值,每50ms产生一次中断
TR1=0; //关闭定时器T1
// 。
}
/****************************************************************************/
//主函数
//TH,TL,RH,RL分别代表温湿度的整数和小数部分
void main()
{
uchar n;
BEEP=0;
R_SETDOWN = 40;
R_SETTOP = 70;
T_SETDOWN = 20;
T_SETTOP = 40;
L_SETDOWN=5;
L_SETTOP=40;
InitLCD(); //液晶初始化
init(); //定时器初始化
Write_Instruction(0x0c); //关光标
TR1=1;
while(1)
{
if(HW_check==0) { BEEP=1; } //热释电红外未检测到人体信号
else { BEEP=0; } //热释电红外检测到人体信号
if(count==0)
{
if(flash==0) //第一屏显示湿度、温度
{
Write_Instruction(0x01); //清屏
Write_String(0x80,"R:");
Write_String(0xc0,"T:");
Write_String(0x84,"%R");
Write_d(0xc4,0xdf); //显示℃
Write_String(0xc5,"C");
Write_String(0x87,"SET:");
Write_String(0xc7,"SET:");
Write_String(0x8d,"-");
Write_String(0xcd,"-");
Display(0x8b,R_SETDOWN); //显示湿度下限
Display(0x8e,R_SETTOP); //显示湿度上限
Display(0xcb,T_SETDOWN); //显示温度下限
Display(0xce,T_SETTOP); //显示温度上限
read_TRH(); //启动温湿度传感器检测
}
else //第二屏显示光照强度
{
Write_Instruction(0x01); //清屏
Write_String(0x80,"L:");
Write_String(0x84,"Lx");
Write_String(0x87,"SET:");
Display(0x8b,L_SETDOWN); //显示光照强度下限
Write_String(0x8d,"-");
Display(0x8e,L_SETTOP); //显示光照强度上限
}
TR1=1;
}
RH_data=RH_data; //获取湿度
if( RH_data<=R_SETDOWN ) { LED_ZS=0; LED_GZ=1;} //湿度低,增湿启动
else if( RH_data>=R_SETTOP ){ LED_ZS=1; LED_GZ=0;} //湿度高,干燥启动
else { LED_ZS=1; LED_GZ=1; } //湿度合适,停止增湿,停止干燥
TH_data=TH_data; //获取温度
if( TH_data<=T_SETDOWN ) { LED_JR=0; LED_ZL=1;} //温度低,加热启动
else if( TH_data>=T_SETTOP ){ LED_JR=1; LED_ZL=0;} //温度高,制冷启动
else { LED_JR=1; LED_ZL=1; } //温度合适,停止加热,停止制冷
for(n=1;n<7;n++)
{
AD_Value = Read_ADC0832(0); //获取光照强度
result0=(uchar)(((float)AD_Value+5)*50/251);
result=result+result0;
}
result=result/6;
if(result<=38)result=38-result;
else result=0;
if( result<=L_SETDOWN) { LED_BG=0;LED_ZG=1; } //光照强度值低,启动照明补光
else if(result>=L_SETTOP) { LED_BG=1;LED_ZG=0;}
else {LED_BG=1;LED_ZG=1;}
if(flash==0)
{
Display(0x82,RH_data); //显示湿度
Display(0xc2,TH_data); //显示温度
}
else
{
Display(0x82,result); //显示光照强度
}
if(jia==0) //在轮流显示模式,按【加】按键可以保持显示模式,按多一次取消保持显示模式
{
delay_ms(5);
if(jia==0)
{
while(!jia);
TR1=~TR1;
}
}
if(set==0)
{
delay_ms(5);
if(set==0)
{
while(!set);
Write_Instruction(0x0f); //开光标
TR1=0;
Write_Instruction(0x01);//清屏
Write_String(0x80,"R:");
Write_String(0xc0,"T:");
Write_String(0x84,"%R");
Write_d(0xc4,0xdf); //显示℃
Write_String(0xc5,"C");
Write_String(0x87,"SET:");
Write_String(0xc7,"SET:");
Write_String(0x8d,"-");
Write_String(0xcd,"-");
Display(0x8b,R_SETDOWN);
Display(0x8e,R_SETTOP);
Display(0xcb,T_SETDOWN);
Display(0xce,T_SETTOP);
Display(0x82,RH_data);
Display(0xc2,TH_data);
key_test();
Write_Instruction(0x0c); //关光标
}
}
}
}
/*******************************************************
函数功能:定时器T1的中断服务函数
********************************************************/
void Time1() interrupt 3 using 2 //定时器T1的中断编号为3,使用第2组工作寄存器
{
count++; //T1每中断1次,count加1
if(count==50) //若累计满20次,即计满1秒钟
{
count=0;
flash=~flash;
TR1=0;
}
TH1=(65536-43863)/256; //定时器T1高8位赋初值
TL1=(65536-43863)%256; //定时器T1低8位赋初值
}
|