基于STM32F103C8T6驱动DHT11温湿度讲解

DHT11分析:

1、MCU接收DHT11的温湿度数据是数字量还是模拟量?

2、DHT11产品参数

3、DHT11的通信方式是什么?

4、DHT11一次传输多少位数据,低位先出还是高位先出?

5、DHT11的数据格式是什么?

6、DHT11的校验位?如何校验?

7、DHT11如何判断零下温度、零上温度?

8、DHT11时序图如何分析?

9、IO口配置什么模式?

10、DHT11起始信号?

11、DHT11响应信号?

12、如何接收dht11传输的数据0或数据1?

一、DHT11基础讲解

DHT11:单总线通信(IIC总线相似)

单总线通信概述:单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成

DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器

DHT11输出的是数字信号,MCU可以直接接收并处理

如果输出的是模拟信号,则需要通过ADC转换为数字信号后再进行处理

引脚说明:

发挥作用只用三个引脚:1、2、4号引脚

湿度性能表:

温度性能表:

二、DHT11单总线通信时序

三、DHT11数据结构分析

DATA线改配置什么模式?

因为设备(主机或从机)通过一个漏开路或三态端口连至该数据线,并该数据线接了一个上拉电阻

所以DATA线配置为通用开漏输出

因为有上拉电阻,所以总线空闲状态默认为高电平

主从结构:只有主机呼叫从机时,从机才会应答,主机起到主导作用

单总线数据格式一次传送 40 位数据,高位先出

  • 一次接受40bit数据全部接收
  • 接收2次16bit数据再接收1次8bit
  • 接收5次8bit数据

数据格式:

8bit湿度整数数据 + 8bit湿度小数数据 + 8bit温度整数数据 + 8bit温度小数数据 + 8bit校验位

:其中湿度小数部分为 0

校验位数据定义

“8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据” 8bit 校验位等于所得结果的末 8 位

例子:如何接收40bit数据并校验?变量  或者  数组   u8 data[5]

u8 data[0] = 湿度整数数据;

u8 data[1] = 湿度数数据;

u8 data[2] = 度整数数据;

u8 data[3] = 数数据;

u8 data[4] = 校验位数据;

if((data[0] + data[1] + data[2] + data[3])&0xff == data[4])

{

//数据处理

}

MCU接收8bit高位先发数据:

u8 Mcu_Rec(void)
{
	u8 data = 0;
	for(u8 i=0;i<8;i++)
{
	data <<= 1;
		if(IO_IN)
{
		data |= 1;
}
}
}

MCU接收8bit低位先发数据:

u8 Mcu_Rec(void)
{
	u8 data = 0;
	for(u8 i=0;i<8;i++)
{
	data >>= 1;
		if(IO_IN)
{
		data |= 0x80;
}
}
}

MCU发送8bit低位数据:

void Mcu_Send(u8 data)
{
	for(u8 i=0;i<8;i++)
{
	if(data & (0x01 << i))
    {
       IO = 1;
}
    Else
    {
       IO = 0;
}
}
}

四、代码流程

  • 初始化部分

打开GPIO时钟  ---- 通用开漏输出   ---  等待1s以越过不稳定状态(1s延时) --- DATA线拉高

  • 起始信号部分

拉低DATA线  --- 低电平时间保持大于18ms(延时20ms)  --- 拉高DATA线

  •  响应信号部分(输出切换成输入)

等待高电平结束  ---  添加超时退出等待操作(超过100us返回响应不正常) ---  等待83us低电平结束  --- 等待87us高电平结束  --- 返回响应正常

  • 接收8bit低位数据部分

循环接收8bit数据 ---- 等待54us低电平结束 --- --- 延时50us  ---- 跟据IO的高低电平判断数据0还是数据1 ----  返回数据

  • 整合函数部分(单总线序列)

起始信号   ---  判断是否正常响应   ---- 接收40bit数据(分5次接)  --- 校验数据  ---- 处理数据

五、代码展示

DHT11.c

