数字温湿度传感器 — DHT11 ---- 温湿度数据采集详解
引脚接口说明
-
建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻 。
-
DHT11的供电电压为 3-5.5V 。
-
传感器上电后, 要等待 1s 以越过不稳定状态在此期间无需发送任何指令。 (给传感器反应一段时间)
-
电源引脚(VDD, GND) 之间可增加一个100nF 的电容, 用以去耦滤波。
通讯方式(串行接口 (单线双向))
-
DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分 。
-
一次完整的数据传输为40bit,高位先出 。
-
用户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.c驱动代码
#include "dht11.h"
/****************************单总线输出引脚配置*******************************/
void DHT11_IO_OUT (void){ //端口变为输出
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DHT11_IO; //选择端口号(0~15或all)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //模式推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Init(DHT11PORT, &GPIO_InitStructure);
}
/****************************单总线输入引脚配置*******************************/
void DHT11_IO_IN (void){ //端口变为输入
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DHT11_IO; //选择端口号(0~15或all)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(DHT11PORT, &GPIO_InitStructure);
}
/*****************************DHT11初始化(主机的开始信号)******************************/
void DHT11_RST (void){ //DHT11端口复位,发出起始信号(IO发送)
DHT11_IO_OUT(); //单总线切换为输出模式
GPIO_ResetBits(DHT11PORT,DHT11_IO); //拉低总线
Delay_ms(20); //拉低至少18ms
GPIO_SetBits(DHT11PORT,DHT11_IO); //拉高总线
Delay_us(30); //主机拉高20~40us
}
/*****************************等待DHT11回应,返回1:未检测到DHT11,返回0:成功(IO接收)******************************/
u8 Dht11_Check(void){
u8 retry=0; //定义1个DHT11响应超时变量
DHT11_IO_IN();//总线切换到输入状态
while (GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO)&&retry<100){//等待DHT11拉低40~80us
retry++;
Delay_us(1);
}
/******************************如果超时返回1,否则将超时变量清零为下次准备*****************************/
if(retry>=100)return 1; else retry=0;
while (!GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO)&&retry<100){//等待DHT11拉低后会再次拉高40~80us
retry++;
Delay_us(1);
}
if(retry>=100)return 1;
return 0;
}
/******************************从DHT11读取一个位 返回值:1/0*****************************/
u8 Dht11_ReadBit(void){
u8 retry=0; //定义1个DHT11响应超时变量
while(GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO)&&retry<100){//等待变为低电平
retry++;
Delay_us(1);
}
retry=0;
while(!GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO)&&retry<100){//等待变高电平
retry++;
Delay_us(1);
}
Delay_us(40);//等待40us检测电平状态 //用于判断高低电平,即数据1或0
/*****************************如果为低则为0,为高则为1,并且返回数据0/1******************************/
if(GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO))return 1; else return 0;
}
/*****************************从DHT11读取一个字节 返回值:读到的数据******************************/
u8 Dht11_ReadByte(void){
u8 i,dat;//定义一个循环变量和一个接收8位数据的变量
dat=0; //初识值为0000 0000
for (i=0;i<8;i++){
dat<<=1; //提前移动一次没有作用,(移动7次就行)
dat|=Dht11_ReadBit();//0或上0为0,或上1为1
}
return dat;
}
/******************************DHT11初始化*****************************/
u8 DHT11_Init (void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //APB2外设时钟使能
DHT11_RST();//DHT11端口复位,发出起始信号
return Dht11_Check(); //等待DHT11回应
}
/****************************读取数据,储存在指针所指的地址处*******************************/
u8 DHT11_ReadData(u8 *h){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败
u8 buf[5];//存放40bit数据
u8 i;
DHT11_RST();//DHT11端口复位,发出起始信号
if(Dht11_Check()==0){ //等待DHT11回应
for(i=0;i<5;i++){//读取5位数据
buf[i]=Dht11_ReadByte(); //读出数据
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){ //数据校验
*h=buf[0]; //将湿度值放入指针1
h++;
*h=buf[2]; //将温度值放入指针2
}
}
else return 1;
return 0;
}
DHT11.h驱动代码
#ifndef __DHT11_H
#define __DHT11_H
#include "sys.h"
#include "delay.h"
#define DHT11PORT GPIOA //定义IO接口
#define DHT11_IO GPIO_Pin_15 //定义IO接口
void DHT11_IO_OUT (void);
void DHT11_IO_IN (void);
void DHT11_RST (void);
u8 Dht11_Check(void);
u8 Dht11_ReadBit(void);
u8 Dht11_ReadByte(void);
u8 DHT11_Init (void);
u8 DHT11_ReadData(u8 *h);
#endif
Delay_ms(1000);//初始化后的必要的延时(不得小于1秒)