一、概述
(1)DHT11
数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,应用领域:暖通空调;汽车;消费品;气象站;湿度调节器;除湿器;家电;医疗;自动控制
(2)特点
(3)接线
只有一根数据线 DATA ,上官一号发送序列指令给 DHT11 模块,模块一次完整的数据传输为 40bit, 高位先出
二、数据传输
(1)格式:
8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
(2)通讯过程时序图
三、详细设计
(1)检测模块是否存在
a : dht = 1b :dht = 0延时30msc: dht = 1在60us后读 d 点,如果 d 点是低电平(被模块拉低),说明模块存在(这里找60us是因为主机拉高是在20-40us,响应信号是过了80us之后,所以公共部分是40us-100us)
代码
#include "reg52.h" #include "intrins.h" sbit led1 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口 sbit led2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口 sbit DHT = P3^3; void Delay30ms() //@11.0592MHz { unsigned char i, j; i = 54; j = 199; do { while (--j); } while (--i); } void Delay60us() //@11.0592MHz { unsigned char i; i = 25; while (--i); } void Check_DHT() { DHT = 1;//开始时先拉高 DHT = 0;//再拉低 Delay30ms();//持续30ms DHT = 1;//再将其拉高 Delay60us();//过60us检测模块是否发送了低电平 if( DHT == 0 ){ led1 = 0; } } void Delay1000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); i = 8; j = 1; k = 243; do { do { while (--k); } while (--j); } while (--i); } void main() { Delay1000ms(); //延时1s,等待模块稳定 Delay1000ms(); led1 = 1; Check_DHT(); while(1);//死循环控制灯持续两者,防止程序退出看不到现象 }
(2)传输信息
由于DHT11每次发送40bit, 0-7bit传送的是湿度的整数部分,8-15bit是湿度的小数部分。16-23bit是温度的整数部分,24-31bit是温度的小数部分,最后8bit是校验位。所以我们可以定义一个char型数组, char datas[5],将每次的数据传入其中。
DHT11是低功耗,所以每传一次,需要唤醒
a : dht = 1b :dht = 0延时30msc: dht = 1卡d点; while(dht1);卡e 点 while(!dht)卡f 点: while(dht)卡g 点: while(!dht) 有效数据都是高电平,持续时间不一样,50us 读,低电平 0 高电平
DHT11传输0的时序分析
DHT11传输1的时序分析
读取温湿度的数据,并存入datas数组中
void ReadData_From_DHT() { int i; int j; char tmp; int flag; DHT_Start();//每次读一论都要用单片机唤醒一次,使其进从低功耗入工作模式 for(i=0;i<5;i++){ for(j=0;j<8;j++){ while(!DHT); //卡g点,即等待一个高电平 Delay60us();//延迟60us检测 if( DHT == 1){ flag = 1; while(DHT);//等低电平再出去 } else{ flag = 0; } tmp <<=1; tmp |=flag; } datas[i] = tmp; } }
(3)通过串口显示
将之前写的串口代码复制过来,修改整合,将数据通过串口显示出
void UartInit(void) //9600bps@11.0592MHz { PCON &= 0x7F; SCON &= 0x0F;//设置串行工作方式为8位波特率可变,REN允许串口收数据 SCON |= 0x50; TMOD &= 0x0F;//设置定时器1的工作方式为8位自动重装载定时器 TMOD |= 0x20; TL1 = 0xFD;//设置定时器初值 TH1 = 0xFD; TR1 = 1; //启动定时器1 } void sentByte(char data_msg) { SBUF = data_msg; //Delay10ms(); while(!TI); TI = 0; } void sentString(char *str) { while(*str){ sentByte(*str); str++; } } void Build_Data() { Humidity[0]='H'; Humidity[1]=':'; Humidity[2]=datas[0]/10+0x30; Humidity[3]=datas[0]%10+0x30; Humidity[4]='.'; Humidity[5]=datas[1]/10+0x30; Humidity[6]=datas[1]%10+0x30; Humidity[7]='\0'; Temperature[0]='T'; Temperature[1]=':'; Temperature[2]=datas[2]/10+0x30; Temperature[3]=datas[2]%10+0x30; Temperature[4]='.'; Temperature[5]=datas[3]/10+0x30; Temperature[6]=datas[3]%10+0x30; Temperature[7]='\0'; } void main() { Delay1000ms(); //延时1s,等待模块稳定 Delay1000ms(); UartInit(); LCD1602_Inite(); Delay1000ms(); led1 = 0; while(1){ Delay1000ms(); ReadData_From_DHT(); Build_Data(); sentString(" Humidity: "); sentString(Humidity); sentString("\r\n"); sentString(" Temperature: "); sentString(Temperature); sentString("\r\n"); } }
(4)再通过Lcd1602显示
加入lcd1602的初始化代码
void Check_Busy() { char temp = 0x80; dataBuffer = 0x80; while(temp & 0x80){ RS = 0; RW = 1; EN = 0; _nop_(); EN = 1; _nop_(); _nop_(); temp = dataBuffer; EN = 0; _nop_(); } } void Write_Cmd_Func(char cmd) { Check_Busy(); RS = 0; RW = 0; EN = 0; _nop_(); dataBuffer = cmd; _nop_(); EN = 1; _nop_(); _nop_(); EN = 0; _nop_(); } void Write_Data_Func(char dataShow) { Check_Busy(); RS = 1; RW = 0; EN = 0; _nop_(); dataBuffer = dataShow; _nop_(); EN = 1; _nop_(); _nop_(); EN = 0; _nop_(); } void LCD1602_Inite() { //(1)延时 15ms Delay15ms(); //(2)写指令 38H(不检测忙信号) Write_Cmd_Func(0x38); //(3)延时 5ms Delay5ms(); //(4)以后每次写指令,读/写数据操作均需要检测忙信号 //(5)写指令 38H:显示模式设置 Write_Cmd_Func(0x38); //(6)写指令 08H:显示关闭 Write_Cmd_Func(0x08); //(7)写指令 01H:显示清屏 Write_Cmd_Func(0x01); //(8)写指令 06H:显示光标移动设置 Write_Cmd_Func(0x06); //(9)写指令 0CH:显示开及光标设置 Write_Cmd_Func(0x0c); } void Lcd1602_Showline(char row,char col,char * pData) { switch(row){ case 1: Write_Cmd_Func(0x80+col); while(*pData){ Write_Data_Func(*pData); pData++; } break; case 2: Write_Cmd_Func(0x80+0x40+col); while(*pData){ Write_Data_Func(*pData); pData++; } break; } } void main() { Delay1000ms(); //延时1s,等待模块稳定 Delay1000ms(); UartInit(); LCD1602_Inite(); Delay1000ms(); led1 = 0; while(1){ Delay1000ms(); ReadData_From_DHT(); Build_Data(); sentString(" Humidity: "); sentString(Humidity); sentString("\r\n"); sentString(" Temperature: "); sentString(Temperature); sentString("\r\n"); Lcd1602_Showline(1,2,Humidity); Lcd1602_Showline(2,2,Temperature); } }