1.DHT11温湿度传感器简介
DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度5~ 95%RH,温度-20 ~ +60℃。
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。产品为4针单排引脚封装,连接方便。
2.DHT11硬件接口
微处理器与 DHT11 的连接典型应用电路如上图所示, DATA 上拉后与微处理器的 I/O 端口相连。
1.典型应用电路中建议连接线长度短于 5m 时用 4.7K 上拉电阻,大于 5m 时根据实际情况降低上拉电
阻的阻值。
2. 使用 3.3V 电压供电时连接线尽量短,接线过长会导致传感器供电不足,造成测量偏差。
3. 每次读出的温湿度数值是上一次测量的结果,欲获取实时数据,需连续读取 2 次,但不建议连续多次
读取传感器,每次读取传感器间隔大于 2 秒即可获得准确的数据。
4. 电源部分如有波动,会影响到温度。如使用开关电源纹波过大,温度会出现跳动。
3.通讯协议
DHT11 器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备(主机或从机)通过一个漏枀开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约 4.7kΩ 的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结极,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
3.1 数据格式
-
单总线传送数据位定义
DATA 用于微处理器与 DHT11 之间的通讯和同步,采用单总线数据格式,一次传送 40 位数据,高位先 出。
-
数据格式:
8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据 + 8bit 校验位。
-
校验位数据定义
“8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据” 8bit 校验位等于所得结果的末 8 位。
-
示例一:接收到的 40 位数据为:
0011 0101 0000 0000 0001 1000 0000 01 00 0101 0001
湿度高 8 位 湿度低 8 位 温度高 8 位 温度低 8 位 校验位
-
计算:
0011 0101+0000 0000+0001 1000+0000 01 00= 0101 0001
-
接收数据正确:
湿度: 0011 0101(整数)=35H=53%RH 0000 0000(小数)=00H=0.0%RH =>53%RH+0.0%RH = 53.0%RH
**温度:** 0001 1000(整数)=18H=24℃ 0000 0100(小数)=04H=0.4℃ =>24℃ + 0.4℃ = 24.4℃
-
特殊说明:
当温度低于 0 ℃ 时温度数据的低 8 位的最高位置为 1。
示例: -10.1 ℃ 表示为 0000 1010 1000 0001
温度: 0000 1010(整数)=0AH=10℃, 0000 0001(小数)=01H=0.1℃ =>-(10℃+0.1℃)= -10.1℃
3.2时序图
用户主机( MCU)发送一次开始信号后, DHT11 从低功耗模式转换到高速模式,待主机开始信号结束后, DHT11 发送响应信号,送出 40bit 的数据,并触发一次信采集。信号发送如图所示。
注:主机从 DHT11 读取的温湿度数据总是前一次的测量值,如两次测间隔时间很长,请连续读两次以第二次获得的值为实时温湿度值。
3.3 数据读取
DHT11 上电后( DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令),测试环境温湿度数据,并记录数据,同时 DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电平;此时 DHT11 的DATA 引脚处于输入状态,时刻检测外部信号。
1.发送起始信号
DHT11模块空闲电平为高电平,主机发起起始信号,10~30ms的低电平,然后释放总线。
void DHT11_Rst(void)
{
DHT11_IO_OUT();
DHT11_DQ_OUT=0;
Delay_Ms(20);
DHT11_DQ_OUT=1;
Delay_Us(30);
}
2.从机响应信号
DHT11收到信号后将返回83us的低+87us高电平。
/***********等待DHT11的回应***************
**返回1:未检测到DHT11的存在
**返回0:存在
*******************************************/
u8 DHT11_Check(void)
{
u8 retry=0;
DHT11_IO_IN();//配置为输入模式
while (!DHT11_DQ_IN&&retry<100)//DHT11会拉低83us左右
{
retry++;
Delay_Us(1);
}
if(retry>=100)return 1;
while (DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高87us
{
retry++;
Delay_Us(1);
}
if(retry>=100)return 1;
else retry=0;
return 0;
}
4.数据读取
数据0格式:54us低 + 23us ~ 27us高
数据0格式:54us低 + 68us~74us高
/*******************读取1bit数据***************
** 数字0: 58us低电平,23~27us高电平
** 数字1:58us低电平,68~74us高电平
**返回值:1/0
*************************************************/
u8 DHT11_Read_Bit(void)
{
u8 retry=0;
while(DHT11_DQ_IN&&retry<100)//等待变为低电平
{
retry++;
Delay_Us(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry<100)//等待变高电平
{
retry++;
Delay_Us(1);
}
Delay_Us(40);//等待40us
if(DHT11_DQ_IN)return 1;
else return 0;
}
/**************读取1byte数据*************
**
**从DHT11读取一个字节
**返回值:读到的数据
**
******************************************/
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
u8 DHT11_Read_Data(u8 *temp,u8 *humi)
{
u8 buf[5]={0};
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi++=buf[0];
*humi=buf[1];
*temp++=buf[2];
*temp=buf[3];
}
}else return 1;
return 0;
}
4.数据采集与显示
OLED_Init();
TIM2_Init(72,20000);
TIM3_PWM_Out(1,72,1000,1000);
if(DHT11_Init())//初始化DHT11
{
printf("DHT11初始化失败\r\n");
}
printf("初始化完成\r\n");
BEEP_ON;
Delay_Ms(100);
BEEP_OFF;
RTC_Init();
printf("初始化完成\r\n");
OLED_ClearGram(0xff);
OLED_DisplayFont(32,0,16,13);
OLED_DisplayFont(32+16,0,16,14);
OLED_DisplayFont(32+16*2,0,16,15);
OLED_DisplayFont(32+16*3,0,16,16);
OLED_DisplayFont(0,16,24,19);
OLED_DisplayFont(0+24,16,24,21);
OLED_DisplayFont(0,40,24,20);
OLED_DisplayFont(0+24,40,24,21);
OLED_Refresh();
while(1)
{
DHT11_Read_Data(temp,humi);
dht11_temp=temp[0]+temp[1]*0.1;
dht11_humi=humi[0];
sprintf((char *)data,":%02d.%1d",temp[0],temp[1]);
OLED_DisplayStr(24*2,16,12,24,(char *)data);
OLED_DisplayFont(24*2+12*5,24,16,12);
sprintf((char *)data,":%02d",humi[0]);
OLED_DisplayStr(24*2,40,12,24,(char *)data);
OLED_DisplayStr(24*2+12*3,48,8,16,(char *)" %RH");
OLED_Refresh();
if(dht11_temp>=30 || dht11_humi>=60)
{
stat=1;
}
else
{
stat=0;
BEEP_OFF;
}
Delay_Ms(1);
time++;
if(stat==1 && time>=10)
{
time=0;
falg=!falg;
if(falg)BEEP_ON;
else BEEP_OFF;
}
}
采用0.96寸OLED实现温湿度显示,无源蜂鸣器实现阈值报警。