#include <reg51.h>
#include"stdio.h"
#include"intrins.h"
#define OK 1
#define ERROR 0
extern void Delay_1ms(unsigned int ms);
//函数的返回值表示读取数据是否成功 OK 表示成功 ERROR 表示失败
extern unsigned char DHT11_ReadTempAndHumi(void);
sbit dht11 = P2^0; //IO口定义
//防止在与硬件通信时发生死循环的计数范围
#define NUMBER 120 //20 12T
#define SIZE 5
static unsigned char status;
unsigned char tempshi,tempge;
//存放五字节数据的数组
static unsigned char value_array[SIZE];
/*可在其他的文件引用温湿度值,实际是温度的整数的10 倍
如dht11 读回的温度是26,则temp_value = 260, 湿度同理*/
int temp_value, humi_value;
static unsigned char ReadValue(void);
void serial_init(){
TMOD=0x20;
TH1=0xfd;
TL1=0xfd; //设置9600波特率
SCON=0x50; //串口方式1,允许接收
TR1=1;
}
void main(){
serial_init();
while(1){
if(DHT11_ReadTempAndHumi()==OK){
TI=1;
SBUF=temp_value;
TI=0;
Delay_1ms(1000);
TI=1;
SBUF=humi_value;
TI=0;
Delay_1ms(1000);
}
else if(DHT11_ReadTempAndHumi()==ERROR){
TI=1;
SBUF=0x01;
TI=0;
Delay_1ms(1000);
}
}
}
extern void Delay_1ms(unsigned int a){ //延时约1ms
unsigned int i;
while (--a!=0)
for(i=600;i>0;i--);
}
static void DHT11_Delay_10us(void){
unsigned char i;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
i--;
}
/*读一个字节的数据*/
static unsigned char DHT11_ReadValue(void){
unsigned char count, value = 0, i;
status = OK; //设定标志为正常状态
for(i = 8; i > 0; i--){
//高位在先
value <<= 1;
count = 0;
//每一位数据前会有一个50us 的低电平时间.等待50us 低电平结束
while(dht11 == 0 && count++ < NUMBER);
if(count >= NUMBER){
status = ERROR; //设定错误标志
return 0; //函数执行过程发生错误就退出函数
}
//26-28us 的高电平表示该位是0,为70us 高电平表该位1
DHT11_Delay_10us();
DHT11_Delay_10us();
DHT11_Delay_10us();
//延时30us 后检测数据线是否还是高电平
if(dht11 != 0){
//进入这里表示该位是1
value++;
//等待剩余(约40us)的高电平结束
while(dht11 != 0 && count++ < NUMBER){
dht11 = 1;
}
if(count >= NUMBER){
status = ERROR; //设定错误标志
return 0;
}
}
}
return (value);
}
//读温度和湿度函数,读一次的数据,共五字节,读出成功函数返回OK, 错误返回ERROR
extern unsigned char DHT11_ReadTempAndHumi(void){
unsigned char i = 0, check_value = 0,count = 0;
//EA = 0;
dht11 = 0; //拉低数据线大于18ms 发送开始信号
Delay_1ms(20); //需大于18 毫秒
dht11 = 1; //释放数据线,用于检测低电平的应答信号
//延时20-40us,等待一段时间后检测应答信号,应答信号是从机拉低数据线80us
DHT11_Delay_10us();
DHT11_Delay_10us();
DHT11_Delay_10us();
DHT11_Delay_10us();
if(dht11 != 0){ //检测应答信号,应答信号是低电平
//没应答信号
// EA = 1;
return ERROR;
}
else{
//有应答信号
while(dht11 == 0 && count++ < NUMBER); //等待应答信号结束
if(count >= NUMBER){ //检测计数器是否超过了设定的范围
dht11 = 1;
// EA = 1;
return ERROR; //读数据出错,退出函数
}
count = 0;
dht11 = 1;//释放数据线
//应答信号后会有一个80us 的高电平,等待高电平结束
while(dht11 != 0 && count++ < NUMBER);
if(count >= NUMBER){
dht11 = 1;
// EA = 1;
return ERROR; //退出函数
}
//读出湿.温度值
for(i = 0; i < SIZE; i++){
value_array[i] = DHT11_ReadValue();
if(status == ERROR){ //调用ReadValue()读数据出错会设定status 为ERROR
dht11 = 1;
// EA = 1;
return ERROR;
}
//读出的最后一个值是校验值不需加上去
if(i != SIZE - 1){
//读出的五字节数据中的前四字节数据和等于第五字节数据表示成功
check_value += value_array[i];
}
}//end for
//在没用发生函数调用失败时进行校验
if(check_value == value_array[SIZE - 1]){
//将温湿度扩大10 倍方便分离出每一位
humi_value = value_array[0] * 10;
temp_value = value_array[2] * 10;
dht11 = 1;
// EA = 1;
return OK; //正确的读出dht11 输出的数据
}
else{
//校验数据出错
// EA = 1;
return ERROR;
}
}
}
/*****************************************************************************/
/*****************************************************************************/
/************************************************************************/