熱度 3|
#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();
}
}