DTH11 温湿度模块

简介: DTH11 温湿度模块

前言

DHT11 是一款可测量 温度 和 湿度 的传感器。比如市面上一些空气加湿器,会测量空气中湿度,再根据测量结果决定是否继续加湿。


一、DTH11 模块介绍

  1. DHT11通信过程:
    主机通过一条数据线与DH11连接,主机通过这条线发命令给DHT11,DHT11再通过这条线把数据发送给主机。
    当主机没有与DHT11通信时,总线处于空闲状态,此时总线电平由于上拉电阻的作用处于高电平。
  • 主机将对应的GPIO管脚配置为输出,准备向DHT11发送数据;
  • 主机发送一个开始信号:
    开始信号 = 一个低脉冲 + 一个高脉冲。低脉冲至少持续18ms,高脉冲持续20-40us。
  • 主机将对应的GPIO管脚配置为输入,准备接受DHT11传来的数据,这时信号由上拉电阻拉高;
  • DHT11发出响应信号:
    响应信号 = 一个低脉冲 + 一个高脉冲。低脉冲持续80us,高脉冲持续80us。
  • DHT11发出数据信号:
    数据为0的一位信号 = 一个低脉冲 + 一个高脉冲。低脉冲持续50us,高脉冲持续26~28us。
    数据为1的一位信号 = 一个低脉冲 + 一个高脉冲。低脉冲持续50us,高脉冲持续70us。
    DHT11发出结束信号:
  • 最后1bit数据传送完毕后,DHT11拉低总线50us,然后释放总线,总线由上拉电阻拉高进入空闲状态。
  • 数据格式:

8 bit 湿度整数数据 + 8 bit 湿度小数数据 + 8 bit 温度整数数据 + 8 bit 温度小数数据 + 8 bit 校验和。(5 字节数据,共 40 位 )

数据传送正确时,校

  1. 验和等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。

二、设备树设置

设备树 中 compatible 与 驱动程序 进行匹配。

将模块分别接到 开发板的 gpio4-19引脚。每一组 GPIO 有 32 个引脚。

配置设备树需要对 GPIO 引脚 以及相关的 pincontrol 配置。由于本实验是使用 DTH11 模块,所以不需要配置 pincontrol 。

三、驱动程序

  1. 根据框架编写基本驱动程序:

首先要 定义一个file_operations 结构体,在入口函数里对其 注册,在 出口函数里卸载。 实现辅助信息,使用 class_create 创建类 , device_create 创建设备节点。

定义一个 platform_driver。也是在入口函数里对其 注册,在 出口函数里卸载。

这些基本代码的详细实现可以参考我之前的文章 :SR501人体红外模块

  1. 实现 probe 函数。
    总线处于空闲状态,此时总线电平由于上拉电阻的作用处于高电平。
static int dht11_probe(struct platform_device *pdev)
{
  /* 获取引脚信息,将其设置为输出引脚高电平 */
  dht11_data_pin = gpiod_get(&pdev->dev, NULL, GPIOD_OUT_HIGH);
  if (IS_ERR(dht11_data_pin))
  {
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  }
  /* 创建设备节点 */
  device_create(dht11_class, NULL, MKDEV(major, 0), NULL, "mydht11");
  return 0;
}
  1. 首先将 gpio 引脚设置为 输出引脚,准备向 DTH11 发送数据。
static void dht11_reset(void)
{
  gpiod_direction_output(dht11_data_pin, 1);
}
  1. 然后主机发送一个开始信号。
    发送开始 信号完毕,将 引脚设置为 输入引脚,等待 DHT11 发送数据,准备接收数据。
static void dht11_start(void)
{
  mdelay(30);
  gpiod_set_value(dht11_data_pin, 0);
  mdelay(20);
  gpiod_set_value(dht11_data_pin, 1);
  udelay(40); 
  gpiod_direction_input(dht11_data_pin);    
  udelay(2);  
}
  1. DHT11 发出响应信号,之后发送数据。
static int dht11_wait_for_ready(void)
{
  int timeout_us = 20000;         //设置超时时间
  /* 等待低电平 */
  while (gpiod_get_value(dht11_data_pin) && --timeout_us)
  {
    udelay(1);
  }
  if (!timeout_us)
  {
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    return -1;
  }
  /* 现在是低电平,等待高电平 */
  timeout_us = 200;
  while (!gpiod_get_value(dht11_data_pin) && --timeout_us)
  {
    udelay(1);
  }
  if (!timeout_us)
  {
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    return -1;
  }
  /*  现在是高电平,等待低电平 */
  timeout_us = 200;
  while (gpiod_get_value(dht11_data_pin) && --timeout_us)
  {
    udelay(1);
  }
  if (!timeout_us)
  {
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    return -1;
  }
  return 0; 
}

读一字节的数据。

每字节八位数据,按位读取。

怎么判断读出的数据是 0 还是 1 呢?

通过判断高电

  1. 平的持续时间可 得出写入的数据。当 高电平 持续26~28us,表示输出 0 。高脉冲持续70us,表明数据是 1 .
