STM32+DHT11监测环境的温湿度

发布者:beta13最新更新时间:2024-05-10 来源: elecfans关键字:STM32  DHT11  监测环境  温湿度 手机看文章 扫描二维码
随时随地手机看文章

【1】DHT11传感器

DHT11是一种数字温湿度传感器,能够通过数字信号输出当前环境的温度和湿度值。DHT11可以通过一条数据信号线连接到微控制器或其他外设,从而实现温湿度的实时测量和数据读取。


DHT11采用单总线通信协议,只需要连接一个数字信号线和两个电源线,即可实现传感器的数据读取。传感器本身具有一定的温度和湿度校准能力,因此输出的数据比较可靠。



DHT11传感器的测量范围为0~50°C的温度和20%~90%的相对湿度,测量精度为±2°C和±5%RH。


【2】通信协议

DHT11采用单总线通信协议,使用一条数据信号线来传输数据,其中包括起始信号、数据位和校验位。通信协议如下:


主机发送一个开始信号给DHT11,即将数据信号线拉低至少18ms以上。

主机发出启动信号之后,拉低数据线至少80us,在这个过程中,DHT11将会检测到主机发送的启动信号,并做出回应。

DHT11响应主机发出的启动信号后,会拉高数据信号线至少80us,表示传输数据前的“准备工作”已经完成。

DHT11开始向主机发送数据,每个数据包包含40个位,高位先传输。在数据传输的过程中,DHT11会将数据信号线从低电平转换为高电平,表示1的开始,持续时间2628us,然后将数据线拉低,表示0的开始,持续时间70us。

在发送完40位数据后,DHT11会发送一个校验位。校验位的计算方法是将前四个字节数据相加,求出一个8位校验码,将此校验码与第五个字节进行比较,如果相等,则数据传输成功,否则需要重传数据。

主机接收到数据后,需要将数据信号线拉高,以结束传输。

【3】读取DHT11温湿度数据

以下是一个读取DHT11传感器的温度和湿度示例代码:


Copy Code#include 'stm32f10x.h'

#include 'dht11.h'

#define DHT11_GPIO_PORT GPIOB

#define DHT11_GPIO_PIN GPIO_Pin_12

void delay_us(uint32_t us)

{

  us *= (SystemCoreClock / 1000000) / 5;

  while (--us);

}

void dht11_start(void)

{

  GPIO_InitTypeDef GPIO_InitStruct;

  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_PORT, &GPIO_InitStruct);

  /* 发送开始信号 */

  GPIO_ResetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN);

  delay_us(18000);

  GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN);

  delay_us(40);

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);

}

uint16_t dht11_read_bit(void)

{

  uint16_t retry = 0;

  while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET) {

    retry++;

    if (retry > 1000) {

      return 0;

     }

    delay_us(1);

   }

  retry = 0;

  while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == SET) {

    retry++;

    if (retry > 1000) {

      return 0;

     }

    delay_us(1);

   }

  if (retry < 30) {

         return 0;

     } else {

         return 1;

     }

 }

 

 uint8_t dht11_read_byte(void)

 {

     uint8_t i;

     uint8_t data = 0;

 

     for (i = 0; i < 8; i++) {

         data <<= 1;

         if (dht11_read_bit()) {

             data |= 0x01;

         }

     }

 

     return data;

 }

 

 uint8_t dht11_read_data(dht11_data_t *data)

 {

     uint8_t i;

     uint8_t buf[5];

     uint8_t checksum = 0;

 

     dht11_start();

 

     if (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET) {

         /* 等待DHT11响应 */

         while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET);

 

         /* 等待DHT11发射数据 */

         while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == SET);

 

         /* 接收数据 */

         for (i = 0; i < 5; i++) {

             buf[i] = dht11_read_byte();

         }

 

         /* 校验和 */

         checksum = buf[0] + buf[1] + buf[2] + buf[3];

 

         if (checksum == buf[4]) {

             data->humidity = buf[0];

      data->temperature = buf[2];

      return 1;

     }

   }

  return 0;

}

int main(void)

