第3-2讲:温湿度传感器DHT11
-
- 学习目的
- 了解DHT11数字温湿度传感器的基本原理及其数据格式。
- 掌握STC8A8K64D4与DHT11单总线通信的程序设计,通信步骤,数据校验等。
- 硬件电路设计
- 湿敏元件简介
- 硬件电路设计
湿敏元件是最简单的湿度传感器。湿敏元件比较常见的是电阻式湿敏元件和电容式湿敏元件。除此之外,还有电解质离子型湿敏元件、重量型湿敏元件(利用感湿膜重量的变化来改变振荡频率)、光强型湿敏元件、声表面波湿敏元件等。下面就电阻式湿敏元件和电容式湿敏元件进行介绍。
电阻式湿敏元件一般指的是湿敏电阻,湿敏电阻的特点是在基片上覆盖一层用感湿材料制成的膜,当空气中的水蒸气吸附在感湿膜上时,元件的电阻率和电阻值都发生变化,利用这一特性即可测量湿度。湿敏电阻的种类很多,例如金属氧化物湿敏电阻、硅湿敏电阻、陶瓷湿敏电阻等。
湿敏电阻的优点是灵敏度高,主要缺点是线性度和产品的互换性差。
电容式湿敏元件一般指的就是湿敏电容,湿敏电容一般是用高分子薄膜电容制成的,常用的高分子材料有聚苯乙烯、聚酰亚胺、酷酸醋酸纤维等。当环境湿度发生改变时,湿敏电容的介电常数发生变化,使其电容量也发生变化,其电容变化量与相对湿度成正比。
湿敏电容的主要优点是灵敏度高、产品互换性好、响应速度快、湿度的滞后量小、便于制造、容易实现小型化和集成化,其精度一般比湿敏电阻要低一些。
湿敏元件的线性度及抗污染性差,在检测环境湿度时,湿敏元件要长期暴露在待测环境中,很容易被污染而影响其测量精度及长期稳定性。
温度的概念大家比较了解,下面重点介绍下与湿度有关的知识点。湿度,一般在气象学中指的是空气湿度,他是空气中水蒸气的含量。空气中液态或固态的水不算在湿度中,不含水蒸气的空气被称为干空气。下面介绍与湿度有关的3个概念。
- 相对湿度(Relative Humidity)是指气体中(通常为空气中)所含水蒸气量(水蒸气压)与其空气相同情况下饱和水蒸气量(饱和水蒸气压)的百分比,一般用百分数表示。通常所说的湿度都是指相对湿度,比如说某个房间的湿度为60%,即指该房间的相对湿度是60%。
- 绝对湿度是指一定体积的空气中含有的水蒸气的质量,一般其单位是克/立方米。绝对湿度的最大限度是饱和状态下的最高湿度。绝对湿度只有与温度一起才有意义,因为空气中能够含有的湿度的量随温度而变化,在不同的温度中绝对湿度也不同,因为随着温度的变化空气的体积也要发生变化。但绝对湿度越靠近最高湿度,他随温度的变化就越小。
- 饱和湿度是表示在一定温度下,单位容积空气中所能容纳的水蒸气量的最大限度。如果超过这个限度,多余的水蒸气就会凝结,变成水滴,此时的空气湿度便称为饱和湿度。
他们之间的关系是:相对湿度 = 绝对湿度 / 饱和湿度×100% 。
-
-
- DHT11数字温湿度传感器
-
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,也是一款电容式湿度传感器。他应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
图1:DHT11数字温湿度传感器实物图
- DHT11数字温湿度传感器的规格参数
DHT11数字温湿度传感器的规格参数如下表所示。
表1:DHT11数字温湿度传感器规格参数
DHT11管脚号 | 功能描述 |
工作电压 | 3.3V~5.5V。 |
外形尺寸 | 23.2(L)mm×12.5(W)mm。 |
测量范围 | 温度:-20~+60℃ 湿度:5~95%RH。 |
精度 | 温度:±2℃。 湿度:±5%RH(25℃)。 |
分 辨 率 | 温度:0.1℃。 湿度:1%RH。 |
衰 减 值 | 温度:<0.1℃/年。 湿度:<1%RH/年。 |
输出信号 | 单总线数字信号。 |
外壳材料 | ABS塑料。 |
重量 | 1g。 |
引脚数 | 4个。 |
- DHT11数字温湿度传感器的管脚定义
DHT11数字温湿度传感器的引脚定义如下。
图2:DHT11数字温湿度传感器管脚号
4个引脚的功能如下表所示。
表2:DHT11数字温湿度传感器引脚定义
DHT11管脚号 | 管脚名 | 功能描述 |
1 | VCC | 供电,(3.3~5.5)V。 |
2 | DATA | 串行数据,单总线。 |
3 | NC | 空脚。 |
4 | GND | 接地,电源负极。 |
-
-
- DHT11接口电路
-
IK-64D4开发板上设计了DHT11数字温湿度传感器接口,电路如下图所示,这里需要注意的是DHT11的DATA引脚需要上拉,建议连接线长度短于5m时用4.7K上拉电阻,大于5m时根据实际情况降低上拉电阻的阻值,开发板上连接DHT11的线长比较短,因此,开发板用的是10K上拉电阻。
图3:DHT11接口电路
DHT11占用的STC8A8K64D4的引脚如下表:
表3:DHT11引脚分配
DHT11 | 引脚 | 说明 |
DHT11数据 | P7.0 | 和DAC电路的输入共用 |
-
- 软件设计
- DHT11应用步骤
- 软件设计
DHT11数字温湿度传感器采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其他设备使用总线;单总线通常要求外接一个约4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。由于他们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
MCU作为单总线通信的主机与DHT11从机之间通信的步骤如下图所示,共需4个步骤。
图4:MCU与DHT11单总线通信步骤
- MCU向DHT11发送起始信号
DHT11上电后要等待1S以越过不稳定状态,在此期间不能发送任何指令。MCU的I/O此时配置为输入,因为DHT11的DATA数据线接了上拉电阻,因此保持高电平。
MCU从DHT11读取温湿度数据时,首先发送起始信号,即MCU配置I/O为输出,同时输出低电平,且低电平保持时间不能小于18ms(最大不得超过30ms),然后MCU的I/O设置为输入状态,由于上拉电阻,微处理器的I/O即DHT11的DATA数据线也随之变高,等待DHT11作出回答信号。
图5:起始信号时序
- DHT11向MCU发送响应信号
DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的DATA引脚处于输出状态,输出83微秒的低电平作为应答信号,紧接着输出87微秒的高电平通知外设准备接收数据,MCU的I/O此时处于输入状态,检测到I/O有低电平(DHT11回应信号)后,等待87微秒的高电平后的数据接收。
图6:DHT11响应信号时序
- DHT11向MCU发送5个字节数据
由DHT11的DATA引脚输出40位数据,MCU根据I/O电平的变化接收40位数据,“0”和“1”的格式定义如下:
- 位数据“0”:54us的低电平 + (23~27) us的高电平;
- 位数据“1”:54us的低电平 + (68~74) us的高电平。
图7:“0”和“1”的时序
40位数据包含了温湿度和校验,数据格式为:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位,其中湿度小数部分为0。
结束信号:DHT11的DATA引脚输出40位数据后,继续输出低电平54微秒后转为输入状态,由于上拉电阻随之变为高电平。但DHT11内部重测环境温湿度数据,并记录数据,等待外部信号的到来。
- MCU处理接收的数据
MCU接收完数据之后,需要检查数据的校验,以判断接收的数据是否正确,检查方式为:8bit校验位=8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据。
MCU解析温度数据时,需要注意DHT11正/负温度的表示方式:当温度低于0℃时温度数据的低8位的最高位置为1,否则为0。
- 正温示例
图8:正温度数据
- 负温示例
图9:负温度数据
-
-
- DHT11温湿度读取实验
-
- 注:本节的实验是在“实验2-6-1:串口1数据收发实验”的基础上修改,本节对应的实验源码是:“实验2-21-1:DHT11温湿度读取(串口发送温湿度)”。
-
-
- 实验内容
-
-
每2.5秒从DHT11读取一次温湿度数据并通过串口1输出温湿度数据。
-
-
-
- 代码编写
-
-
- 新建一个名称为“dht11.c”的文件及其头文件“dht11.h”并保存到工程的“Source”文件夹,并将“dht11.c”加入到Keil工程中的“SOURCE”组。
- 引用头文件
因为在“dht11.c”文件中使用了“dht11.c”文件中的函数,所以需要引用下面的头文件“dht11.h”。
代码清单:引用头文件
- //引用DHT11的头文件
- #include "dht11.h"
- 读取温湿度数据
按照前文描述的步骤,编写读取DHT11温湿度数据的代码。MCU首先向DHT11发送起始信号、之后等待DHT11向MCU发送响应信号,接收到响应信号后MCU继续接收DHT11向MCU发送的40位数据。注意数据读取完成后,需要检查数据的校验。
代码清单:读取温湿度数据
- /**************************************************************************************
- 功能描述 : 一次完整的数据传输为40bit,高位在前
- 参 数 : 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
- 返 回 值 : DHT11_SUCCESS:成功,DHT11_NACK:无应答,DHT11_DATA_ERR:数据校验错误
- **************************************************************************************/
- u8 Read_DHT11(DHT11_Data_t *DHT11_Data)
- {
- DATA_PIN = 0; //主机输出低电平
- delay_ms(20); //低电平时间不能小于18ms,不能超过30ms,这里延时20ms
- DATA_PIN = 1; //主机输出高电平
- Delay10us(); //延时30us
- Delay10us();
- Delay10us();
- if(!DATA_PIN) //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
- {
- //DHT11发出83us低电平应答信号。主机等待低电平结束
- if(waitfor_state(1)!=DHT11_SUCCESS)return DHT11_NACK;
- //DHT11发出87us高电平信号通知主机准备接收数据。主机等待高电平结束
- if(waitfor_state(0)!=DHT11_SUCCESS)return DHT11_NACK;
- //数据格式:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位
- //因此这里要连续读出5个字节
- DHT11_Data->h_int= Read_Byte();
- DHT11_Data->h_deci= Read_Byte();
- DHT11_Data->t_int= Read_Byte();
- DHT11_Data->t_deci= Read_Byte();
- DHT11_Data->check_sum= Read_Byte();
- DATA_PIN = 1; //主机输出高电平
- //校验:校验和=8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位
- if(DHT11_Data->check_sum == DHT11_Data->h_int + DHT11_Data->h_deci + DHT11_Data->t_int+
- DHT11_Data->t_deci)
- return DHT11_SUCCESS;
- else
- return DHT11_DATA_ERR;//校验错误,返回错误代码DHT11_DATA_ERR
- }
- else //DHT11无响应,返回错误代码DHT11_NACK
- {
- return DHT11_NACK;
- }
- }
上面代码中的23~27行,MCU通过调用Read_Byte()函数分5次接收DHT11的40位数据(40位共5个字节),这样更便于程序的处理。Read_Byte()函数代码清单如下。
代码清单:接收一个字节数据
- **********************************************************************************
- 功能描述:从DHT11读取一个字节,MSB在前
- 参 数:无
- 返 回 值:读取的数据
- ***********************************************************************************/
- static u8 Read_Byte(void)
- {
- u8 i, temp=0;
- //循环读取8个位
- for(i=0;i<8;i++)
- {
- //每bit以50us低电平标置开始。等待引脚状态变为高电平,100us无变化认为超时,退出函数
- if(waitfor_state(1)!=DHT11_SUCCESS)return DHT11_NACK;
- //DHT11以23~27us的高电平表示0,以68~74us的高电平表示1
- Delay10us(); //延时40us
- Delay10us();
- Delay10us();
- Delay10us();
- //40us后仍为高电平表示数据1
- if(DATA_PIN==1)
- {
- if(waitfor_state(0)!=DHT11_SUCCESS)return DHT11_NACK; //等待数据1的高电平结束,低电平到来
- temp|=(u8)(0x01<<(7-i)); //保存数据位“1”,MSB在前
- }
- else//40us后为低电平表示数据0
- {
- temp&=(u8)~(0x01<<(7-i)); //保存数据位“0”,MSB在前
- }
- }
- return temp;
- }
MCU在等待DHT11信号时,为了防止堵塞,我们在等待中加入超时时间,如果达到超时时间后,MCU等待的信号没有出现,则认为出现错误,程序退出等待,同时返回错误代码,这样就可以避免由于DHT11故障导致出现堵塞的问题,同时通过错误代码通知了应用程序故障原因。MCU等待DHT11信号的代码清单如下。
代码清单:等待DHT11信号
- /**********************************************************************************
- 功能描述:等待连接DHT11的引脚状态变化,为了防止DHT11损坏出现堵塞,设置超时时间为100us
- 参 数:[in]pin_state,0=低电平,1=高电平
- 返 回 值:DHT11_SUCCESS:成功,DHT11_NACK:无应答
- ***********************************************************************************/
- static u32 waitfor_state(u8 pin_state)
- {
- //超时时间100us,100us内引脚状态无变化,认为超时
- u8 delay_us = 10;
- do
- {
- //读取引脚状态,如引脚状态变化,函数运行结束,返回DHT11_SUCCESS
- if(DATA_PIN == pin_state)
- {
- return DHT11_SUCCESS;
- }
- Delay10us();
- delay_us--;
- }while(delay_us);
- return DHT11_NACK; //返回错误代码:DHT11_NACK
- }
- 主函数
主函数中配置连接DHT11数据引脚的GPIO P7.0为准双向后,之后在主循环里面使用Read_DHT11()函数每隔2.5秒读一次温湿度数据,并通过串口1输出数据。
代码清单:主函数
- /**********************************************************************************
- 功能描述:主函数
- 参 数:无
- 返 回 值:int类型
- ***********************************************************************************/
- int main(void)
- {
- u8 err_code;
- P2M1 &= 0xBF; P2M0 &= 0xBF; //设置P2.6为准双向口(指示灯D1)
- P3M1 &= 0xFE; P3M0 &= 0xFE; //设置P3.0为准双向口(串口1的RxD)
- P3M1 &= 0xFD; P3M0 |= 0x02; //设置P3.1为推挽输出(串口1的TxD)
- P7M1 &= 0xFE; P7M0 &= 0xFE; //设置P7.0为准双向口(DHT11数据)
- DATA_PIN=1; //总线拉高
- uart1_init(); //串口1初始化
- EA = 1; //使能总中断
- while(1)
- {
- err_code = Read_DHT11(&DHT11_Data); //从DHT11读取温湿度数据
- //判断函数返回值,读取成功,串口输出温湿度数据
- if(err_code==DHT11_SUCCESS)
- {
- printf("Temperature: %bd.%bd ℃ Humidity: %bd.%bd %RH\r\n",DHT11_Data.t_int,
- DHT11_Data.t_deci,DHT11_Data.h_int,DHT11_Data.h_deci);
- }
- else if(err_code==DHT11_DATA_ERR) //数据校验错误
- {
- printf("Data Checksum ERROR!\r\n");
- }
- else if(err_code==DHT11_NACK) //DHT11无应答
- {
- printf("No ack ERROR!\r\n");
- }
- else
- {
- }
- delay_ms(2500); //每次读取温湿度数据之间的间隔不能小于2秒
- led_toggle(LED_1); //指示灯D1状态翻转,指示程序的运行
- }
- }
-
-
- 硬件连接
-
-
本实验需要使用DHT11数字温湿度传感器,开发板需要将P7.0通过跳线连接到DHT11数字温湿度传感器,如下图所示。
图10:硬件连接
-
-
-
- 实验步骤
-
-
- 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验2-21-1:DHT11温湿度读取(串口发送温湿度)”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
- 双击“…\dht11\project”目录下的工程文件“dht11.uvproj”。
- 点击编译按钮编译工程,编译成功后生成的HEX文件“dht11.hex”位于工程的“…\dht11\Project\Object”目录下。
- 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
- 电脑上打开串口调试助手,选择开发板对应的串口号,将波特率设置为9600bps。
- 程序运行后,开发板每2.5秒读取一次DHT11的温湿度数据,每次读取时取反一次D1指示灯的状态指示程序的运行。读取的数据通过串口输出,电脑上打开串口调试助手,即可观察到读取的温湿度数据,如下图所示。
图11:串口接收的按键信息