打印
[DemoCode下载]

DHT11操作示例

[复制链接]
987|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gejigeji521|  楼主 | 2023-2-12 20:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
读取传感器DHT11的湿度和温度数据
使用NUC240的GPIO (PA.0)和TIMER0读取DHT11的湿度和温度数据。DHT11是个常见的数字湿度、温度传感器。DHT11使用简化的单总线通讯方式交换数据。数据长度为40位,数据格式如所下表所示:


藉由GPIO和TIMER0,使用者可以产生与DHT11通讯的波形。请从以下链接,参考DHT11的规格数据,了解更详细的时序图。
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
* $Revision: 1 $
* $Date: 19/06/26 8:14p $
* [url=home.php?mod=space&uid=247401]@brief[/url]    Use GPIO and TIMER0 to read DHT11 temperature and humidity
*           data
*
* @note
* Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "NUC230_240.h"

/*---------------------------------------------------------------------------*/
/* Define                                                                    */
/*---------------------------------------------------------------------------*/
#define PLL_CLOCK   72000000
#define Data_Pin    PA0
#define Data_Port   PA
#define Data_PinMsk BIT0
#define Max_Data0_Time 40

/*---------------------------------------------------------------------------*/
/* Global variables                                                          */
/*---------------------------------------------------------------------------*/
uint8_t g_u8Humidity_Int, g_u8Humidity_Dec;
uint8_t g_u8Temperature_Int, g_u8Temperature_Dec;

/*---------------------------------------------------------------------------*/
/* Functions                                                                 */
/*---------------------------------------------------------------------------*/
uint32_t DHT11_Reset(void);
uint32_t DHT11_Read(void);
void SYS_Init(void);
void TMR0_Init(void);
void UART0_Init(void);
void Delay_mS(uint32_t m_second);

uint32_t DHT11_Reset(void)
{
    uint32_t u32_poll_time;

    /* The Quasi-bidirection mode could be used as input with pull-up enable */
    GPIO_SetMode(Data_Port, Data_PinMsk, GPIO_PMD_QUASI);

    /* Send out start signal to DHT11 */
    /* Set data pin level from high to low */
    Data_Pin = 1;
    Data_Pin = 0;
    /* Take at least 18 ms to ensure DHT11's detection of signal */
    CLK_SysTickDelay(18000);
    /* Pull up data pin */
    Data_Pin = 1;

    /* Record current timer counter value */
    u32_poll_time = TIMER_GetCounter(TIMER0);

    /* Wait response from DHT11 by pulling down data pin */
    while (1)
    {
        if (Data_Pin == 0)
        {
            break;
        }

        if ((TIMER_GetCounter(TIMER0) - u32_poll_time) > 1000)
            /* DHT11 doesn't response over 1 ms */
            return FALSE;
    }

    /* Wait until DHT11 pulls up data pin level */
    while (1)
    {
        if (Data_Pin == 1)
        {
            break;
        }
    }

    /* Send start signal successfully */
    return TRUE;
}

