fuzidage
专注嵌入式、linux驱动 、arm裸机研究

导航

 

硬件连接:

MCU通过一条数据线与DH11连接,MCU通过这条线发命令给DH11,DH11再通过这条线把数据发送给MCU。

 

温湿度模块的核心就是 MCU发给DH11的命令格式和DH11返回的数据格式。

时序:

 

首先MCU发送一个开始信号S,这个开始信号是一个低脉冲,然后再拉高。等待DHT11应答。

然后,DH11拉低,做出一个响应信号,再拉高,准备发送数据。

接着就是DH11返回的数据。

这些数据一共有40bit,高位先出。(8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和)

数据有40bit: 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和

时序要求:

 

MCU必须先拉低至少18ms,然后再拉高20-40us,DH11再拉低80us以响应,最后再拉高80us.

接下来就是传输数据:

Bit01bit 50us开始后,DHT11拉低数据时间为30us以内

 Bit1:1bit 50us开始后,DHT11拉低数据时间为超过70us

代码实现:

实现GPIO的基本操作:

GPG5,gpio配置如下:

 

 

static void dht11_data_cfg_as_output(void)
{
        GPGCON &= ~(3<<10);
        GPGCON |= (1<<10);
}
static void dht11_data_cfg_as_input(void)
{
        GPGCON &= ~(3<<10);
}

static void dht11_data_set(int val)
{
        if (val)
                GPGDAT |= (1<<5);
        else
                GPGDAT &= ~(1<<5);
}
static int dht11_data_get(void)
{
        if (GPGDAT & (1<<5))
                return 1;
        else
                return 0;
}
DHT11操作:
void dht11_init(void)
{
    dht11_data_cfg_as_output();
    dht11_data_set(1);
    mdelay(2000);
}

static void dht11_start(void)
{
    dht11_data_set(0);
    mdelay(20);
    dht11_data_cfg_as_input();
}

static int dht11_wait_ack(void)
{
    udelay(60);
    return dht11_data_get();
}

static int dht11_recv_byte(void)
{
    int i;
    int data = 0;
    
    for (i = 0; i < 8; i++)
    {
        if (dht11_wait_for_val(1, 1000))
        {
            printf("dht11 wait for high data err!\n\r");
            return -1;
        }
        udelay(40);
        data <<= 1;
        if (dht11_data_get() == 1)
            data |= 1;
        
        if (dht11_wait_for_val(0, 1000))
        {
            printf("dht11 wait for low data err!\n\r");
            return -1;
        }
    }
    
    return data;
}

static int dht11_wait_for_val(int val, int timeout_us)
{
    while (timeout_us--)
    {
        if (dht11_data_get() == val)
            return 0; /* ok */
        udelay(1);
    }
    return -1; /* err */
}


int dht11_read(int *hum, int *temp)
{
    unsigned char hum_m, hum_n;
    unsigned char temp_m, temp_n;
    unsigned char check;        
    
    dht11_start();
    
    if (0 != dht11_wait_ack())
    {
        printf("dht11 not ack, err!\n\r");
        return -1;
    }

    if (0 != dht11_wait_for_val(1, 1000))  /* 等待ACK变为高电平, 超时时间是1000us */
    {
        printf("dht11 wait for ack high err!\n\r");
        return -1;
    }

    if (0 != dht11_wait_for_val(0, 1000))  /* 数据阶段: 等待低电平, 超时时间是1000us */
    {
        printf("dht11 wait for data low err!\n\r");
        return -1;
    }

    hum_m  = dht11_recv_byte();
    hum_n  = dht11_recv_byte();
    temp_m = dht11_recv_byte();
    temp_n = dht11_recv_byte();
    check  = dht11_recv_byte();

    dht11_data_cfg_as_output();
    dht11_data_set(1);

    if (hum_m + hum_n + temp_m + temp_n == check)
    {
        *hum  = hum_m;
        *temp = temp_m;
        mdelay(2000);  /* 读取周期是2S, 不能读太频繁 */
        return 0;
    }
    else
    {
        printf("dht11 checksum err!\n\r");
        return -1;
    }

}

void dht11_test(void)
{
    int hum, temp;
    
    dht11_init();
    
    while (1)
    {
        if (dht11_read(&hum, &temp) !=0 )
        {
            printf("\n\rdht11 read err!\n\r");
            dht11_init();
        }
        else
        {
            printf("\n\rDHT11 : %d humidity, %d temperature\n\r", hum, temp);
        }
    }
}
View Code

 

posted on 2022-04-15 11:37  fuzidage  阅读(775)  评论(0编辑  收藏  举报