static int dht11_read_byte(unsigned char *buf)
{
  int i;
  unsigned char data = 0;
  int timeout_us = 200;
  for (i = 0; i <8; i++)
  {
    /* 现在是低电平 */
    /* 等待高电平 */
    timeout_us = 400;
    while (!gpiod_get_value(dht11_data_pin) && --timeout_us)
    {
      udelay(1);
    }
    if (!timeout_us)
    {
      printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
      return -1;
    }
    /* 现在是高电平 */
    /* 等待低电平,累加高电平的时间 */
    timeout_us = 20000000;
    udelay(40);
    if (gpiod_get_value(dht11_data_pin))
    {
      /* get bit 1 */
      data = (data << 1) | 1;
      /* 当前位的高电平未结束, 等待 */
      timeout_us = 400;
      while (gpiod_get_value(dht11_data_pin) && --timeout_us)
      {
        udelay(1);
      }
      if (!timeout_us)
      {
        printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
        return -1;
      }
    }
    else
    {
      /* get bit 0 */
      data = (data << 1) | 0;
    }
  }
  *buf = data;
  return 0;
}
  1. 读五字节数据。
    将 读出的数据放入数组中,传递给应用程序。
static ssize_t dht11_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
  unsigned long flags;
  int i,err;
  unsigned char data[5];
  if (size != 4)
    return -EINVAL;
  local_irq_save(flags);    // 关中断
  /* 1. 发送高脉冲启动DHT11 */
  dht11_reset();
  dht11_start();
  /* 2. 等待DHT11就绪 */
  if (dht11_wait_for_ready())
  {
    local_irq_restore(flags); // 恢复中断
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    return -EAGAIN;
  }
  /* 3. 读5字节数据 */
  for (i = 0; i < 5; i++)
  {
    if (dht11_read_byte(&data[i]))
    {
      local_irq_restore(flags); // 恢复中断
      printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
      return -EAGAIN;
    }
  }
  dht11_reset();
  local_irq_restore(flags); // 恢复中断
  /* 4. 根据校验码验证数据 */
  if (data[4] != (data[0] + data[1] + data[2] + data[3]))
  {
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    //return -1;
  }
  /* 5. copy_to_user */ 
  /* data[0]/data[1] : 湿度 */
  /* data[2]/data[3] : 温度 */
  err = copy_to_user(buf, data, 4);
  return 4;
}

四、测试程序

判断参数,打开文件,read 函数读出 测出的温度,湿度。

  if (argc != 2) 
  {
    printf("Usage: %s <dev>\n", argv[0]);
    return -1;
  }
  fd = open(argv[1], O_RDWR);     
  if (fd == -1)
  {
    printf("can not open file %s\n", argv[1]);
    return -1;
  }
  while (1)
  {
    if (read(fd, data, 4) == 4)
    {
      printf("get humidity  : %d.%d\n", data[0], data[1]);
      printf("get temprature: %d.%d\n", data[2], data[3]);
    }
    else 
    {
      printf("get humidity/temprature: -1\n");
    }
    sleep(5);       // 等待 5 秒
  }
  close(fd);

五、上机测试及效果

执行 insmod 命令可以将 .ko 文件加载到内核中,再 执行测试程序。(rmmod命令可以卸载已加载的模块,lsmod 命令 可以观察已加载到内核的文件。)

/dev/mydht11 是 驱动程序中创建的设备节点( device_create )。


总结

相关文章
|
8月前
|
传感器 数据采集 数据处理
基于STM32的温湿度监测系统设计与实现
基于STM32的温湿度监测系统设计与实现
1103 1
|
7月前
|
传感器 数据格式
【STM32】DHT11温湿度模块传感器详解&代码
【STM32】DHT11温湿度模块传感器详解&代码
|
8月前
|
传感器
基于STC8H8K64U和DS18B20的温度采集和LabVIEW上位机显示
基于STC8H8K64U和DS18B20的温度采集和LabVIEW上位机显示
基于STC8H8K64U和DS18B20的温度采集和LabVIEW上位机显示
|
8月前
|
数据格式
LabVIEW串口通信的激光器模块智能控制
LabVIEW串口通信的激光器模块智能控制
68 0
|
传感器 编解码 物联网
STC89C52+DHT20设计的环境温湿度检测仪
本项目基于STC89C52单片机和DHT20温湿度传感器,实现了一款环境温湿度检测仪。通过传感器采集环境的温度和湿度数据,利用IIC接口的OLED显示屏显示出来,便于用户实时监测环境温湿度状态。
205 1
|
8月前
|
传感器 监控 C#
使用STM32实现一个简单的温湿度监控系统
使用STM32实现一个简单的温湿度监控系统
236 0
|
传感器 数据采集 SDN
STM32(HAL库)驱动AD8232心率传感器
STM32(HAL库)驱动AD8232心率传感器
STM32(HAL库)驱动SHT30温湿度传感器通过串口进行打印
STM32(HAL库)驱动SHT30温湿度传感器通过串口进行打印
|
传感器 监控
LabVIEW控制Arduino采集DHT11温湿度数值(进阶篇—4)
在多数情况下,测量温度的同时需要测量湿度,本篇博文将介绍使用DHT11温湿度传感器、Arduino Uno和LabVIEW组成温湿度测量系统,可用于粮仓等场合的温湿度监控。
|
传感器
STM32 AHT10温湿度传感器数据
STM32 AHT10温湿度传感器数据 机智云传输温湿度
242 0

热门文章

最新文章