“实现温湿度检测:使用STM32F103单片机与DHT11传感器”
目录
一,产品介绍
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包
括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
二,产品亮点
成本低、长期稳定、相对湿度和温度测量、品质卓越、超快响应、抗干扰能力强、超长的信号传输距离、数字信号输出、精确校准。
三,产品参数
四,引脚连接及通信说明
引脚说明
1、VDD供电3.3~5.5VDC
2、DATA串行数据,单总线
3、NC空脚
4、GND接地,电源负极
◎单总线说明
DHT11器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许
设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约 4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主
机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
◎单总线传送数据位定义
DATA用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次传送40位数据,高位先出。
◎数据格式
8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位。
注:其中湿度小数部分为0。
◎校验位数据定义
“8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”8bit校验 位等于所得结果的末8位。
五,原理讲解
引脚说明
1、VDD供电3.3~5.5VDC
2、DATA串行数据,单总线
3、NC空脚
4、GND接地,电源负极
◎单总线说明
DHT11器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许
设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约 4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主
机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
◎单总线传送数据位定义
DATA用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次传送40位数据,高位先出。
◎数据格式
8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位。
注:其中湿度小数部分为0。
◎校验位数据定义
“8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”8bit校验 位等于所得结果的末8位。
DHT11编码步骤:
一. 单片机上点后1s内不读取(不重要)
二. 主机(单片机)发送起始信号:
1.主机先拉高data。
2.拉低data延迟18ms。(大于18小于30ms)
3.拉高data(通过此操作将单片机引脚设置为输入)。图2
三. 从机(DHT11)收到起始信号后进行应答:
从机拉低data,主机读取到data线被拉低持续83us后从机拉高data线, 持续87us,直到高电平结束,意味着主机可以开始接受数据。 图3
四. 主机开始接收数据:
1.主机先把data线拉高(io设置为输入)。
2.从机把data线拉低,主机读取data线电平,直到低电平结束(大约50us)
从机拉高data线后,延迟40us左右(28~70us之间)主机再次读取data线电平,如果为低电平,则为“0”,如果为高电平,则为“1”。
(DTH11.C中有一部分u8 DHT11_receive_bit(void)获得一个字节过程所得格式0或1,是通过从机信号高电平的持续时长判断的,如果60us之后任然为高电平则为格式1,反之为格式0) 图4.2
3.继续重复上述1,2步骤累计40次。
五. data线拉低50us代表读取结束


