1.简介
温湿度计是一种用于测量和监测环境中温度和湿度的仪器,其工作原理基于热力学原理和物理原理。通过测量和显示环境中的温度和湿度,帮助用户了解当前环境的温湿度状况,从而采取相应的措施来调节或控制环境,以达到最佳的生产、存储或生活条件。
2.工作原理
温度传感器通常使用热敏电阻或热电偶等传感器来测量被测物体的温度。当被测物体的温度发生变化时,传感器会产生与温度相关的电阻或电压变化,这些变化会被转换成电信号或数字信号输出给仪表;湿度传感器常采用电容式湿度传感器来测量相对湿度。该传感器由一个金属氧化物电极和一个介质组成,介质中包含一个固定量的水分子。当被测物体的相对湿度发生变化时,介质中的水分子数量也会发生变化,从而导致电容值的变化,电容值的变化会被转换成数字信号输出给仪表。
3.分类与类型
温湿度计可按不同的标准进行分类,主要包括以下几种:
按测量方法分类:干湿球湿度计、露点温度计、毛发湿度计、库伦湿度计、电化学湿度计、光学型湿度计等。
按显示类型分类:指针温湿度计和数字温湿度计。指针温湿度计通过指针在表盘上的位置来指示温湿度值,而数字温湿度计则通过液晶屏幕以数字形式显示温湿度值。
按精度级别分类:民用温湿度计和工业温湿度计。工业温湿度计通常具有更高的测量精度和稳定性,适用于对温湿度要求较高的场合。
4.DHT11温湿度模块
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有枀高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。
4.1 硬件接口电路
注意:
微处理器与 DHT11 的连接典型应用电路如上图所示,DATA 上拉后与微处理器的 I/O 端口相连。
1.典型应用电路中建议连接线长度短于 5m 时用 4.7K 上拉电阻,大于 5m 时根据实际情况降低上拉电阻的阻值。
2. 使用 3.3V 电压供电时连接线尽量短,接线过长会导致传感器供电不足,造成测量偏差。
3. 每次读出的温湿度数值是上一次测量的结果,欲获取实时数据,需连续读取 2 次,但不建议连续多次读取传感器,每次读取传感器间隔大于 2 秒即可获得准确的数据。
4. 电源部分如有波动,会影响到温度。如使用开关电源纹波过大,温度会出现跳动。
硬件引脚说明:
引脚 | 说明 |
---|---|
VDD | 电源,工作电压3.3~5V |
DATA | 串行数据,单总线PA11引脚 |
NC | 空脚 |
GND | 电源地 |
DHT11 器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约 4.7kΩ 的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
4.2 单总线通讯简介
单总线传送数据位定义
DATA 用于微处理器与 DHT11 之间的通讯和同步,采用单总线数据格式,一次传送 40 位数据,高位先出。
数据格式:
8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据 + 8bit 校验位。
注:其中湿度小数部分为 0。
校验位数据定义:
“8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据”8bit 校验位等于,所得结果的末 8 位。
4.3 单总线时序
用户主机(MCU)发送一次开始信号后,DHT11 从低功耗模式转换到高速模式,待主机开始信号结束后,DHT11 发送响应信号,送出 40bit 的数据,并触发一次信采集。信号发送如图所示。
注:主机从 DHT11 读取的温湿度数据总是前一次的测量值,如两次测间隔时间很长,请连续读两次以第二次获得的值为实时温湿度值。
5.DHT11驱动示例
1.发送开始信号,等待设备响应。
主机发起时序:由主机拉低至少18ms,且不超过30ms。接着释放总线,等待从机响应。(释放总线,延时约20~40us)。
//IO方向设置
#define DHT11_IO_IN() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=0X00008000;}
#define DHT11_IO_OUT() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=0X00003000;}
IO操作函数
#define DHT11_DQ_OUT(x) HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin,(GPIO_PinState)x)
#define DHT11_DQ_IN HAL_GPIO_ReadPin(DHT11_GPIO_Port,DHT11_Pin) //数据端口 PA0 /*******起始信号***************/
void DHT11_Rst(void)
{ DHT11_IO_OUT(); //配置为输出模式DHT11_DQ_OUT(0); //总线拉低Delay_Ms(20); //拉低至少18msDHT11_DQ_OUT(1); //总线拉高Delay_Us(30); //主机拉高20~40us
}
从机响应信号:DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA引脚处于输出状态,输出 83 微秒的低电平作为应答信号,紧接着输出 87 微秒的高电平通知外设准备接收数据。
/***********等待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;
}
2.读取数据‘0’和数据‘1’。
位数据“0”的格式为: 54 微秒的低电平和 23-27 微秒的高电平;
位数据“1”的格式为: 54 微秒的低电平加 68-74微秒的高电平。
位数据“0”、“1”格式信号如图所示:
/*******************读取1bit数据***************
** 数字0: 50~58us低电平,23~27us高电平
** 数字1:50~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)//等待变高电平,第电平时间50~58us{retry++;Delay_Us(1);}Delay_Us(40);//等待40usif(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;
}
读取一次温湿度数据示例(5个字节):
//从DHT11读取一次数据
//temp:温度值-20~60℃
//humi:湿度值5~95%RH
//返回值:0,正常;1,读取失败
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++)//读取40位数据{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;
}
DHT11初始化
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在
u8 DHT11_Init(void)
{ /*1.开时钟*/ DHT11_Rst(); //复位DHT11return DHT11_Check();//等待DHT11的回应
}
6.温湿度采集
循环采集温湿度数据,实时显示在LCD屏幕上:
while(1)
{Delay_Ms(1);time++;if(time>=1000){if(DHT11_Read_Data((u8*)&temp,(u8*)&humidity)==0){//printf("温度:%d.%d℃ 湿度:%d %%\r\n",temp[0],temp[1],humidity[0]);if(lcd_show_flag==0){snprintf(buffer,sizeof(buffer),"%d.%dC ",temp[0],temp[1]);LCD_ShowStr(30,30,64,buffer,RED,WHITE);LCD_DrawLine(0,94,240,94,RED);LCD_DrawLine(0,95,240,95,RED);if(humidity[0]<100){snprintf(buffer,sizeof(buffer),"%02d%% ",humidity[0]);LCD_ShowStr(70,125,64,buffer,RED,WHITE);}LCD_DrawLine(0,189,240,189,RED);LCD_DrawLine(0,190,240,190,RED);}}time=0;}
}