#include<reg52.h>
#include<12864.h>
#include<intrins.h>
sbit DHT = P0^0; //管脚定义,DHT11总线输入输出;
uchar data_byte;
uchar Tem_Z,Tem_X,Hum_Z,Hum_X,Check;
void LCD_Display(); //声明LCD_Display液晶显示函数;
void Rec_DHT(); //声明Rec_DHT,DHT11接收数据函数;
void receive();
//主函数
void main()
{
lcd_init();
while(1)
{
Rec_DHT();
LCD_Display();
delayms(1000);
}
}
//延时函数,//延时ms
void delays()//@12.000MHz
{
uchar i, j, k;
i = 1;
j = 234;
k = 113;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
//延时ius
void delay10us()
{
uchar i;
for(i=0;i<6;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
/********主机发出开始信号*******/
void DHT11_Start()
{
DHT=1;
delay10us();
DHT=0;
delays(); //保持电平时间大于18ms,延时20ms
DHT=1;
delay10us(); //延迟等待20-40us,延时20us
delay10us();
delay10us();
delay10us();
DHT=1; //拉高等待DHT11响应
}
//DHT11接收一个字节数据
uchar receive_data()
{
uchar i,temp,count;
data_byte=0;
for(i=0;i<8;i++)
{
count=2;
while((!DHT)&&count++); //等待50us低电平结束
delay10us(); //等待40us高电平,后判断电平高低,高:DHT为1,低:DHT为0
delay10us();
delay10us();
delay10us();
temp=0;
if(DHT==1) temp=1; //DHT为高:1,位为1
count=2;
while((DHT)&&count++); //等待DHT高电平结束
if(count==1) break; //DHT为低:0,位为0
data_byte<<=1; //字节左移
data_byte|=temp;
}
return data_byte; //返回读取值
}
//DHT11接收数据
void Rec_DHT()
{
uchar flag;
uchar T_H,T_L,H_H,H_L,check,num_check; //定义采集参数中间变量
DHT11_Start(); //主机发出开始信号
if(!DHT) //等待从机响应信号输出低电平
{
flag = 2;
while((!DHT) && flag++); //判断从机是否发出 80us 的低电平响应信号是否结束
flag = 2;
while(DHT && flag++); //判断从机是否发出 80us 的高电平,若发出则开始采集数据
H_H=receive_data(); //采集湿度整数部分
H_L=receive_data(); //采集湿度小数部分
T_H=receive_data(); //采集温度整数部分
T_L=receive_data(); //采集温度小数部分
check=receive_data(); //采集校验位
DHT = 1;
num_check=H_H+H_L+T_H+T_L;
// if(num_check=check) //进行校核
// {
Hum_Z=H_H;
Hum_X =H_L;
Tem_Z =T_H;
Tem_X =T_L;
// }
}
}
/**********12864液晶显示*********/
void LCD_Display()
{
//液晶显示第一行:温度显示;
lcd_pos(1,1);
write_data('T');
write_data('e');
write_data('m');
write_data('p');
write_data(':');
write_data(Tem_Z/10+0x30); //输出温度的十位
write_data(Tem_Z%10+0x30); //输出温度的个位
write_data('.');
write_data(Tem_X/10+0x30); //输出温度的分位
write_data(Tem_X%10+0x30); //输出温度的十分位
write_data(0x27); //输出℃
write_data(0x43);
//液晶第二行:温度提示;
lcd_pos(2,4);
if(Tem_Z>35) write("注意防署");
else if(Tem_Z<15) write("注意防寒");
else write("温度适宜");
//液晶第三行:湿度显示;
lcd_pos(3,1);
write_data('H');
write_data('u');
write_data('m');
write_data(':');
write_data(Hum_Z/10+0x30); //输出湿度的十位
write_data(Hum_Z%10+0x30); //输出湿度的个位
write_data('.');
write_data(Hum_X/10+0x30); //输出湿度的分位
write_data(Hum_X%10+0x30); //输出湿度的十分位
write_data('%');
//液晶第四行:湿度提示;
lcd_pos(4,4);
if(Hum_Z>70) write("注意除湿");
else if(Hum_Z<40) write("注意除燥");
else write("湿度适宜");
}
//12864程序
#define uchar unsigned char //宏定义
#define uint unsigned int
//定义12864串口模式的引脚
sbit cs=P1^5; //片选,高电平有效
sbit sid=P1^6; //串行数据输入端
sbit sclk=P1^7; //串行同步时钟
sbit psb=P0^7; //串并口选择位,H=并口; L=串口
sbit rst=P0^6; //复位信号,低电平有效
//延时函数,延时xms
void delayms(uint xms)
{
uint i;
uchar j;
for(i=xms;i>0;i--) //单片机晶振频率为12MHZ;
for(j=120;j>0;j--){;} //单片机12倍速度运行
}
//12864写命令
void write_com(uchar com)
{
uchar i;
uchar i_data;
i_data=0xf8; //11111000-写指令0
cs=1;
sclk=0;
for(i=0;i<8;i++)
{
sid=(bit)(i_data&0x80);
sclk=0;
sclk=1;
i_data=i_data<<1;
}
i_data=com;
i_data&=0xf0;
for(i=0;i<8;i++)
{
sid=(bit)(i_data&0x80);
sclk=0;
sclk=1;
i_data=i_data<<1;
}
i_data=com;
i_data=i_data<<4;
for(i=0;i<8;i++)
{
sid=(bit)(i_data&0x80);
sclk=0;
sclk=1;
i_data=i_data<<1;
}
cs=0;
delayms(10);
}
//12864写数据
void write_data(uchar date)
{
uchar i;
uchar i_data;
i_data=0xfa; //写数据
cs=1;
for(i=0;i<8;i++)
{
sid=(bit)(i_data&0x80);
sclk=0;
sclk=1;
i_data=i_data<<1;
}
i_data=date;
i_data&=0xf0;
for(i=0;i<8;i++)
{
sid=(bit)(i_data&0x80);
sclk=0;
sclk=1;
i_data=i_data<<1;
}
i_data=date;
i_data=i_data<<4;
for(i=0;i<8;i++)
{
sid=(bit)(i_data&0x80);
sclk=0;
sclk=1;
i_data=i_data<<1;
}
cs=0;
delayms(10);
}
//lcd12864初始化
void lcd_init()
{
psb=0; //液晶屏为串行数据传输模式
rst=0; //复位
delayms(2);
rst=1;
delayms(2);
write_com(0x30); //基本指令, 扩充指令为34H
delayms(4);
write_com(0x02); //清除ddram
delayms(4);
write_com(0x0c); //显示开, 关光标
delayms(4);
write_com(0x01); //清屏
delayms(4);
}
//设定显示位置,x、y为12864轴坐标,x:1-4;y:1-16;
void lcd_pos(uchar x,uchar y)
{
uchar pos;
if(x==1) x=0x80; //x为第几行1-4;
else if(x==2) x=0x90;
else if(x==3) x=0x88;
else if(x==4) x=0x98;
pos=x+y-1;
write_com(pos);
}
//指定位置显示任意文字、字符
void write(uchar * str)
{
uchar i = 0;
while(str[i] != '\0')
{
write_data(str[i++]);
}
}
/*
//写数据时,要清除前面的显示,否则显示会覆盖在前面显示上
//清屏
void clean()
{
write_com(0x30);
write_com(0x01); //清屏
} */