六,源码
1,DHR11.C
-
#include "DHT11.h"
#include "delay.h"
#include "usart.h"
u8 receive_R_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
u8 receive_T_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
void DHT11_Init(void) //´«¸ÐÆ÷³õʼ»¯
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //ʹÄÜGPIO_EʱÖÓ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PE.12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //ͨÓÃÍÆÍìÊä³ö
GPIO_Init(GPIOE, &GPIO_InitStructure);//³õʼ»¯GPIOE12
}
void DHT11_Start(void) //·¢ËÍÆðʼÐźÅ
{
GPIO_SetBits(GPIOE,GPIO_Pin_12);
delay_us(10); //À¸ßµçƽµÈ´ý
GPIO_ResetBits(GPIOE,GPIO_Pin_12);
delay_ms(25); //µÍµçƽ±£³Öʱ¼ä²»Ð¡ÓÚ18MS²»´óÓÚ30MS
GPIO_SetBits(GPIOE,GPIO_Pin_12);
delay_us(30); //À¸ßµçƽ·¢ËÍÆðʼÐźÅ
}
u8 DHT11_receive_bit(void) //´«¸ÐÆ÷·µ»ØÏìÓ¦Ðźš£½ÓÊÕÒ»¸ö×Ö½Ú
{
u8 i,dat=0;
GPIO_ResetBits(GPIOE,GPIO_Pin_12); //À¸ß
delay_us(81);
GPIO_SetBits(GPIOE,GPIO_Pin_12); //ÀµÍ
delay_us(85);
//¿ªÊ¼×¼±¸·¢ËÍÊý¾Ý
for(i=0;i<8;i++)
{
PEout(12)=0; //ÀµÍ³ÖÐø83US
delay_us(50);
PEout(12)=1; //À¸ß³ÖÐø
delay_us(60);
dat<<=1;
if(PEout(12)==1) //Èç¹û¸ßµçƽʱ¼ä³¬¹ý60us¡£Îª¡±1¡°×´Ì¬
dat+=1;
while(PEout(12));
}
return dat; //·µ»ØÊý¾Ý
}
void DHT11_receive_dat(void)
{
u8 R_H,R_L,T_H,T_L,RH,RL,TH,TL,Checkout;
DHT11_Start();//¿ªÊ¼ÆðʼÏìÓ¦¡£½ÓÊÕ40λÊý¾Ý
if(PEout(12)==0)
{
while(PEout(12)==0); //µÈ´ýÀ¸ß
delay_us(80); //À¸ßºóÑÓʱ80us
R_H=DHT11_receive_bit();
R_L=DHT11_receive_bit();
T_L=DHT11_receive_bit();
T_L=DHT11_receive_bit();
Checkout=DHT11_receive_bit();
delay_us (50);
}
/*УÑéÊý¾Ý*/
if((R_H+R_L+T_H+T_L)==Checkout)
{
R_H=RH;
R_L=RL;
T_H=TH;
T_L=TL;
}
/*Êý¾Ý´¦Àí*/
receive_R_dat[1]=RH/10+0x30;
receive_R_dat[2]=RH%10+0x30;
receive_R_dat[3]='.';
receive_R_dat[4]=RL/10+0x30;
receive_R_dat[5]=RL%10+0x30;
receive_R_dat[6]='%';
receive_T_dat[1]=TH/10+0x30;
receive_T_dat[2]=TH%10+0x30;
receive_T_dat[3]='.';
receive_T_dat[4]=TL/10+0X30;
receive_T_dat[5]=TL%10+0X30;
receive_T_dat[6]='^';
receive_T_dat[7]='C';
printf ("Humidity:\r\n");
MyUSART_SendArr(receive_R_dat,7);
printf("\r\n");
printf ("Temperture:\r\n");
MyUSART_SendArr(receive_T_dat,8);
printf("\r\n");
}
2.DHR11.H
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
void DHT11_Init(void); //´«¸ÐÆ÷³õʼ»¯
void DHT11_Start(void); //·¢ËÍÆðʼÐźÅ
u8 DHT11_receive_bit(void) ; //´«¸ÐÆ÷·µ»ØÏìÓ¦Ðźš£½ÓÊÕÒ»¸ö×Ö½Ú
void DHT11_receive_dat(void);//µÃµ½Êý¾Ý×é
extern u8 receive_R_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
extern u8 receive_T_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
#endif
3,main.c
#include "sys.h"
#include "DHT11.h"
#include "usart.h"
#include "delay.h"
int main(void)
{
// u8 receive_R_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
// u8 receive_T_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
delay_init(); //ÑÓʱº¯Êý³õʼ»¯
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //ÉèÖÃNVICÖжϷÖ×é2:2λÇÀÕ¼ÓÅÏȼ¶£¬2λÏìÓ¦ÓÅÏȼ¶
uart_init(115200); //´®¿Ú³õʼ»¯Îª115200
DHT11_Init() ; //ÎÂʪ¶È´«¸ÐÆ÷³õʼ»¯
printf("温湿度传感器初始化成功:\r\n");
while(1)
{
DHT11_receive_dat();
delay_ms (10000);
}
}
/*注释*/
receive_R_dat[1]=RH/10+0x30; 二进制转换十进制
receive_R_dat[2]=RH%10+0x30;
receive_R_dat[3]='.';
receive_R_dat[4]=RL/10+0x30;
receive_R_dat[5]=RL%10+0x30;
receive_R_dat[6]='%';
receive_T_dat[1]=TH/10+0x30;
receive_T_dat[2]=TH%10+0x30;
receive_T_dat[3]='.';
receive_T_dat[4]=TL/10+0X30;
receive_T_dat[5]=TL%10+0X30;
receive_T_dat[6]='^';
receive_T_dat[7]='C';
/*计算*/
00110101+00000000+00011000+00000100=01010001
接收数据正确:
湿度:00110101(整数)=35H=53%RH
00000000(小数)=00H=0.0%RH=>53%RH+0.0%RH=53.0%RH
温度:00011000(整数)=18H=24℃
00000100(小数)=04H=0.4℃=>24℃+0.4℃=24.4℃
#include "DHT11.h"
#include "delay.h"
#include "usart.h"
u8 receive_R_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
u8 receive_T_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
void DHT11_Init(void) //´«¸ÐÆ÷³õʼ»¯
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //ʹÄÜGPIO_EʱÖÓ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PE.12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //ͨÓÃÍÆÍìÊä³ö
GPIO_Init(GPIOE, &GPIO_InitStructure);//³õʼ»¯GPIOE12
}
void DHT11_Start(void) //·¢ËÍÆðʼÐźÅ
{
GPIO_SetBits(GPIOE,GPIO_Pin_12);
delay_us(10); //À¸ßµçƽµÈ´ý
GPIO_ResetBits(GPIOE,GPIO_Pin_12);
delay_ms(25); //µÍµçƽ±£³Öʱ¼ä²»Ð¡ÓÚ18MS²»´óÓÚ30MS
GPIO_SetBits(GPIOE,GPIO_Pin_12);
delay_us(30); //À¸ßµçƽ·¢ËÍÆðʼÐźÅ
}
u8 DHT11_receive_bit(void) //´«¸ÐÆ÷·µ»ØÏìÓ¦Ðźš£½ÓÊÕÒ»¸ö×Ö½Ú
{
u8 i,dat=0;
GPIO_ResetBits(GPIOE,GPIO_Pin_12); //À¸ß
delay_us(81);
GPIO_SetBits(GPIOE,GPIO_Pin_12); //ÀµÍ
delay_us(85);
//¿ªÊ¼×¼±¸·¢ËÍÊý¾Ý
for(i=0;i<8;i++)
{
PEout(12)=0; //ÀµÍ³ÖÐø83US
delay_us(50);
PEout(12)=1; //À¸ß³ÖÐø
delay_us(60);
dat<<=1;
if(PEout(12)==1) //Èç¹û¸ßµçƽʱ¼ä³¬¹ý60us¡£Îª¡±1¡°×´Ì¬
dat+=1;
while(PEout(12));
}
return dat; //·µ»ØÊý¾Ý
}
void DHT11_receive_dat(void)
{
u8 R_H,R_L,T_H,T_L,RH,RL,TH,TL,Checkout;
DHT11_Start();//¿ªÊ¼ÆðʼÏìÓ¦¡£½ÓÊÕ40λÊý¾Ý
if(PEout(12)==0)
{
while(PEout(12)==0); //µÈ´ýÀ¸ß
delay_us(80); //À¸ßºóÑÓʱ80us
R_H=DHT11_receive_bit();
R_L=DHT11_receive_bit();
T_L=DHT11_receive_bit();
T_L=DHT11_receive_bit();
Checkout=DHT11_receive_bit();
delay_us (50);
}
/*УÑéÊý¾Ý*/
if((R_H+R_L+T_H+T_L)==Checkout)
{
R_H=RH;
R_L=RL;
T_H=TH;
T_L=TL;
}
/*Êý¾Ý´¦Àí*/
receive_R_dat[1]=RH/10+0x30;
receive_R_dat[2]=RH%10+0x30;
receive_R_dat[3]='.';
receive_R_dat[4]=RL/10+0x30;
receive_R_dat[5]=RL%10+0x30;
receive_R_dat[6]='%';
receive_T_dat[1]=TH/10+0x30;
receive_T_dat[2]=TH%10+0x30;
receive_T_dat[3]='.';
receive_T_dat[4]=TL/10+0X30;
receive_T_dat[5]=TL%10+0X30;
receive_T_dat[6]='^';
receive_T_dat[7]='C';
printf ("Humidity:\r\n");
MyUSART_SendArr(receive_R_dat,7);
printf("\r\n");
printf ("Temperture:\r\n");
MyUSART_SendArr(receive_T_dat,8);
printf("\r\n");
}
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
void DHT11_Init(void); //´«¸ÐÆ÷³õʼ»¯
void DHT11_Start(void); //·¢ËÍÆðʼÐźÅ
u8 DHT11_receive_bit(void) ; //´«¸ÐÆ÷·µ»ØÏìÓ¦Ðźš£½ÓÊÕÒ»¸ö×Ö½Ú
void DHT11_receive_dat(void);//µÃµ½Êý¾Ý×é
extern u8 receive_R_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
extern u8 receive_T_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
#endif
#include "sys.h"
#include "DHT11.h"
#include "usart.h"
#include "delay.h"
int main(void)
{
// u8 receive_R_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
// u8 receive_T_dat[10];//¶¨ÒåÒ»¸öÊý¾Ý×é
delay_init(); //ÑÓʱº¯Êý³õʼ»¯
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //ÉèÖÃNVICÖжϷÖ×é2:2λÇÀÕ¼ÓÅÏȼ¶£¬2λÏìÓ¦ÓÅÏȼ¶
uart_init(115200); //´®¿Ú³õʼ»¯Îª115200
DHT11_Init() ; //ÎÂʪ¶È´«¸ÐÆ÷³õʼ»¯
printf("温湿度传感器初始化成功:\r\n");
while(1)
{
DHT11_receive_dat();
delay_ms (10000);
}
}
/*注释*/
receive_R_dat[1]=RH/10+0x30; 二进制转换十进制
receive_R_dat[2]=RH%10+0x30;
receive_R_dat[3]='.';
receive_R_dat[4]=RL/10+0x30;
receive_R_dat[5]=RL%10+0x30;
receive_R_dat[6]='%';
receive_T_dat[1]=TH/10+0x30;
receive_T_dat[2]=TH%10+0x30;
receive_T_dat[3]='.';
receive_T_dat[4]=TL/10+0X30;
receive_T_dat[5]=TL%10+0X30;
receive_T_dat[6]='^';
receive_T_dat[7]='C';
/*计算*/
00110101+00000000+00011000+00000100=01010001
接收数据正确:
湿度:00110101(整数)=35H=53%RH
00000000(小数)=00H=0.0%RH=>53%RH+0.0%RH=53.0%RH
温度:00011000(整数)=18H=24℃
00000100(小数)=04H=0.4℃=>24℃+0.4℃=24.4℃
最后,欢迎各位指正,互相交流互相学习