DHT11检测温湿度求教

如题所述

第1个回答  2017-04-17
‍使用51单片机,12M晶振,LCD1206液晶显示屏显示

DHT11使用SPI单总线通讯协议进行通信,对延时程序的精度要求较高,如果得不到结果的话大部分都是延时有问题。

#include"reg52.h" //头文件
#define uint unsigned int
#define uchar unsigned char
int humi,temp,check;
uchar n,Readflag; //定义全局变量
sbit SPI = P1^1;
sbit RS = P2^4;
sbit RW = P2^5;
sbit EN = P2^6; //定义端口
void delayms(uchar ms);
void Init_Timer0(void); //函数声明
void write_com(uchar com) //LCD1206端口写函数
{
RS=0;
P0=com;
delayms(5);
EN=1;
delayms(5);
EN=0;
}
void write_data(uchar date) //LCD1206数据写函数
{
RS=1;
P0=date;
delayms(5);
EN=1;
delayms(5);
EN=0;
}
void LCD1602_init() //LCD1206初始化函数
{
RW=0;
EN=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
void Display_Humi(int v,unsigned char position) ////////////湿度显示函数
{
int shu;
write_com(position);
write_data('R');
write_data('H');
shu=v%100/10;
write_data(shu+'0');
shu=v%10;
write_data(shu+'0');
write_data('%');
}
void Display_Temp(int v,unsigned char position) ///////////温度显示函数
{
int shu;
write_com(position);
write_data('T');
write_data('e');
write_data('m');
write_data('p');
write_data(':');
shu=v%100/10;
write_data(shu+'0');
shu=v%10;
write_data(shu+'0');
write_data(0xdf);
write_data('C');
}
void Display_Check(int v,uchar position) //校验位显示函数
{
int shu;
write_com(position);
write_data('C');
write_data('h');
write_data('e');
write_data('c');
write_data('k');
write_data(':');
shu=v/100;
write_data(shu+'0');
shu=v%100/10;
write_data(shu+'0');
shu=v%10;
write_data(shu+'0');
}
void delayms(uchar ms) //精确延时毫秒级函数
{
uchar i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
void delayus(uchar us) //精确延时微秒级函数
{
while(us--);
}
void DHT_Rst() //DHT11启动函数
{
SPI=0; //主机拉低总线18ms以上
delayms(20);
SPI=1; //主机拉高总线约30us
delayus(14);/// 20-40us
while(SPI); //等待DHT11响应
while(!SPI); //等待DHT11拉高总线
}
uchar Readbit() //读一位程序
{
while(SPI);//等待总线变为低电平
while(!SPI);//等待总线变为高电平
delayus(5);//等待10us,执行下几条程序使用约20us
if(SPI)
return 1;
else
return 0; //////判断SPI总线状态,返回0或1
}
uchar Readbyte() //读一个字节程序
{
uchar i,dat;
dat=0;
for(i=0;i<8;i++) //重复读取8位数据
{
dat=dat<<1; //dat左移一次,总共8次
dat=Readbit()|dat; //dat和返回值,按位或
}
return dat; //返回dat
}
void ReadDHT() //读DHT11温湿度传感器
{
uchar buf[5],i; //定义临时变量
DHT_Rst(); //初始化传感器
for(i=0;i<5;i++) //读5字节,共40位
buf[i]=Readbyte();
SPI=1; //通讯结束,拉高总线
if(buf[0]+buf[1]+buf[2]+buf[3]==buf[4])//数据校验
{
humi=buf[0];//湿度值
temp=buf[2];//温度值
check=buf[4];//校验位值,校验位=湿度值+温度值(小数位为零)
}
}
void main() //主函数
{
Init_Timer0(); //初始化定时器
Readflag=0; //读标志位为0
LCD1602_init(); //初始化LCD1602液晶显示屏
while(1) //主循环
{
if(Readflag==1) //验证是否读
{
Readflag=0; //重置读标志位
ReadDHT(); //读一次DHT11
}
Display_Temp(temp,0x80);
Display_Humi(humi,0x8A);
Display_Check(check,0xc0); /////显示值
}
}

void Init_Timer0(void) //定时器初始化函数
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
void Timer0_isr(void) interrupt 1 //定时器中断服务程序
{
static unsigned int num;
TH0=(65536-10000)/256; //重新赋值 10ms
TL0=(65536-10000)%256;
num++;
if(num==20) //大致200ms
{
num=0;
Readflag=1; //激活读命令
}
}

纯手打,望采纳
相似回答