{

  dht11_data_t data;

  GPIO_InitTypeDef GPIO_InitStruct;

  /* 使能GPIOB时钟 */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  /* 配置DHT11引脚为输入模式 */

  GPIO_InitStruct.GPIO_Pin = DHT11_GPIO_PIN;

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);

  while (1) {

    if (dht11_read_data(&data)) {

      printf('Temperature: %d°C   Humidity: %d%%n', data.temperature, data.humidity);

     } else {

      printf('Error reading data from DHT11.n');

     }

    delay_us(2000000);

   }

}

在这个示例代码中,首先定义了一个

dht11_data_t

结构体,用于保存读取的温度和湿度数据。然后,编写了一些函数来执行DHT11读取操作。


delay_us()

函数是一个简单的延迟函数,用于等待一定量的时间。需要精确地计算一个微秒的延迟,并在循环中使用该延迟来等待一段时间。


dht11_start()

函数用于发送DHT11的开始信号。将DHT11引脚配置为输出模式,并发送18毫秒的低电平信号,然后再发送40微秒的高电平信号。


dht11_read_bit()

函数用于读取DHT11传输的数据位。等待DHT11输出信号的变化,并根据变化的时间来判断数据位的值。如果一个数据位的响应时间小于30微秒,则被判定为0,否则为1。


dht11_read_byte()

函数用于读取一个字节的数据(8个数据位)。通过调用

dht11_read_bit()

函数8次来读取每个数据位,并将结果组合成一个字节。


dht11_read_data()

函数用于读取整个DHT11数据包,包括温度、湿度和校验和。首先调用

dht11_start()

函数发送开始信号,然后等待DHT11发送数据。使用

dht11_read_byte()

函数读取5个字节的数据,并验证校验和以确保数据完整和正确。


最后,在

main()

函数中,初始化GPIO口和DHT11传感器,并执行一个循环来读取数据。如果读取成功,则将温度和湿度打印到串口终端上,否则输出错误信息。


关键字:STM32  DHT11  监测环境  温湿度 引用地址:STM32+DHT11监测环境的温湿度

上一篇:STM32采集传感器数据通过冒泡排序取稳定值
下一篇:基于STM32物联网开发板(2)--语音播报SYN6288

推荐阅读最新更新时间:2024-11-17 11:46

