一、相关概述
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
引脚说明
1、VDD 供电3.3~5.5V DC
2、DATA 串行数据,单总线
3、NC 空脚
4、GND 接地,电源负极
二、数据传输
- 单总线说明
DHT11器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制
均由单总线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许
设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约
4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主
机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
- 单总线传送数据位定义
DATA用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次传送40位数据,
高位先出。
- 数据格式:
8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位。
注:其中湿度小数部分为0。
- 校验位数据定义
( 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据 )= 8bit校验位
三、发送时序图
- 起始信号:
空闲时,总线为高电平,主机把总线拉低等待DHT11响应,处于低电平的时间要大于 18us
确保DHT11能检测到主机发送的起始信号,然后拉高总线 20~40us 等待开始信号结束 - 响应信号:
等待开始信号结束,然后DHT11 发送 80us 的低电平响应信号,在把总线拉高 80us 准备发送数据 - 发送数据:
发送数据时 , 每一bit数据都以50us低电平时隙开始,高电平的长短决定了数据位是0还是1。
“ 0 ”:处于高电平时间 26us ~ 28us
“ 1 ”:处于高电平时间 70us - 结束信号
最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态
相关代码
bsp_dht11.h
/************************** DHT11 数据类型定义********************************/
typedef struct
{
uint8_t humi_int; //湿度的整数部分
uint8_t humi_deci; //湿度的小数部分
uint8_t temp_int; //温度的整数部分
uint8_t temp_deci; //温度的小数部分
uint8_t check_sum; //校验和
} DHT11_Data_TypeDef;
/************************** DHT11 连接引脚定义********************************/
#define DHT11_GPIO_PROT GPIOE
#define DHT11_RCC_PROT_ENR RCC_APB2Periph_GPIOE
#define DHT11_GPIO_PIN GPIO_Pin_6
/************************** DHT11 函数宏定义********************************/
#define DHT11_Dout_0() GPIO_ResetBits(DHT11_GPIO_PROT, DHT11_GPIO_PIN)
#define DHT11_Dout_1() GPIO_SetBits(DHT11_GPIO_PROT,DHT11_GPIO_PIN)
#define DHT11_Dout_Read() GPIO_ReadInputDataBit(DHT11_GPIO_PROT,DHT11_GPIO_PIN)
/************************** DHT11 函数声明********************************/
void DHT11_Init(void);
static void DHT11_GPIO_Config(void);
static void DHT11_Mode_OPP(void);
static void DHT11_Mode_IPU(void);
static uint8_t DHT11_ReadByte(void);
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef* DHT11_Data);
bsp_dht11.c
static void DHT11_GPIO_Config(void);
static void DHT11_Mode_OPP(void);
static void DHT11_Mode_IPU(void);
static uint8_t DHT11_ReadByte(void);
/*
* 函数名:DHT11_Init
* 描述 :DHT11初始化
* 输入 :无
* 输出 :无
*/
void DHT11_Init(void)
{
DHT11_GPIO_Config();
DHT11_Dout_1();
}
/*
* 函数名:DHT11_GPIO_Config
* 描述 :配置DHT11用到的I/O口
* 输入 :无
* 输出 :无
*/
static void DHT11_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); // GPIOE端口使能
GPIO_InitStruct.GPIO_Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO_PROT, &GPIO_InitStruct);
}
/*
* 函数名:DHT11_Mode_OPP
* 描述 :使DHT11-DATA引脚变为推挽输出模式
* 输入 :无
* 输出 :无
*/
static void DHT11_Mode_OPP(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO_PROT, &GPIO_InitStruct);
}
/*
* 函数名:DHT11_Mode_IPU
* 描述 :使DHT11-DATA引脚变为上拉输入模式
* 输入 :无
* 输出 :无
*/
static void DHT11_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = DHT11_GPIO_PIN;
GPIO_Init(DHT11_GPIO_PROT, &GPIO_InitStruct);
}
/*
* 函数名:DHT11_ReadByte
* 描述 :DHT11读取一个字节,从MSB开始
* 输入 :无
* 输出 :无
*/
static uint8_t DHT11_ReadByte(void)
{
uint8_t i, temp = 0;
for (i = 0; i < 8; i++)
{
/*每bit以50us低电平标置开始,轮询直到从机发出的50us低电平结束*/
while (DHT11_Dout_Read() == Bit_RESET);
/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
*通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
*/
CPU_TS_Tmr_Delay_US(40); // x us这个延时需要大于数据0持续的时间即可
if (DHT11_Dout_Read() == Bit_SET) /* x us后仍为高电平表示数据“1” */
{
while (DHT11_Dout_Read() == Bit_SET); // 等待数据1的高电平结束
temp |= (uint8_t)(0x01 << (7 - i)); // 把第7-i位置1,MSB先行
}
else /* x us后仍为高电平表示数据“0” */
{
temp &= ~(uint8_t)(0x01 << (7 - i)); // 把第7-i位置0,MSB先行
}
}
return temp;
}
/*
* DHT11_Read_TempAndHumidity
* 描述 :一次完整的数据传输为40bit,高位先出
* 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
* 输入 :无
* 输出 :无
*/
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
// 输出模式
DHT11_Mode_OPP();
DHT11_Dout_0(); //主机拉低
CPU_TS_Tmr_Delay_MS(18); //延时18ms
DHT11_Dout_1(); //总线拉高,保持30us
CPU_TS_Tmr_Delay_US(30);
DHT11_Mode_IPU(); // 输入模式
if (DHT11_Dout_Read() == Bit_RESET)
{
/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while (DHT11_Dout_Read() == RESET);
/*轮询直到从机发出 的80us 高电平 响应信号结束*/
while (DHT11_Dout_Read() == SET);
//开始发送数据
DHT11_Data->humi_int = DHT11_ReadByte();
DHT11_Data->humi_deci = DHT11_ReadByte();
DHT11_Data->temp_int = DHT11_ReadByte();
DHT11_Data->temp_deci = DHT11_ReadByte();
DHT11_Data->check_sum = DHT11_ReadByte();
DHT11_Mode_OPP();
DHT11_Dout_1(); //主机拉高
//检查读取数据是否正确
if (DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int + DHT11_Data->temp_deci)
{return SUCCESS;}
else
{return ERROR;}
}
else{
return ERROR;
}
}
参考文档
DHT11数据手册
野火实验例程