#include<reg52.h>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
typedef enum keystate{initstate,affrimstate,singlestate,repeastate};
typedef enum ledstate{D0,D1,D2,D3,D4,D5,D6,D7};
sbit RS=P2^6;
sbit RW=P2^5;
sbit EN=P2^7;
sbit DQ=P3^7;
sbit DHT= P1^1 ;//DHT11
sbit key1=P3^0;
uint tempval;//温度值
uchar n; //正负标志
uchar flag;
uchar U8temp;
uchar U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
uchar U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
uchar U8comdata;
uchar DHTData1,DHTData2;
uchar data str[6]={0,0,0,0,0,0};
uchar data temp_data1[2]={0,0};
uchar data1[3];
uchar data dis_buf[8]={0,0,0,0,0,0,0,0};
uchar code ditab[16]=
{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
uchar temp;
uchar table1[]={"温度"};
uchar table[]={"."};
uchar table2[]={"C"};
uchar table3[]={":"};
uchar table6[]={"温度: "};
uchar table7[]={"湿度:"};
uchar table8[]={"%"};
uchar table9[]={"DHT11 显示"};
uchar keynum;
void keyprocess();
//温度传感器程序
void delay_us(uint i)
{
while(i--);
}
void ds1820rst() //ds1820复位
{ uchar x=0;
DQ = 1; //DQ复位
delay_us(4);
DQ = 0; //DQ拉低
delay_us(100);
DQ = 1; //拉高
delay_us(40);
}
uchar ds1820read()//18b20读数据
{ uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{ DQ = 0; //给脉冲信号
dat>>=1;
DQ = 1; //给脉冲信号
if(DQ)
dat|=0x80;
delay_us(10);
}
return(dat);
}
void ds1820write(uchar wdat)//写数据
{uchar i=0;
for (i=8; i>0; i--)
{ DQ = 0;
DQ = wdat&0x01;
delay_us(10);
DQ = 1;
wdat>>=1;
}
}
void read_temp() //读取温度值并转换
{
ds1820rst(); //复位
ds1820write(0xcc); //跳过读序列号
ds1820write(0xbe); //读取温度
temp_data1[0]=ds1820read(); //高位
temp_data1[1]=ds1820read(); //低位
ds1820rst(); //复位
ds1820write(0xcc); //跳过读序列号
ds1820write(0x44); //启动温度转换
}
void ds1820display() //温度值显示
{
if(temp_data1[1]>127) // 温度值正负判断
{temp_data1[1]=(255-temp_data1[1]);temp_data1[0]=(255-temp_data1[0]);n=1;} // 负温度求补码
dis_buf[0]=temp_data1[0]&0x0f; // 取小数部分的值
dis_buf[1]=ditab[dis_buf[0]]+0x30; // 存入小数部分显示值
dis_buf[2]=((temp_data1[0]&0xf0)>>4)|((temp_data1[1]&0x0f)<<4); // 取中间八位,即整数部分的值
dis_buf[3]=dis_buf[2]/100+0x30; // 取百位数据暂存
dis_buf[4]=dis_buf[2]%100/10+0x30; // 取十位数据暂存
dis_buf[5]=dis_buf[2]%100%10+0x30;
if(dis_buf[3]==0x30)
{ dis_buf[3]=0x20; //最高位为0时不显示 百位
if(dis_buf[4]==0x30)
{
dis_buf[4]=0x20; //十位为0时不显示 十位
}
}
if( dis_buf[3]==0) //符号位位0,则显示“-”
{
n=0x2d;
}
else
{
n=0x20;
}
}
void delay(uint t)
{
uchar i,j;
for(i=t;i>0;i--)
for(j=0;j<120;j++);
}
void busy()
{
P0=0xff;
delay(5);
RS=0;
RW=1;
EN=1;
while(P0&0x80);
delay(5);
EN=0;
}
void lcdwritecommand(uchar cmd)
{
busy();
delay(5);
RS=0;
RW=0;
EN=0;
P0=cmd;
EN=1;
delay(5);
EN=0;
}
void lcdwritedata(uchar dat)
{
busy();
delay(20);
RS=1;
RW=0;
EN=0;
P0=dat;
EN=1;
delay(5);
EN=0;
}
void pos(uchar *p)
{
while(*p!='\0')
{
lcdwritedata(*p);
p++;
delay(5);
}
}
void lcdinit()
{
keyprocess();
lcdwritecommand(0x30);
delay(5);
lcdwritecommand(0x01);
delay(5);
lcdwritecommand(0x0c);
delay(5);
}
void Delay_10us(void)
{
uchar i;
i--;
i--;
i--;
i--;
i--;
i--;
}
void COM(void)
{
uchar i;
for(i=0;i<8;i++)
{
flag=2;
while((!DHT)&&flag++);
Delay_10us();
Delay_10us();
Delay_10us();
U8temp=0;
if(DHT)U8temp=1;
flag=2;
while((DHT)&&flag++);
//超时则跳出for循环
if(flag==1)break;
//判断数据位是0还是1
// 如果高电平高过预定0高电平值则数据位为 1
U8comdata<<=1;
U8comdata|=U8temp; //0
}//rof
}
void RH(void)
{
//主机拉低18ms
DHT=0;
delay(180);
DHT=1;
//总线由上拉电阻拉高 主机延时20us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
//主机设为输入 判断从机响应信号
DHT=1;
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!DHT) //T !
{
flag=2;
//判断从机是否发出 80us 的低电平响应信号是否结束
while((!DHT)&&flag++);
flag=2;
//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
while((DHT)&&flag++);
//数据接收状态
COM();
U8RH_data_H_temp=U8comdata;
COM();
U8RH_data_L_temp=U8comdata;
COM();
U8T_data_H_temp=U8comdata;
COM();
U8T_data_L_temp=U8comdata;
COM();
U8checkdata_temp=U8comdata;
DHT=1;
//数据校验
U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
if(U8temp==U8checkdata_temp)
{
U8RH_data_H=U8RH_data_H_temp;
U8RH_data_L=U8RH_data_L_temp;
str[1]=(U8RH_data_H|U8RH_data_L)%100/10+0x30;//湿度十位
str[2]=(U8RH_data_H|U8RH_data_L)%100%10+0x30; //湿度个位
U8T_data_H=U8T_data_H_temp;
U8T_data_L=U8T_data_L_temp;
str[4]=(U8T_data_H|U8T_data_L)%100/10+0x30;
str[5]=(U8T_data_H|U8T_data_L)%100%10+0x30;
U8checkdata=U8checkdata_temp;
}
}
}
/**************按键函数*******************/
void timer0(void)
{
TMOD=0X01;
TH0=0XDC;
TL0=0X00;
TR0=1;
}
uchar keyscan(void)
{
static uchar keystatevalue=0;
static uchar presstime=0;
uchar num;
uchar key_value;
key_value=key1;
switch(keystatevalue)
{
case initstate:
if(key_value==0)
{
keystatevalue=affrimstate;
}
else
{
keystatevalue=initstate;
}
break;
case affrimstate:
if(key_value==0)
{
keystatevalue=singlestate;
}
else
{
keystatevalue=affrimstate;
}
break;
case singlestate:
presstime++;
if(presstime>100)
{
presstime=0;
keystatevalue=repeastate;
}
else if(key_value==1)
{
keystatevalue=initstate;
num++;
if(num==8)
{
num=0;
}
}
break;
case repeastate:
if(key_value==1)
{
keystatevalue=initstate;
}
presstime++;
if(presstime>10)
{
presstime=0;
num++;
if(num==8)
{
num=0;
}
}
break;
default:keystatevalue=initstate; break;
}
return num;
}
/*******DS18B20温度的显示*******/
void ds18b20xianshi()
{
lcdinit();
ds1820rst();
ds1820write(0xcc);//跳过读序列号
ds1820write(0x44);//启动温度转换
read_temp(); //读取温度
while(1)
{
read_temp(); //读取温度
ds1820display();
delay(200);
lcdwritecommand(0x80);
pos(table1);
pos(table3);
lcdwritedata(dis_buf[3]);
lcdwritedata(dis_buf[4]);
lcdwritedata(dis_buf[5]);
pos(table);
lcdwritedata(dis_buf[1]);
pos(table2);
}
}
void dht11xianshi()
{
/*******DHT11的显示*******/
lcdinit();
while(keynum!=3)
{
RH();
lcdwritecommand(0x88);
pos(table6);
lcdwritedata(str[4]);
lcdwritedata(str[5]);
pos(table2);
lcdwritecommand(0x90);
pos(table9);
lcdwritecommand(0x98);
pos(table7);
lcdwritedata(str[1]);
lcdwritedata(str[2]);
pos(table8);
}
}
void keyprocess(void)
{
if(TF0==1)
{
TF0=0;
TH0=0XDC;
TL0=0X00;
keynum=keyscan();
}
switch(keynum)
{
case D0: P1=0xfe;break;
case D1: P1=0xfd;break;
case D2: ds18b20xianshi();break;
case D3: dht11xianshi();break;
case D4: P1=0xef;break;
case D5: P1=0xdf;break;
case D6: P1=0xbf;break;
case D7: P1=0x7f;break;
default: P1=0xff;break;
}
}
/**********主函数*************************/
void main(void)
{ timer0();
while(1)
{
keyprocess();
}
}