uint32_t DHT11_Read(void)
{
    uint32_t i;
    uint32_t u32_prev_time;
    uint8_t u8Checksum;

    /* Init TIMER0 to measure high level time */
    TMR0_Init();

    /* Start communicate with DHT11 */
    if (DHT11_Reset() == TRUE)
    {
        /* Wait until DHT11 starts data transmission */
        while (Data_Pin == 1);

        /* A complete data transmission is 40 bits, DHT11 sends MSB first */
        /* 1st 8 bits is humidity integral data */
        g_u8Humidity_Int = 0;

        for (i = 0; i < 8; i++)
        {
            /* Shift current data for next bit */
            g_u8Humidity_Int = g_u8Humidity_Int << 1;

            /* Wait until DHT11 pull high data pin */
            while (Data_Pin == 0);

            /* Measure the high level time to determine the data bit */
            u32_prev_time = TIMER_GetCounter(TIMER0);

            while (Data_Pin == 1);

            if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
            {
                g_u8Humidity_Int |= 0x01;
            }
        }

        /* 2nd 8 bits is humidity decimal data */
        g_u8Humidity_Dec = 0;

        for (i = 0; i < 8; i++)
        {
            /* Shift current data for next bit */
            g_u8Humidity_Dec = g_u8Humidity_Dec << 1;

            /* Wait until DHT11 pull high data pin */
            while (Data_Pin == 0);

            /* Measure the high level time to determine the data bit */
            u32_prev_time = TIMER_GetCounter(TIMER0);

            while (Data_Pin == 1);

            if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
            {
                g_u8Humidity_Dec |= 0x01;
            }
        }

        /* 3rd 8 bits is temperature integral data */
        g_u8Temperature_Int = 0;

        for (i = 0; i < 8; i++)
        {
            /* Shift current data for next bit */
            g_u8Temperature_Int = g_u8Temperature_Int << 1;

            /* Wait until DHT11 pull high data pin */
            while (Data_Pin == 0);

            /* Measure the high level time to determine the data bit */
            u32_prev_time = TIMER_GetCounter(TIMER0);

            while (Data_Pin == 1);

            if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
            {
                g_u8Temperature_Int |= 0x01;
            }
        }

        /* 4th 8 bits is temperature decimal data */
        g_u8Temperature_Dec = 0;

        for (i = 0; i < 8; i++)
        {
            /* Shift current data for next bit */
            g_u8Temperature_Dec = g_u8Temperature_Dec << 1;

            /* Wait until DHT11 pull high data pin */
            while (Data_Pin == 0);

            /* Measure the high level time to determine the data bit */
            u32_prev_time = TIMER_GetCounter(TIMER0);

            while (Data_Pin == 1);

            if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
            {
                g_u8Temperature_Dec |= 0x01;
            }
        }

        /* 5th 8 bits is checksum */
        u8Checksum = 0;

        for (i = 0; i < 8; i++)
        {
            /* Shift current data for next bit */
            u8Checksum = u8Checksum << 1;

            /* Wait until DHT11 pull high data pin */
            while (Data_Pin == 0);

            /* Measure the high level time to determine the data bit */
            u32_prev_time = TIMER_GetCounter(TIMER0);

            while (Data_Pin == 1);

            if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
            {
                u8Checksum |= 0x01;
            }
        }

        /* Stop TIMER0 */
        TIMER_Stop(TIMER0);

        /* Compare received data and checksum */
        if ((uint8_t)(g_u8Humidity_Int + g_u8Humidity_Dec + g_u8Temperature_Int + g_u8Temperature_Dec) == \
                u8Checksum)
        {
            return TRUE;
        }
        else
        {
            printf("Checksum error!\n");

            return FALSE;
        }
    }
    else
    {
        /* Stop TIMER0 */
        TIMER_Stop(TIMER0);

        printf("DHT11 is no response.\n");

        return FALSE;
    }
}

void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Enable Internal RC 22.1184MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

    /* Waiting for Internal RC clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

    /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

    /* Set core clock as PLL_CLOCK from PLL */
    CLK_SetCoreClock(PLL_CLOCK);

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock and CycylesPerUs automatically. */
    SystemCoreClockUpdate();

    /* Enable UART module clock */
    CLK_EnableModuleClock(UART0_MODULE);

    /* Enable TIMER0 module clock */
    CLK_EnableModuleClock(TMR0_MODULE);

    /* Select UART module clock source */
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_CLKDIV_UART(1));

    /* Select TIMER0 module clock source */
    CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0_S_HCLK, NULL);

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Set GPB multi-function pins for UART0 RXD and TXD */
    SYS->GPB_MFP = (SYS->GPB_MFP & ~(SYS_GPB_MFP_PB0_Msk | SYS_GPB_MFP_PB1_Msk)) | \
                   (SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD);
}

void UART0_Init()
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Reset UART0 */
    SYS_ResetModule(UART0_RST);

    /* Configure UART0 and set UART0 Baudrate */
    UART_Open(UART0, 115200);
}

void TMR0_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init TIMER                                                                                              */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Reset TIMER0 */
    SYS_ResetModule(TMR0_RST);

    /* Set periodic mode */
    TIMER0->TCSR = TIMER_PERIODIC_MODE;

    /* Set prescaler value to make unit count time is 1 us */
    /* Timer clock input is HCLK = 72 MHz, prescaler value is HCLK/(10^6) - 1 = 71 */
    TIMER_SET_PRESCALE_VALUE(TIMER0, SystemCoreClock / 1000000 - 1);

    /* Set 24-bit comapre register value to maximum value 0xFFFFFF */
    TIMER_SET_CMP_VALUE(TIMER0, 0xFFFFFF);

    /* Enable TDR_EN to make TDR register be updated continuously to monitor 24-bit up counter value */
    TIMER0->TCSR |= TIMER_TCSR_TDR_EN_Msk;

    /* Start TIMER0 */
    TIMER_Start(TIMER0);
}