FreeModbus for stm32(Keil工程)——精简Modbus slave协议
1、测试环境Keil MDK 4.7a stm32f103c8, PB12为输出线圈,可以通过Modbus Poll来控制线圈的输出状态。 2、通过ModbusProt.h配置硬件、数据缓冲区大小和功能码配置 3、移植要点为Port.c和Port.h 定时器操作在stm32平台下基本不用改 a、定时器初始化; xMBPortTimersInit() b、开定时器及中断; vMBPortTimersEnable() c、关定时器及中断; vMBPortTimersDisable() d、定时器溢出中断服务程序;TIME_IQR_HANDLER() 串口操作: a、串初始化; xMBPortS
[单片机]
FreeModbus for <font color='red'>stm32</font>(Keil工程)——精简Modbus slave协议
STM32USART串口库函数介绍之USART_Init
本文将介绍USART串口的库函数,总的来说有以下函数体: ※ USART_Init函数:初始化所使用的串口外设 ※ USART_Cmd函数:使能或者失能USART外设 ※ USART_ITConfig函数:使能或者失能指定的USART中断 ※ USART_SendData函数:通过外设USARTx发送单个数据 ※ USART_ReceiveData函数:返回USARTx最近解释接收到的数据 ※ USART_GetFlagStatus函数:检查指定的USART标志位设置与否 ※ USART_ClearFlag函数:清楚USARTx的待处理标志位 ※ USART_GetITStatus函数:检查指定的U
[单片机]
stm32串口的flag和it标志位
今天用到stm32的串口,对串口进行配置进行接受数据。之后大家也可以想象到结果是什么,完全没有用哎! 后来慢慢的发现了问题的所在,现做笔记如下: ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT); USART_IT参数: #define USART_IT_PE ((uint16_t)0x0028) #define USART_IT_TXE ((uint16_t)0x0727) #define USART_IT_TC ((uint16_t)0x0626
[单片机]
STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA
历程详解 详解包括: 中断原理讲解 例程流程详解 库函数分析详解 对应寄存器介绍 对应函数介绍 对应注释详解 本篇文章提供两种方法: 一种是 :IDLE 接收空闲中断+DMA 一种是: IDLE 接收空闲中断+RXNE接收数据中断 都可完成串口数据的收发 知识点介绍: STM32 IDLE 接收空闲中断 功能: 在使用串口接受字符串时,可以使用空闲中断(IDLEIE置1,即可使能空闲中断),这样在接收完一个字符串,进入空闲状态时(IDLE置1)便会激发一个空闲中断。在中断处理函数,我们可以解析这个字符串。 接受完一帧数据,触发中断 STM32的IDLE的中断产生条件: 在串口无数据接收的情况下,不会产生,
[单片机]
<font color='red'>STM32</font> HAL CubeMX 串口IDLE接收空闲中断+DMA
STM32 | 在SRAM、FLASH中调试代码的配置方法
STM32的FLASH擦写次数有限(大概为1万次),所以为了延长FLASH的使用时间,我们平时调试时可以选择在SRAM中进行硬件调试。除此之外,SRAM 存储器的写入速度比在内部 FLASH 中要快得多,所以下载程序到SRAM中的速度较快。 所以我们很有必要建立两个版本的工程配置,在SRAM中调试程序完毕后,再把代码下载到FLASH中即可。这篇笔记主要分享在keil5中配置FLASH调试与SRAM调试的详细配置方法及如何切换两种配置。 本篇笔记以STM32F103ZET6为例。其FLASH大小为512KB,SRAM的大小为64KB。FLASH基地址为0x08000000,SRAM基地址为0x20000000。在STM32F
[单片机]
<font color='red'>STM32</font> | 在SRAM、FLASH中调试代码的配置方法
simulink开发STM32串口函数的步骤
配置环境:MATLAB2018b,STM32CubeMX-5.4.0,STM32MatTarget_5.4.0,Keil MDK5 单片机:STM32F103ZET6 CK_1****功能:单片机发送任意长度数组给上位机。 注意数组的输出数据类型要选择为uint8。不要删除两个getBuffPtr文件, 生成代码后将getBuffPtr的头文件和源文件分别复制到生成的Inc和Src文件夹中,先将源文件getBuffPtr添加到Keil的Application/User中,然后再编译下载。 注意:如果找不到getBuffPtr文件,请在STM32MatTarget的安装位置拷贝,默认的安装路径为:C:MATLABSTM32-MAT
[单片机]
simulink开发<font color='red'>STM32</font>串口函数的步骤
个人对STM32 SysTick的总结(寄存器操作)
一、概述: SysTick是一个简单的递减24位计数器。如果你不需要再应用程序中嵌入操作系统,SysTick可以作为简单的延时和产生周期性的中断。 状态控制寄存器的第0位可以使能计数器,当前值寄存器随着时钟一直递减,当他减到0的时候,重装载寄存器就会重新装载这只的值,计数器继续从这个值递减。 二、相关寄存器: 2.1SysTick- CTRL 状态和控制寄存器 位16:当前值寄存器递减到0,位16置1 位2:时钟源选择位,0:使用外部参考时钟;1:使用内核时钟 位1:使能SysTick中断,当前值寄存器递减到0时产生中断 位0:SysTick时钟使能 2.2SysTick- LOAD 重装载值寄存器 当前值寄存器为
[单片机]
个人对<font color='red'>STM32</font> SysTick的总结(寄存器操作)
GD32单片机和STM32单片机的区别
一、前言 什么GD32? GD32是国内开发的一款单片机,据说开发的人员是来自ST公司的,GD32也是以STM32作为模板做出来的。 所以GD32和STM32有很多地方都是一样的,不过GD32毕竟是不同的产品,不可能所有东西都沿用STM32,有些自主开发的东西还是有区别的。相同的地方我们就不说了,下面我给大家讲一下不同的地方。 二、区别 1、内核 GD32采用二代的M3内核,STM32主要采用一代M3内核,下图是ARM公司的M3内核勘误表,GD使用的内核只有752419这一个BUG。 2、主频 使用HSE(高速外部时钟):GD32的主频最大108M,STM32的主频最大72M 使用HSI(高速内部时钟):GD32的主频最大10
[单片机]
GD32单片机和<font color='red'>STM32</font>单片机的区别
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved