文章目录
- 一、DHT11是什么?
- 二、使用步骤
- 1.硬件
- 1.硬件连接
- 2.工作原理
- 1.串行单总线
- 2.温湿度数据采集原理
- 2.软件
- 1.DHT11初始化如下(示例):
- 2.DHT11复位如下(示例):
- 3.等待DHT11的回应如下(示例):
- 4.检测DHT11是否正常代码如下(示例):
- 5.DHT11读取一个字节代码如下(示例):
- 6.DHT11读取一个位数据代码如下(示例):
- 7.DHT11读取温湿度数据代码如下(示例):
- 8.DHT11采集温湿度数据代码如下(示例):
- 9.测试结果:
- 1.上电状态
- 2.湿纸巾状态
- 三、总结
一、DHT11是什么?
DHT11是一种温湿度传感器模块,用于测量环境的温度和湿度。它采用数字信号输出,使用单总线通信协议,具有低成本、简单易用的特点。
DHT11传感器由一个温度传感器和一个湿度传感器组成,内部集成了模拟信号读取、数字信号处理和校准等功能。传感器通过测量热敏电阻来获取环境温度,并通过测量湿度敏感电阻来获取环境湿度。它将温度和湿度转换为数字信号,通过单总线通信协议将数据传输给主控设备。
DHT11传感器模块的工作电压通常为3.3V或5V,可以与各类微控制器(如Arduino、Raspberry Pi等)进行连接和交互。通过简单的代码和接线,你可以读取DHT11传感器提供的温度和湿度数值,从而监测和控制环境的温湿度。
需要注意的是,DHT11相对于其他高精度传感器而言,其精度较低,温湿度测量的范围和精确度也相对有限,见下面参数表。
相关重要参数如下:
参数 | 规格 |
---|---|
工作电压 | 3.3V-5.5V |
外形尺寸 | 23.2(L)mm ×12.5(W)mm |
测量范围 | 温度:-20~+60℃ 湿度:5~95%RH |
精度 | 温度:±2℃ 湿度:±5%RH (25℃) |
分辨率 | 温度:0.1℃ 湿度:1%RH |
衰减值 | 温度:<0.1℃/年 湿度:<1%RH/年 |
输出信号 | 单总线数字信号 |
外壳材料 | ABS塑料 |
重量 | 1g |
引脚数 | 3/4(有一个空脚) |
二、使用步骤
1.硬件
1.硬件连接
硬件相对比较简单,DHT11的数据接单片机IO口即可。这里我用的是主控STM32F103C8的PA4.
/* Defines ------------------------------------------------------------------*/
#define DHT11_GPIO_RCC RCC_APB2Periph_GPIOA
#define DHT11_GPIO_Port GPIOA
#define DHT11_Pin GPIO_Pin_4//根据实际的引脚修改
2.工作原理
1.串行单总线
串行单总线是一种通信协议,它允许多个设备通过共享同一条数据线进行通信。在这种协议中,每个设备都有一个唯一的地址,主控设备可以通过这个地址来选择特定的设备进行通信。这种通信方式可以减少连接线的数量,降低成本,并简化系统设计。
DHT11之所以采用串行单总线通信,主要是出于简单、成本低廉和易用性的考虑。采用串行单总线通信可以大大简化DHT11模块与主控设备(比如微控制器)的连接,只需要一根数据线即可完成通信,从而降低了连接复杂性和成本。此外,串行单总线通信也使得多个传感器可以共享同一条数据线,方便在系统中同时使用多个传感器模块。
2.温湿度数据采集原理
1.DHT11传输的40位数据包括湿度整数数据、湿度小数数据、温度整数数据、温度小数数据和校验位。这些数据的传输顺序是高位先出的,也就是从最高位开始传输到最低位。
8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位
2.每个数据位的传输格式如下:
位数据“0”:先发送一个持续时间为54微秒的低电平信号,然后是一个持续时间在23至27微秒之间的高电平信号。
位数据“1”:先发送一个持续时间为54微秒的低电平信号,然后是一个持续时间在68至74微秒之间的高电平信号。
3.此外,校验位的计算方式是将湿度整数数据、湿度小数数据、温度整数数据和温度小数数据相加,得到的结果应与传输的校验位数据相等。
8bit校验位=8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据
2.软件
1.DHT11初始化如下(示例):
/*******************************************************************************
* 函数名:DHT11_Init
* 描述 :DHT11初始化
* 输入 :void
* 输出 :uint8_t
* 调用 :
* 备注 :返回0:存在 返回1:未检测到DHT11的存在
*******************************************************************************/
uint8_t DHT11_Init(void)
{
delay_syms(1000);//在上电后到对DHT11初始化前应有1s的稳定期,等待传感器稳定。可以在单片机上电后采用1s延时处理。
DHT11_RST();//DHT11端口复位,发出起始信号
return DHT11_Check();//等待DHT11回应
}
2.DHT11复位如下(示例):
/*******************************************************************************
* 函数名:DHT11_RST
* 描述 :DHT11复位
* 输入 :void
* 输出 :uint8_t
* 调用 :
* 备注 :DHT11开始信号
*******************************************************************************/
void DHT11_RST(void)
{
DHT11_IO_OUT();//端口为输出
DHT11_IO_LOW();//使总线为低电平
delay_syms(25);//拉低至少18ms
DHT11_IO_HIGH();//使总线为高电平
Delay_20us();//主机拉高20~40us
}
3.等待DHT11的回应如下(示例):
/*******************************************************************************
* 函数名:DHT11_Check
* 描述 :等待DHT11的回应
* 输入 :void
* 输出 :uint8_t
* 调用 :
* 备注 :返回0:存在 返回1:未检测到DHT11的存在
*******************************************************************************/
uint8_t DHT11_Check(void)
{
uint8_t retry = 0;
DHT11_IO_IN();
while((DHT11_IO_Read()) && retry < 100)//DHT11会拉低40~80us
{
retry++;
Delay_2us();
};
if(retry >= 100) return 1;
else retry = 0;
while ((!DHT11_IO_Read()) && retry < 100)//DHT11拉低后会再次拉高40~80us
{
retry++;
Delay_2us();
};
if(retry >= 100) return 1;
return 0;
}
4.检测DHT11是否正常代码如下(示例):
/*******************************************************************************
* 函数名:DHT11_Detection
* 描述 :检测DHT11是否正常
* 输入 :void
* 输出 :uint8_t
* 调用 :
* 备注 :返回0:存在 返回1:未检测到DHT11的存在
*******************************************************************************/
void DHT11_Detection(void)
{
if(DHT11_Init() == 0)
{
DHT11_flag = 1;
printf("DHT11 OK\r\n");
}
else
{
DHT11_flag = 0;
printf("DHT11 Fail\r\n");
}
}
5.DHT11读取一个字节代码如下(示例):
/*******************************************************************************
* 函数名:DHT11_Read_Byte
* 描述 :DHT11读取一个字节
* 输入 :void
* 输出 :uint8_t
* 调用 :
* 备注 :返回值:读到的数据
*******************************************************************************/
uint8_t DHT11_Read_Byte(void)
{
uint8_t i, dat;
dat = 0x00;
for (i = 0; i < 8; i++)
{
dat <<= 1;//左移运算符,dat左移1位
dat |= DHT11_Read_Bit();
}
return dat;
}
6.DHT11读取一个位数据代码如下(示例):
/*******************************************************************************
* 函数名:DHT11_Read_Bit
* 描述 :DHT11读取数据 读取一个位
* 输入 :void
* 输出 :uint8_t
* 调用 :
* 备注 :返回0/1
*******************************************************************************/
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry = 0;
while((DHT11_IO_Read() == 1) && retry < 100) //等待变为低电平
{
retry++;
Delay_2us();
}
while((DHT11_IO_Read() == 0) && retry < 100) //等待变高电平
{
retry++;
Delay_2us();
}
Delay_20us();
Delay_20us();
if(DHT11_IO_Read() == 1) //用于判断高低电平,即数据1或0
{
return 1;
}
else
{
return 0;
}
}
7.DHT11读取温湿度数据代码如下(示例):
/*******************************************************************************
* 函数名:DHT11_Read_Data
* 描述 :DHT11读取一次数据
* 输入 :temp:温度值(范围:0~50°)
humi:湿度值(范围:20%~90%)
* 输出 :uint8_t
* 调用 :
* 备注 :返回值:0,正常;1,读取失败
*******************************************************************************/
uint8_t DHT11_Read_Data(uint8_t *temphigh, uint8_t *templow, uint8_t *humi)
{
uint8_t buf[5];
uint8_t i;
DHT11_RST();//DHT11端口复位,发出起始信号
if(DHT11_Check() == 0)//等待DHT11回应,0为成功回应
{
for(i = 0; i < 5; i++) //读取40位数据
{
buf[i] = DHT11_Read_Byte();//读出数据
}
if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) //数据校验
{
*humi = buf[0];//将湿度整数值放入指针humi
*temphigh = buf[2];//将温度整数值放入指针temphigh
*templow = buf[3];//将温度小数值放入指针templow
}
}
else return 1;
return 0;
}
8.DHT11采集温湿度数据代码如下(示例):
/*******************************************************************************
* 函数名:DHT11_Collect_data
* 描述 :DHT11采集温湿度数据
* 输入 :void
* 输出 :void
* 调用 :1s
* 备注 :
*******************************************************************************/
void DHT11_Collect_data(void)
{
uint8_t humidity = 0;
uint8_t tempe_high = 0;
uint8_t tempe_low = 0;
if(DHT11_Read_Data(&tempe_high,&tempe_low,&humidity) == 0)
{
DHT11_humi = humidity;
DHT11_temp_high = tempe_high;
DHT11_temp_low = tempe_low;
printf("DHT11_temp_high = %d\r\n",DHT11_temp_high);
printf("DHT11_temp_low = %d\r\n",DHT11_temp_low);
printf("DHT11_humi = %d\r\n",DHT11_humi);
}
else
{
printf("DHT11 DATA Fail\r\n");
}
}
显示部分,这里的显示是用0.96寸OLED显示的,不懂的话可以参考我的另外一篇博客:0.96寸OLED(IIC接口)显示屏的图像显示应用
注意:OLED字模库没有包含°,也没特地去取°,不影响温湿度的数据显示。
/*******************************************************************************
* 函数名:OLED_Rfresh
* 描述 :OLED实时显示数据刷新
* 输入 :void
* 输出 :void
* 调用 :1s
* 备注 :
*******************************************************************************/
void OLED_Rfresh(void)
{
if(DHT11_flag)
{
OLED_ShowString(1, 1, "Temp:");
OLED_ShowSignedNum(1, 6, DHT11_temp_high, 2);
OLED_ShowString(1, 9, ".");
OLED_ShowSignedNum(1, 9, DHT11_temp_low, 1);
OLED_ShowString(1, 11, "C");
OLED_ShowString(2, 1, "Humi:");
OLED_ShowSignedNum(2, 6, DHT11_humi, 2);
OLED_ShowString(2, 9, "%");
}
}
9.测试结果:
1.上电状态
上电串口打印DHT11 OK表示DHT11工作正常
uint8_t DHT11_temp_high = 0;//温度高位
uint8_t DHT11_temp_low = 0;//温度低位
uint8_t DHT11_humi = 0;//湿度
2.湿纸巾状态
由于要让湿度变化明显比较容易,所以咱直接湿纸巾盖上去。
可以发现湿度变化比较大,温度也有稍微变化,毕竟水降点温。
三、总结
今天简单介绍了温湿度传感器DHT11的温湿度数据采集及显示,感谢你的观看,谢谢!