DHT11温湿度传感器驱动
本帖最后由 bigfanofloT 于 2017-5-16 19:44 编辑一、DHT11介绍
DHT11是一款有已校准数字信号输出的温湿度传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。产品为4针单排引脚封装,连接方便。
主要性能指标如下:
测量范围:湿度20-90%RH, 温度0~50℃
分辨率:湿度1%RH, 温度1℃
精度:湿度+/-5%RH, 温度+/-2℃
量程:湿度20-90%RH, 温度0~50℃
供电电压 :3.3~5.5V DC
输 出:单总线数字信号
长期稳定性: <±1%RH/年
图1 DHT11实物图
DHT11输出单总线数字信号,可以十分方便的与MCU连接,典型使用方法如图2所示:
图2 DHT11典型应用电路
二、硬件连线
对于Gokit V2.3扩展板,板载DHT11的数字输出IO连接到了Arduino UNO接口的D3,如图3所示:
图3 Gokit V2.3扩展板DHT11原理图
根据Nucleo-F767ZI的原理图,图4可以知道,STM32F767ZIT6的GPIO PE13连接到了Arduino UNO接口的D3,因此在后面我们将配置PE13与DHT11通信,根据DHT11时序编写驱动。
图4 Nucleo-F767ZI的Arduino UNO接口原理图
三、DHT11时序
DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零。
操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。
通讯过程如下图:
总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
数字0信号表示方法如下图:
数字1信号表示方法.如下图:
四、完整程序
如下是DHT11驱动的完整代码,用户可以十分方便的移植到其它型号STM32或者MCU,只需修改GPIO定义、GPIO读写即可。Hal_temp_hum.h文件如下:
#ifndef _HAL_HEMP_HUM_H
#define _HAL_HEMP_HUM_H
#include <stdio.h>
#include "stm32f7xx_hal.h"<font color="#008000">//若用户使用了其它MCU,需要修改此处MCU相关头文件</font>
<font color="#008000">//Set GPIO Direction,若用户使用不同的GPIO请修改此处</font>
#define DHT11_DIN_Pin GPIO_PIN_13
#define DHT11_DIN_GPIO_Port GPIOE
<font color="#008000">//控制GPIO输出高低电平宏</font>
#define DHT11_DQ_OUT_1 HAL_GPIO_WritePin(DHT11_DIN_GPIO_Port, DHT11_DIN_Pin, GPIO_PIN_SET)
#define DHT11_DQ_OUT_0 HAL_GPIO_WritePin(DHT11_DIN_GPIO_Port, DHT11_DIN_Pin, GPIO_PIN_RESET)
<font color="#008000">//读取GPIO电平</font>
#define DHT11_DQ_IN HAL_GPIO_ReadPin(DHT11_DIN_GPIO_Port, DHT11_DIN_Pin)
#define MEAN_NUM 10
typedef struct
{
uint8_t curI;
uint8_t thAmount;
uint8_t thBufs;
}thTypedef_t;
/* Function declaration */
uint8_t dht11Init(void); //Init DHT11
uint8_t dht11Read(uint8_t *temperature, uint8_t *humidity); //Read DHT11 Value
static uint8_t dht11ReadData(uint8_t *temperature, uint8_t *humidity);
static uint8_t dht11ReadByte(void);//Read One Byte
static uint8_t dht11ReadBit(void);//Read One Bit
static uint8_t dht11Check(void);//Chack DHT11
static void dht11Rst(void);//Reset DHT11
void dht11SensorTest(void);
#endif /*_HAL_HEMP_HUM_H*/
Hal_temp_hum.c文件如下:
/**
******************
*
* @file Hal_temp_hum.c
* @author Gizwtis
* @version V03010100
* @date 2016-07-05
*
* @brief 机智云.只为智能硬件而生
* Gizwits Smart Cloudfor Smart Products
* 链接|增值ֵ|开放|中立|安全|自有|自由|生态
* www.gizwits.com
*
******************/
#include "hal_temp_hum.h"
#include <string.h>
thTypedef_t temphumTypedef;
void delayUs(uint32_t nus)
{
uint8_t i=0;
while(nus--)
{
i=100;<font color="#008000">//自己定义,需根据系统时钟调整</font>
while(i--) ;
}
}
void DHT11_IO_OUT(void)
{
GPIO_InitTypeDef myGPIO_InitStruct;
myGPIO_InitStruct.Pin = DHT11_DIN_Pin;
myGPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
myGPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_DIN_GPIO_Port, &myGPIO_InitStruct);
}
void DHT11_IO_IN(void)
{
GPIO_InitTypeDef myGPIO_InitStruct;
myGPIO_InitStruct.Pin = DHT11_DIN_Pin;
myGPIO_InitStruct.Pull = GPIO_PULLUP;
myGPIO_InitStruct.Mode = GPIO_MODE_INPUT;
myGPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_DIN_GPIO_Port, &myGPIO_InitStruct);
}
//Reset DHT11
static void dht11Rst(void)
{
DHT11_IO_OUT(); //SET OUTPUT
DHT11_DQ_OUT_0; //GPIOA.0=0
HAL_Delay(20); //Pull down Least 18ms
DHT11_DQ_OUT_1; //GPIOA.0=1
delayUs(30); //Pull up 20~40us
}
static uint8_t dht11Check(void)
{
uint8_t retry=0;
DHT11_IO_IN(); //SET INPUT
while (DHT11_DQ_IN && (retry<100)) //DHT11 Pull down 40~80us
{
retry++;
delayUs(1);
}
if(retry >= 100)
{
return 1;
}
else
{
retry=0;
}
while (!DHT11_DQ_IN&& (retry < 100)) //DHT11 Pull up 40~80us
{
retry++;
delayUs(1);
}
if(retry >= 100)
{
return 1; //check error
}
return 0;
}
static uint8_t dht11ReadBit(void)
{
uint8_t retry=0;
while(DHT11_DQ_IN && (retry<100)) //wait become Low level
{
retry++;
delayUs(1);
}
retry = 0;
while(!DHT11_DQ_IN && (retry < 100)) //wait become High level
{
retry++;
delayUs(1);
}
delayUs(30);//wait 40us
if(DHT11_DQ_IN)
{
return 1;
}
else
{
return 0;
}
}
static uint8_t dht11ReadByte(void)
{
uint8_t i,dat;
dat=0;
for (i=0; i<8; i++)
{
dat<<=1;
dat |= dht11ReadBit();
}
return dat;
}
static uint8_t dht11ReadData(uint8_t *temperature, uint8_t *humidity)
{
uint8_t buf;
uint8_t i;
dht11Rst();
if(0 == dht11Check())
{
for(i=0; i<5; i++)
{
buf = dht11ReadByte();
}
if(buf == (buf+buf+buf+buf))
{
*humidity = buf;
*temperature = buf;
}
}
else
{
return 1;
}
return 0;
}
uint8_t dht11Read(uint8_t *temperature, uint8_t *humidity)
{
uint8_t curTem = 0, curHum = 0;
uint16_t temMeans = 0, humMeans = 0;
uint8_t curI = 0;
uint8_t ret = 0;
ret = dht11ReadData(&curTem, &curHum);
if(1 != ret)
{
//Cycle store ten times stronghold
if(MEAN_NUM > temphumTypedef.curI)
{
temphumTypedef.thBufs = curTem;
temphumTypedef.thBufs = curHum;
temphumTypedef.curI++;
}
else
{
temphumTypedef.curI = 0;
temphumTypedef.thBufs = curTem;
temphumTypedef.thBufs = curHum;
temphumTypedef.curI++;
}
}
else
{
return (1);
}
if(MEAN_NUM <= temphumTypedef.curI)
{
temphumTypedef.thAmount = MEAN_NUM;
}
if(0 == temphumTypedef.thAmount)
{
//Calculate Before ten the mean
for(curI = 0; curI < temphumTypedef.curI; curI++)
{
temMeans += temphumTypedef.thBufs;
humMeans += temphumTypedef.thBufs;
}
temMeans = temMeans / temphumTypedef.curI;
humMeans = humMeans / temphumTypedef.curI;
*temperature = temMeans;
*humidity = humMeans;
}
else if(MEAN_NUM == temphumTypedef.thAmount)
{
//Calculate After ten times the mean
for(curI = 0; curI < temphumTypedef.thAmount; curI++)
{
temMeans += temphumTypedef.thBufs;
humMeans += temphumTypedef.thBufs;
}
temMeans = temMeans / temphumTypedef.thAmount;
humMeans = humMeans / temphumTypedef.thAmount;
*temperature = (uint8_t)temMeans;
*humidity = (uint8_t)humMeans;
}
return (0);
}
uint8_t dht11Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Migrate your driver code */
__HAL_RCC_GPIOE_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, DHT11_DIN_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PBPin PBPin PBPin */
GPIO_InitStruct.Pin = DHT11_DIN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
dht11Rst();
memset((uint8_t *)&temphumTypedef, 0, sizeof(thTypedef_t));
printf("dh11Init \r\n");
return dht11Check();
}
本系列帖子目录:
http://club.gizwits.com/thread-6544-1-1.html
有f103c8t6的温湿度驱动吗 zhin 发表于 2017-5-23 15:53
有f103c8t6的温湿度驱动吗
有啊。你查看我其他帖子 大佬你好,有红外传感器驱动和MQ-2烟雾传感器吗?
页:
[1]