void Delay_mS(uint32_t m_second)
{
    uint32_t i;

    for (i = 0; i < m_second; i++)
    {
        TIMER_Delay(TIMER0, 1000);
    }
}

/*---------------------------------------------------------------------------------------------------------*/
/*  MAIN function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Init System, peripheral clock and multi-function I/O */
    SYS_Init();

    /* Lock protected registers */
    SYS_LockReg();

    /* Init UART0 for printf */
    UART0_Init();

    printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
    printf("+--------------------------------------------------+\n");
    printf("|    Read DHT11 data Sample Code                   |\n");
    printf("|    Use GPIO(PA.0) and TIMER0 to read DHT11 data  |\n");
    printf("|    Please connect PA.0 to DHT11 data pin         |\n");
    printf("+--------------------------------------------------+\n\n");

    while (1)
    {
        /* Delay 1.5 seconds */
        Delay_mS(1500);

        if (DHT11_Read() == TRUE)
        {
            printf("Humidity: %d.%d, ", g_u8Humidity_Int, g_u8Humidity_Dec);
            printf("Temperature: %d.%d\n", g_u8Temperature_Int, g_u8Temperature_Dec);
        }
    }
}

/*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/



使用特权

评论回复
沙发
gejigeji521|  楼主 | 2023-2-12 20:06 | 只看该作者
DHT11-Technical-Data-Sheet-Translated-Version.pdf (1.42 MB)

使用特权

评论回复
板凳
中国龙芯CDX| | 2023-2-13 09:05 | 只看该作者
DHT11有极高的可靠性和卓越的长期稳定性

使用特权

评论回复
地板
小夏天的大西瓜| | 2023-2-14 09:20 | 只看该作者
有已校准数字信号输出的温湿度复合传感器可应用到自动控制或者检测设备

使用特权

评论回复
5
稳稳の幸福| | 2023-2-14 14:01 | 只看该作者
GPIO_PMD_QUASI,是不是一定这个模式,其他模式应该不行的吧

使用特权

评论回复
6
AdaMaYun| | 2023-2-24 14:32 | 只看该作者
应用专用的数字模块采集技术和温湿度传感技术

使用特权

评论回复
7
yangxiaor520| | 2023-2-24 19:37 | 只看该作者
DHT11,挺经典的一款温湿度传感器,大学时测量温湿度就用的这个。

使用特权

评论回复
8
zhuotuzi| | 2023-2-25 19:56 | 只看该作者
时序跟18B20一样吗

使用特权

评论回复
9
dongnanxibei| | 2023-2-26 20:05 | 只看该作者
跟18B20的通讯时序一样吗

使用特权

评论回复
10
OKAKAKO| | 2023-2-27 15:54 | 只看该作者
应用挺多的暖通空调 测试及检测设备 湿度调节器 除湿器

使用特权

评论回复
11
szt1993| | 2023-2-28 12:31 | 只看该作者
DHT11体积小功耗低,很多环境都能用

使用特权

评论回复
12
中国龙芯CDX| | 2023-2-28 14:16 | 只看该作者

DHT11的数据手册了解一下

使用特权

评论回复
13
LOVEEVER| | 2023-2-28 14:28 | 只看该作者
等效替换温度传感器:DHT22,AM2302,SHT71

使用特权

评论回复
14
AloneKaven| | 2023-3-1 20:04 | 只看该作者
和18B20的通讯时序一样吗

使用特权

评论回复
15
tpgf| | 2023-3-6 10:52 | 只看该作者
DHT11传感器是通过哪种数据总线和单片机进行数据交互的啊

使用特权

评论回复
16
八层楼| | 2023-3-6 11:19 | 只看该作者
这种温湿度计的实时性能如何 大概有多少的延时啊

使用特权

评论回复
17
观海| | 2023-3-6 11:33 | 只看该作者
DHT11的检测精度能达到多少啊?和什么因数有关系呢

使用特权

评论回复
18
guanjiaer| | 2023-3-6 12:04 | 只看该作者
这种传感器的温湿度测量范围都是多少啊 能适用于恶劣的环境吗

使用特权

评论回复
19
heimaojingzhang| | 2023-3-6 12:16 | 只看该作者
非常经典的一款传感器了  运行起来应该也很稳定

使用特权

评论回复
20
keaibukelian| | 2023-3-6 12:47 | 只看该作者
一条总线上可以挂多少个这种型号的传感器呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

177

主题

2208

帖子

8

粉丝