查看: 3140|回复: 3

[经验] GD32F207读DHT11传感器的温湿度值

[复制链接]
  • TA的每日心情

    2023-7-25 22:49
  • 签到天数: 385 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2016-2-4 12:10:16 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 党国特派员 于 2016-2-5 00:25 编辑

    1、DHT11介绍
    DHT11是一款比较便宜的温湿度传感器模块。读取数据只需要占用一个IO口。能够同时测量温度和相对湿度。
    2、接口说明
    建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻
    111.jpg
    3、电源引脚
    DHT11的供电电压为 3-5.5V。传感器上电后,要等待 1s 以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去耦滤波。
    4、串行接口(单纯双向)
    DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:
    一次完整的数据传输为40bit,高位先出。
    数据格式:8bit湿度整数数据+8bit湿度小数数据
    +8bi温度整数数据+8bit温度小数数据
             +8bit校验和
    数据传送正确时校验和数据等于8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据所得结果的末8位。
    用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。
    5、驱动代码
    dht11.h
    1. /**
    2. ****************************************************************************************
    3. *
    4. * @file dht11.h
    5. *
    6. * @brief dht11传感器操作模块头文件
    7. *
    8. * Copyright (C) sunsjw 2015
    9. *
    10. * $Rev: 1.0 $
    11. *
    12. ****************************************************************************************
    13. */
    14. #ifndef __DHT11_H
    15. #define __DHT11_H

    16. #include <stdint.h>
    17. //IO操作函数        


    18. #define PBout(n) BITBAND_REG(PTB->PDOR,n)
    19. #define PBin(n) BITBAND_REG(PTB->PDIR,n)

    20. #define        DHT11_DQ_OUT PBout(0) //数据端口        PB0
    21. #define        DHT11_DQ_IN  GPIO_ReadInputBit(GPIOC,GPIO_PIN_0)  //数据端口        PB0

    22. #define DHT11_SETOUT    GPIOC->CTLR1 = (GPIOC->CTLR1 & 0xFFFFFFF0 | 0x01)
    23. #define DHT11_SETIN     GPIOC->CTLR1 = (GPIOC->CTLR1 & 0xFFFFFFF0 | 0x08)

    24. #define DHT11_HIGH      GPIO_SetBits(GPIOC,GPIO_PIN_0)
    25. #define DHT11_LOW       GPIO_ResetBits(GPIOC,GPIO_PIN_0)

    26. void DHT11_Init(void);               //初始化DHT11
    27. uint16_t DHT11_Read_Data(void);        //读取温湿度
    28. uint8_t DHT11_Read_Byte(void);  //读出一个字节
    29. uint8_t DHT11_Read_Bit(void);   //读出一个位
    30. uint8_t DHT11_Check(void);      //检测是否存在DHT11
    31. void DHT11_Rst(void);           //复位DHT11  


    32. #endif
    复制代码
    dht11.c
    1. /**
    2. ****************************************************************************************
    3. *
    4. * @file dht11.c
    5. *
    6. * @brief dht11传感器操作模块文件
    7. *
    8. * Copyright (C) sunsjw 2015
    9. *
    10. * $Rev: 1.0 $
    11. *
    12. ****************************************************************************************
    13. */
    14. #include "gd32f20x_gpio.h"              // Keil::Device:StdPeriph Drivers:GPIO

    15. #include "dht11.h"
    16. #include "delay.h"

    17. /*!
    18. * @brief 复位DHT11
    19. *
    20. * @param None
    21. *
    22. * @return None
    23. */
    24. void DHT11_Rst(void)
    25. {
    26.     DHT11_SETOUT;
    27.         DelayUs(1);
    28.     DHT11_LOW;             //拉低DQ
    29.     DelayMs(20);    //拉低至少18ms
    30.     DHT11_HIGH;         //DQ=1
    31.     DelayUs(30);    //主机拉高20~40us        
    32. }

    33. /*!
    34. * @brief 等待DHT11的回应
    35. *
    36. * @param None
    37. *
    38. * @return 0:未检测到DHT11的存在,(低电平80us,高电平80us),1:存在
    39. */
    40. uint8_t DHT11_Check(void)
    41. {
    42.     uint8_t retry=0;
    43.     DHT11_SETIN;
    44.     //DHT11_IO_IN();//SET INPUT
    45.     while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
    46.     {
    47.         retry++;
    48.         DelayUs(1);
    49.     };
    50.     if(retry>=100)
    51.       return 0;
    52.     else
    53.       retry=0;
    54.     while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
    55.     {
    56.         retry++;
    57.         DelayUs(1);
    58.     };
    59.     if(retry>=100)
    60.       return 0;
    61.     return 1;
    62. }

    63. /*!
    64. * @brief 从DHT11读取一个位 (起始位50us低电平,26-28us高电平代表0,70us高电平代表1)
    65. *
    66. * @param None
    67. *
    68. * @return 1/0
    69. */
    70. uint8_t DHT11_Read_Bit(void)
    71. {
    72.     uint8_t retry=0;
    73.     while(DHT11_DQ_IN&&retry<100)//等待变为低电平
    74.     {
    75.         retry++;
    76.         DelayUs(1);
    77.     }
    78.     retry=0;
    79.     while(!DHT11_DQ_IN&&retry<100)//等待变高电平
    80.     {
    81.         retry++;
    82.         DelayUs(1);
    83.     }

    84.     DelayUs(35);//等待40us
    85.     if(DHT11_DQ_IN)
    86.       return 1;
    87.     else
    88.       return 0;
    89. }

    90. /*!
    91. * @brief 从DHT11读取一个字节
    92. *
    93. * @param None
    94. *
    95. * @return 读到的数据
    96. */
    97. uint8_t DHT11_Read_Byte(void)
    98. {
    99.     uint8_t i,dat;
    100.     DHT11_SETIN;
    101.     dat=0;
    102.     for (i=0; i<8; i++)
    103.     {
    104.         dat<<=1;
    105.         dat|=DHT11_Read_Bit();
    106.     }
    107.     return dat;
    108. }

    109. /*!
    110. * @brief 从DHT11读取一次数据
    111. *
    112. * @param None
    113. * @param[in,out] temp:温度值(范围:0~50°),humi:湿度值(范围:20%~90%)
    114. * @return 0:读取失败,非0值:高8位是温度值,低8位是湿度值
    115. */
    116. uint16_t DHT11_Read_Data()
    117. {
    118.     uint8_t buf[5];
    119.         uint16_t result;
    120.     uint8_t i;
    121.     DHT11_Rst();
    122.     if(DHT11_Check())
    123.     {
    124.         for(i=0; i<5; i++) //读取40位数据
    125.         {
    126.             buf[i]=DHT11_Read_Byte();
    127.         }
    128.         if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
    129.         {
    130.                         result = buf[2];
    131.                         result <<= 8;
    132.             result |= buf[0];
    133.         }
    134.     }
    135.     else
    136.       return 0;
    137.     return result;
    138. }

    139. /*!
    140. * @brief 初始化DHT11的IO口 DQ 同时检测DHT11的存在
    141. *
    142. * @param None
    143. *
    144. * @return None
    145. */
    146. void DHT11_Init(void)
    147. {
    148.         GPIO_InitPara gpio_stru;
    149.         /*初始化DHT11使用的GPIO*/
    150.         gpio_stru.GPIO_Mode = GPIO_MODE_OUT_PP;
    151.         gpio_stru.GPIO_Pin = GPIO_PIN_0;
    152.         gpio_stru.GPIO_Speed = GPIO_SPEED_10MHZ;
    153.         
    154.         GPIO_Init(GPIOC,&gpio_stru);
    155.         GPIO_SetBits(GPIOC,GPIO_PIN_0);
    156.         
    157. }







    复制代码
    主程序main.c
    1. #include <stdio.h>
    2. #include "gd32f20x.h"                   // Device header
    3. #include "cmsis_os.h"                   // ARM::CMSIS:RTOS:Keil RTX

    4. #include "delay.h"
    5. #include "dht11.h"
    6. #include "oled.h"


    7. uint8_t showBuffer[32];

    8. void RCC_config(void);
    9. void GPIO_config(void);
    10. void SPI_config(void);


    11. void ShowDHT11(void);


    12. void thread_led(const void *arg)
    13. {
    14.         uint16_t pin = (uint16_t)arg;
    15.         for(;;)
    16.         {
    17.                 if(GPIO_ReadOutputBit(GPIOD,pin))
    18.                         GPIO_ResetBits(GPIOD,pin);
    19.                 else
    20.                         GPIO_SetBits(GPIOD,pin);
    21.                
    22.                 osDelay(pin);
    23.         }
    24. }



    25. void task_dht11(const void* arg)
    26. {
    27.         for(;;)
    28.         {
    29.                 ShowDHT11();
    30.                 osDelay(1000);
    31.         }
    32. }

    33. osThreadDef(thread_led,osPriorityNormal,3,0);
    34. osThreadDef(task_dht11,osPriorityHigh,1,0);


    35. int main()
    36. {   
    37.         osKernelInitialize();
    38.         
    39.         RCC_config();
    40.         GPIO_config();
    41.         SPI_config();

    42.         
    43.         DelayInit();
    44.         DHT11_Init();
    45.         OLED_Init();
    46.         OLED_Clear();
    47.         GP2Y_init();
    48.         
    49.         osThreadCreate(osThread(thread_led),(void*)GPIO_PIN_11);
    50.         
    51.         osThreadCreate(osThread(task_dht11),NULL);
    52.         
    53.         osKernelStart();
    54.         while(1)
    55.         {
    56.                 osDelay(1000);
    57.         }
    58. }

    59. void RCC_config(void)
    60. {
    61.     RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOA|RCC_APB2PERIPH_GPIOD|RCC_APB2PERIPH_GPIOC,ENABLE);

    62.         RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_SPI1,ENABLE);
    63.         RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_ADC1,ENABLE);
    64.         
    65.         RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_USART2,ENABLE);
    66.         RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_TIMER6,ENABLE);
    67.         RCC_ADCCLKConfig(RCC_ADCCLK_APB2_DIV6);
    68. }

    69. void GPIO_config(void)
    70. {
    71.         /*初始化LED灯的GPIO*/
    72.         GPIO_InitPara gpio_stru;
    73.         gpio_stru.GPIO_Mode = GPIO_MODE_OUT_PP;
    74.         gpio_stru.GPIO_Speed = GPIO_SPEED_10MHZ;
    75.         gpio_stru.GPIO_Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
    76.         
    77.         GPIO_Init(GPIOD,&gpio_stru);
    78. }


    79. void SPI_config(void)
    80. {
    81.         SPI_InitPara spi_stru;
    82.         
    83.         spi_stru.SPI_FirstBit = SPI_FIRSTBIT_MSB;
    84.         spi_stru.SPI_FrameFormat =  SPI_FRAMEFORMAT_8BIT;
    85.         spi_stru.SPI_Mode = SPI_MODE_MASTER;
    86.         spi_stru.SPI_PSC = SPI_PSC_64;
    87.         spi_stru.SPI_SCKPH = SPI_SCKPH_1EDGE;
    88.         spi_stru.SPI_SCKPL = SPI_SCKPL_LOW;
    89.         spi_stru.SPI_SWNSSEN = SPI_SWNSS_SOFT;
    90.         spi_stru.SPI_TransType = SPI_TRANSTYPE_BDMTX;
    91.         spi_stru.SPI_CRCPOL = 7;
    92.         
    93.         SPI_Init(SPI1,&spi_stru);
    94.         SPI_CRC_Enable(SPI1,DISABLE);
    95.         SPI_Enable(SPI1,ENABLE);
    96. }


    97. void ShowDHT11(void)
    98. {
    99.         uint16_t data = DHT11_Read_Data();

    100.         sprintf((char*)showBuffer,":%3d",data>>8);
    101.         OLED_ShowCHinese(0,2,6);//显示汉字温
    102.         OLED_ShowCHinese(16,2,8);//显示汉字度
    103.         OLED_ShowString(32,2,showBuffer);
    104.         OLED_ShowCHinese(64,2,9);//显示℃

    105.         sprintf((char*)showBuffer,":%3d",data & 0xFF);
    106.         OLED_ShowCHinese(0,4,7);//显示汉字温
    107.         OLED_ShowCHinese(16,4,8);//显示汉字度
    108.         OLED_ShowString(32,4,showBuffer);
    109.         OLED_ShowCHinese(64,4,11);//显示%
    110. }
    复制代码
    实验效果:
    IMG_20160205_001730.jpg



    回复

    使用道具 举报

  • TA的每日心情
    开心
    2018-11-19 16:39
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2016-2-16 13:59:10 | 显示全部楼层
    亲,可以将内容一并发到经验频道,很有机会获得每月之星的呢http://jingyan.eeboard.com/
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2023-7-25 22:49
  • 签到天数: 385 天

    连续签到: 1 天

    [LV.9]以坛为家II

     楼主| 发表于 2016-2-17 10:12:22 | 显示全部楼层
    糖悦之果飞 发表于 2016-2-16 13:59
    亲,可以将内容一并发到经验频道,很有机会获得每月之星的呢http://jingyan.eeboard.com/ ...

    我申请了四篇,才通过一篇呢?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-11-19 16:39
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2016-2-17 16:12:23 | 显示全部楼层
    党国特派员 发表于 2016-2-17 10:12
    我申请了四篇,才通过一篇呢?

    都通过了的呢,工程师比较慢,有时候审核比较慢些,请谅解
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-4-26 14:50 , Processed in 0.132760 second(s), 22 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.