STM32F405RGT6获取DHT11温湿度数据

配置环境:STM32CubeMX、IAR

硬件环境:STM32F405RGT6、DHT11

今天主要给大家分享一个比较简单的温湿度传感器(DHT11),只需要用到GPIO口就能实现。

DHT11读取过程比较简单,我们主要理解其工作时序就行了。

时序图:

这里需要注意的是,在唤醒之前是需要我们设置GPIO口以输出的方式进行唤醒的,然后再切换GPIO输入模式来获取响应信号和数据信号。

响应数据:

DHT11响应信号是收到主机的高电平信号后,输出一个低电平到高电频的转换实现响应信号。同时主机发送响应信号后需要延时等待,所以需要用到定时器实现一个us级别的延时。

每个数据信号开始前都是以一个12-14us的低电频信号开始,然后根据高电平的数据时间长短来区别数据'0'和数据'1'。

数据'0'

数据'1'

配置时钟:

定时器配置:

这里我们使用TIM3

IO配置:

代码实现timer3的us级别延时

//Time3us延时
void DHT11_DelayUs(uint16_t delay)
{
  //关闭定时器
  __HAL_TIM_DISABLE(&htim3);
  //初始化计数器值
  __HAL_TIM_SET_COUNTER(&htim3,0);
  //启动定时器
  __HAL_TIM_ENABLE(&htim3);
  uint16_t curCnt=0;
  while(1)
	{
	curCnt =__HAL_TIM_GET_COUNTER(&htim3);
	if(curCnt>=delay)
         {
          break;
         }
	}
  //关闭定时器
  __HAL_TIM_DISABLE(&htim3);
}

进行DHT11唤醒:

//设置IO口为输入
void DHT11_SetGpioInput()
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  //设置引脚9
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
//设置IO口为输出
void DHT11_SetGpioOutput()
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  //设置引脚9
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
//主机初始信号设置
void MasterResponseTest()
{
  //设置当前IO口为输出
  DHT11_SetGpioOutput();
  //拉低当前信号
  HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9, GPIO_PIN_RESET);
  //拉低30us
  HAL_Delay(30);
  //再次拉高当前信号
  HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9, GPIO_PIN_SET);
  DHT11_DelayUs(40);
}
//dht11响应测试
Bool DHT11_ResponseSignalFeedback()
{
  int temp = 0;
  Bool ret = cFalse;
  //主机初始信号测试
  MasterResponseTest();
  //设置当前IO为输入信号
  DHT11_SetGpioInput();
  //读取到低信号并且未超过响应时间
  while(GPIO_PIN_RESET != HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) && (temp < RES_TIME_MAX))
  {
    temp ++;
    DHT11_DelayUs(1);
  }
  //未超时  响应信号结束
  if(temp < RES_TIME_MAX)
  {
    temp = 0;
  }
  //当读取高信号
  while(GPIO_PIN_SET != HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) && (temp < RES_TIME_MAX))
  {
    temp ++;
    DHT11_DelayUs(1);
  }
  //未超时
  if(temp < RES_TIME_MAX)
  {
    temp = 0;
    ret = cTrue;
  }
  return ret;
}

进行数据读取:

//bit位数据读取
Uint8 DHT11_BitDataRead()
{
  int temp = 0;
  //读取到低电频信号                 :数据起始信号   
  while(GPIO_PIN_RESET != HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9))
  {
    DHT11_DelayUs(1);
  }
  //读取到高电频信号                 :数据信号
  while(GPIO_PIN_SET != HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9))
  {
    DHT11_DelayUs(1);
  }
  //延时一个数据起始信号
  DHT11_DelayUs(30);
  //读取到下起始信号            判断读取时间
  if(GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9))
  {
    temp = 1;
  }
  else
  {
    temp = 0;
  }
  return temp;		
}

//数据读取函数
Uint8 DHT11_DataRead()
{
  Uint8 Index = 0;
  Uint8 data = 0;
  Uint8 buff[7] = {0};
  for(;Index < 8;Index++)
  {
    buff[Index] = DHT11_BitDataRead();
    data |= (buff[Index] << (7 - Index));
  }
  return data;
}

//数据读取函数
void DHT11_ReadInfo(DHT11Info *dht11Info)
{
  //空指针检查
  if(NULL != dht11Info)
  {
    //发送起始信号
    Bool temp = DHT11_ResponseSignalFeedback();
    //起始信号响应成功
    if(cTrue == temp)
    {
      dht11Info->humi_H = DHT11_DataRead();
      dht11Info->humi_L = DHT11_DataRead();
      dht11Info->temputer_H = DHT11_DataRead();
      dht11Info->temputer_L = DHT11_DataRead();
      dht11Info->check = DHT11_DataRead();
    }
    else
    {
      my_printf("DHT11 Err!!\r\n"); 
    }
    
  }
}

这里大家我喜欢把常见的数据类型重新定义一下,大家使用代码时记得在.h中添加上:

typedef unsigned char       Uint8;
typedef signed   char       Int8;
typedef unsigned short      Uint16;
typedef signed   short      Int16;
typedef unsigned long       Uint32;
typedef signed   long       Int32;
typedef unsigned long long  Uint64;
typedef signed   long long  Int64;
typedef float               F32;
typedef float               F64;    /*TODO*/

typedef enum
{
    cTrue = 0x55,
    cFalse = 0xAA,
    EnumReturnNull = 0x00
}Bool;

