DHT11传感器的原理非常简单(我只是解释了更多),但在使用中可能会遇到很多问题。大多数问题的本质是延迟函数。传统软件延迟和实际差异太大,所以尽量不要使用,我使用的晶体振动是11.0952MHZ,一个周期大约等于1Ms。没太啰嗦,直接上程序
#include<reg52.h> #include<intrins.h> ///包括所需的机械延迟 #define uint unsigned int #define uchar unsigned char /******************************* *********dht11相关配置********** ***只需直接调用数据接收函数即可**** *******************************/ sbit temp_date=P1^0; ///可以根据自己的界面自行修改 void dht11_start(); //让dht11开始发送数据 uchar rec_byte(); //回到字节 不要使用返回值void void dht11_receive(); //dht11接收数据的函数,start与rec_byte()均包含在其中 /*****LCD1602相关函数********* *RW接地可配置为低电平* **我用的P0端口需要增加拉电阻** *只需简单延时即可,无需复杂操作* *****************************/ void write_com(uchar com); //写命令 void write_data(uchar date);//写数据 void lcd1602init(); void delayms(uint z); sbit lcdrs=P3^5; //////根据实际情况自行配置 sbit lcden=P3^4; //////根据实际情况自行配置 /***********主函数**********/ void main() { delayms(1000); delayms(1000); //上电后等待元件启动 lcd1602init(); //1602初始化 while(1) { dht11_receive(); //接收温湿度数据已在1602中显示,当然可以自行调整 delayms(100); //没100Ms检测一次 } } /*开始*/ void dht11_start() { temp_date=1; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); temp_date=0; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); temp_date=1; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } /***********dht11相关子函数*************/ uchar rec_byte() //接收字节 { uchar i,dat=0; for(i=0;i<8;i ) ///从高到低依次接收8位数据 { while(!temp_date); //等待50us低电平过去 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); //延时40us,如果数据仍然很高,则为1,否则为0 dat<<=1; ///移位使8位数据正确接收,数据0直接移位 if(temp_date==1) //数据为1时,使dat加1接收数据1 dat =1; while(temp_date); //等待数据线拉低 } return dat; } void dht11_receive() ///接收数据的函数并显示 { uchar R_H,R_L,T_H,T_L,revise; ///分别是湿度、温度、效率 uchar RL,RH,TH,TL,sd1,sd2,wd1,wd2.//均匀使用的局部变量只能用于这个复合函数 //sd 湿拼音缩写 wd 温度拼音缩写 dht11_start(); if(temp_date==0) //判断是否响应 { while(temp_date==0); while(temp_date); /**接收数据**/ R_H=rec_byte(); R_L=rec_byte(); T_H=rec_byte(); T_L=rec_byte(); revise=rec_byte(); //准备检查 _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); if(R_H R_L T_H T_L==revise) //检查是否正确 { RH=R_H; RL=R_L; TH=T_H; TL=T_L; } /***************计算****************/ wd1=TH/10; wd2=TH; sd1=RH0/10; sd2=RH; temp_date=1; } write_com(0x80); //第一行从开始写 write_data('w'); write_data('e'); write_data('n'); write_data('d'); write_data('u'); write_data('0' wd1); write_data('0' wd2); write_data(' '); write_data(' '); write_data('s'); write_data('h'); write_data('i'); write_data('d'); write_data('u'); write_data('0' sd1); write_data('0' sd2); } /*********LCD1602相关子函数**********/ void write_com(uchar com) { lcdrs=0; P0=com; delayms(5); lcden=1; delayms(5); lcden=0; } void write_data(uchar date) { lcdrs=1; P0=date; delayms(5); lcden=1; delayms(5); lcden=0; } void lcd1602init() { lcden=0; write_com(0x38); write_com(0x0c); write_com(0x06); write_co(0x01);
}
/*************简单延时函数************/
void delayms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}