#include "dht11.h"
/*******************************************************	

函数名:
函数功能:温湿度初始化
形参:void
返回值:void
DHT11_DATA --- PB14 --- 通用开漏输出 --- 需要关闭JTAG调试 
--- 等待1s以越过不稳定状态(1s延时) --- DATA线拉高


********************************************************/ 	
u8 DHT11_Temp,DHT11_Hum;
//复位DHT11
void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//SET OUTPUT
    DHT11_DQ_OUT=0; 	//拉低DQ
    delay_ms(20);    	//拉低至少18ms
    DHT11_DQ_OUT=1; 	//DQ=1 
	delay_us(30);     	//主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void) 	   
{   
	u8 retry=0;
	DHT11_IO_IN();//SET INPUT	 判断方向,也可以用等待高电平结束
    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us,等待低电平结束
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;//等待超时
	else retry=0;
    while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us,等待高电平结束
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}
//从DHT11读取一个位
//返回值: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)//等待变高电平
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if(DHT11_DQ_IN)return 1;
	else return 0;		   
}
//从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;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(float *temp,float *humi)    
{        
 	u8 buf[5];
	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])
		{
			
			*temp=buf[2]*1.0f +	buf[3]/10.0f;//存储温度
			*humi=buf[0]*1.0f +	buf[1]/10.0f;//存储湿度
		}
	}else return 1;
	return 0;	    
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在    	 
u8 DHT11_Init(void)
{	 
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PG端口时钟
	
 	GPIO_InitStructure.GPIO_Pin = DHT11_PIN;				 //PG11端口配置
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(DHT11_IO, &GPIO_InitStructure);				 //初始化IO口
 	GPIO_SetBits(DHT11_IO,DHT11_PIN);						 //PG11 输出高
			    
	DHT11_Rst();  //复位DHT11
	return DHT11_Check();//等待DHT11的回应
} 

/***********************
函数名:Dht11_GetValue
函数功能:DHT11温湿度显示
形参:void
返回值:void
函数说明:

温度:tempeature
湿度:humidity
************************/
float temp ,humi;
void Dht11_GetValue(void)
{
	//printf("a\r\n");
	
	if(DHT11_Read_Data(&temp, &humi)==0)
	{
	}


}

DHT11.h

#ifndef _DHT11_H
#define _DHT11_H

#include "dht11.h"
extern float temp,humi;
extern u8 DHT11;
extern u8 buf1[20];
extern u8 buf2[20];
#define DHT11_IO    GPIOB
#define DHT11_PIN   GPIO_Pin_14
//IO方向设置
#define DHT11_IO_IN()  {DHT11_IO->CRH&=0XF0FFFFFF;DHT11_IO->CRH|=8<<24;}
#define DHT11_IO_OUT() {DHT11_IO->CRH&=0XF0FFFFFF;DHT11_IO->CRH|=3<<24;}
IO操作函数											   
#define	DHT11_DQ_OUT PBout(14) //数据端口	PA0 
#define	DHT11_DQ_IN  PBin(14)  //数据端口	PA0 


u8 DHT11_Init(void);//初始化DHT11
u8 DHT11_Read_Data(float *temp,float *humi);//读取温湿度
u8 DHT11_Read_Byte(void);//读出一个字节
u8 DHT11_Read_Bit(void);//读出一个位
u8 DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11 
void Dht11_GetValue(void);


#endif

好的,以下是基于STM32F103C8T6驱动DHT11的代码: ```c #include "stm32f10x.h" #include "dht11.h" #define DHT11_GPIO GPIOA #define DHT11_PIN GPIO_Pin_0 void DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_GPIO, &GPIO_InitStructure); } void DHT11_Start(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_GPIO, &GPIO_InitStructure); GPIO_SetBits(DHT11_GPIO, DHT11_PIN); delay_us(30); GPIO_ResetBits(DHT11_GPIO, DHT11_PIN); delay_ms(18); GPIO_SetBits(DHT11_GPIO, DHT11_PIN); delay_us(40); } uint8_t DHT11_Check_Response(void) { uint8_t Response = 0; delay_us(40); if (!(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN))) { delay_us(80); if ((GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN))) Response = 1; else Response = -1; } while ((GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN))); return Response; } uint8_t DHT11_Read(void) { uint8_t i, j; for (j = 0; j < 8; j++) { while (!(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN))); delay_us(40); if (!(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN))) i &= ~(1 << (7 - j)); else i |= (1 << (7 - j)); while ((GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN))); } return i; } void DHT11_Get_Data(uint8_t *temp, uint8_t *humi) { uint8_t Response = 0; uint8_t Rh_byte1, Rh_byte2, Temp_byte1, Temp_byte2; uint16_t SUM; DHT11_Start(); Response = DHT11_Check_Response(); if (Response == 1) { Rh_byte1 = DHT11_Read(); Rh_byte2 = DHT11_Read(); Temp_byte1 = DHT11_Read(); Temp_byte2 = DHT11_Read(); SUM = DHT11_Read(); if (SUM == (Rh_byte1 + Rh_byte2 + Temp_byte1 + Temp_byte2)) { *humi = Rh_byte1; *temp = Temp_byte1; } } } void delay_us(uint32_t us) { uint32_t i; for (i = 0; i < us; i++) __NOP(); } void delay_ms(uint32_t ms) { uint32_t i; for (i = 0; i < ms; i++) delay_us(1000); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点灯之王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值