主函数调用:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
 
  /* USER CODE BEGIN 2 */
  DHT11_ResponseSignalFeedback();
  HAL_Delay(3000);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    DHT11Info dht11Info = {0};
    my_printf("MAIN\r\n");
    DHT11_ReadInfo(&dht11Info);
    my_printf("humi_H:%d\r\n",dht11Info.humi_H);
    my_printf("humi_L:%d\r\n",dht11Info.humi_L); 
    my_printf("temputer_H:%d\r\n",dht11Info.temputer_H); 
    my_printf("temputer_L:%d\r\n",dht11Info.temputer_L); 
    my_printf("check:%d\r\n",dht11Info.check); 
    HAL_Delay(2000);
  }
  /* USER CODE END 3 */
}

说明下为啥在唤醒测试结束后延时3S呢,是为了在开始主逻辑前读取数据前读取数据时序不受影响,保证当前唤醒时序结束,这里可以改成其他值(完成一个读取时序周期即可)。

测试结果:

完整代码:

DHT11.c

/*
模块名称:温湿度传感器
芯片:DHT11
*/
#include "DHT11.h"

/*LED显示模块*/
#include "test.h"

DHT11Info g_dht11_info = {0};                           //温湿度信息

//Time3us延时
void DHT11_DelayUs(uint16_t delay)
{
  //关闭定时器
  __HAL_TIM_DISABLE(&htim3);
  //初始化计数器值
  __HAL_TIM_SET_COUNTER(&htim3,0);
  //启动定时器
  __HAL_TIM_ENABLE(&htim3);
  uint16_t curCnt=0;
  while(1)
	{
	curCnt =__HAL_TIM_GET_COUNTER(&htim3);
	if(curCnt>=delay)
         {
          break;
         }
	}
  //关闭定时器
  __HAL_TIM_DISABLE(&htim3);
}

//设置IO口为输入
void DHT11_SetGpioInput()
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  //设置引脚9
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
//设置IO口为输出
void DHT11_SetGpioOutput()
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  //设置引脚9
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

//主机初始信号设置
void MasterResponseTest()
{
  //设置当前IO口为输出
  DHT11_SetGpioOutput();
  //拉低当前信号
  HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9, GPIO_PIN_RESET);
  //拉低30us
  HAL_Delay(30);
  //再次拉高当前信号
  HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9, GPIO_PIN_SET);
  DHT11_DelayUs(40);
}

//dht11响应测试
Bool DHT11_ResponseSignalFeedback()
{
  int temp = 0;
  Bool ret = cFalse;
  //主机初始信号测试
  MasterResponseTest();
  //设置当前IO为输入信号
  DHT11_SetGpioInput();
  //读取到低信号并且未超过响应时间
  while(GPIO_PIN_RESET != HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) && (temp < RES_TIME_MAX))
  {
    temp ++;
    DHT11_DelayUs(1);
  }
  //未超时  响应信号结束
  if(temp < RES_TIME_MAX)
  {
    temp = 0;
  }
  //当读取高信号
  while(GPIO_PIN_SET != HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) && (temp < RES_TIME_MAX))
  {
    temp ++;
    DHT11_DelayUs(1);
  }
  //未超时
  if(temp < RES_TIME_MAX)
  {
    temp = 0;
    ret = cTrue;
  }
  return ret;
}

//bit位数据读取
Uint8 DHT11_BitDataRead()
{
  int temp = 0;
  //读取到低电频信号                 :数据起始信号   
  while(GPIO_PIN_RESET != HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9))
  {
    DHT11_DelayUs(1);
  }
  //读取到高电频信号                 :数据信号
  while(GPIO_PIN_SET != HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9))
  {
    DHT11_DelayUs(1);
  }
  //延时一个数据起始信号
  DHT11_DelayUs(30);
  //读取到下起始信号            判断读取时间
  if(GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9))
  {
    temp = 1;
  }
  else
  {
    temp = 0;
  }
  return temp;		
}

//数据读取函数
Uint8 DHT11_DataRead()
{
  Uint8 Index = 0;
  Uint8 data = 0;
  Uint8 buff[7] = {0};
  for(;Index < 8;Index++)
  {
    buff[Index] = DHT11_BitDataRead();
    data |= (buff[Index] << (7 - Index));
  }
  return data;
}

//数据读取函数
void DHT11_ReadInfo(DHT11Info *dht11Info)
{
  //空指针检查
  if(NULL != dht11Info)
  {
    //发送起始信号
    Bool temp = DHT11_ResponseSignalFeedback();
    //起始信号响应成功
    if(cTrue == temp)
    {
      dht11Info->humi_H = DHT11_DataRead();
      dht11Info->humi_L = DHT11_DataRead();
      dht11Info->temputer_H = DHT11_DataRead();
      dht11Info->temputer_L = DHT11_DataRead();
      dht11Info->check = DHT11_DataRead();
    }
    else
    {
      my_printf("DHT11 Err!!\r\n"); 
    }
    
  }
}

DHT11.h

#ifndef DHT11_H_
#define DHT11_H_
#include "Comm.h"
#include "gpio.h"
#include "tim.h"

#define RES_TIME_MAX                    100

#define DATA_TIME_MAX                   132 

#define DATA_TIME                       118 
//DHT11 信息结构体
typedef struct
{
  Uint8 temputer_H;             //温度高位
  Uint8 temputer_L;             //温度低位
  Uint8 humi_H;                 //湿度高位
  Uint8 humi_L;                 //湿度低位
  Uint8 check;                  //检查数据位置
}DHT11Info;

//us延时
void DHT11_DelayUs(uint16_t delay);

//dht11响应
Bool DHT11_ResponseSignalFeedback();

//GPIO输入
void DHT11_SetGpioInput();

//GPIO输出
void DHT11_SetGpioOutput();

//主机响应信号测试
void MasterResponseTest();

//数据读取函数
void DHT11_ReadInfo(DHT11Info *dht11Info);


#endif


  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值