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