这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 有奖活动 » 【e起DIY】低功耗蓝牙温湿度计:驱动DHT11

共1条 1/1 1 跳转至

【e起DIY】低功耗蓝牙温湿度计:驱动DHT11

高工
2026-06-07 17:28:45     打赏

简介

在上一个章节中我们已经成功了安装了开发环境,并且运行了第一个demo,在本章节中我们将来驱动DHT11传感器。


1- 首先根据原理图确定我们需要使用的PIN是DH的第一个Pin

image.png因为这里的pin已经被I2c给占用了,所以要在Zephyr 中解绑这个PIN

2- 解绑I2C占用

在项目目录下创建boards文件夹,然后创建frdm_mcxw71.overlay文件,并且输入下面内容

#include <zephyr/dt-bindings/gpio/gpio.h>

&lpi2c1 {
	status = "disabled";
};


3- 尝试使用GPIO toggle来判断IO是否解绑。

/*
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>

#define PTB5_PORT DT_NODELABEL(gpiob)
#define PTB5_PIN 5

static const struct device *const ptb5_port = DEVICE_DT_GET(PTB5_PORT);

static void ptb5_toggle_thread(void *, void *, void *)
{
    if (!device_is_ready(ptb5_port)) {
        printk("PTB5 GPIO port is not ready\n");
        return;
    }

    if (gpio_pin_configure(ptb5_port, PTB5_PIN, GPIO_OUTPUT_INACTIVE) != 0) {
        printk("Failed to configure PTB5 as output\n");
        return;
    }

    while (true) {
        gpio_pin_toggle(ptb5_port, PTB5_PIN);
        k_msleep(500);
    }
}

K_THREAD_DEFINE(ptb5_toggle_thread_id, 1024, ptb5_toggle_thread,
        NULL, NULL, NULL, 5, 0, 0);

int main(void)
{
    printk("PTB5 toggle thread started\n");
    return 0;
}

示波器输出如下。

d3a2d576165f5d867f305af20280f595.jpg

4- 连接DHT11

a42a406569e608a7cb7e5278e03f0f81.jpg

5- 读取DHT11, 我这里最初尝试的是使用Zephyr 内的驱动来读取DHT11,但是没有成功。后来在AI的帮助下完成了下面的使用GPIO模拟单线制的读取。

/*
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>

#define DHT_PORT DT_NODELABEL(gpiob)
#define DHT_PIN 5

static const struct device *const dht_port = DEVICE_DT_GET(DHT_PORT);

static int signal_duration_us(bool active)
{
    uint32_t start_cycles = k_cycle_get_32();
    uint32_t elapsed_cycles;
    uint32_t max_wait_cycles = (uint32_t)((uint64_t)100U *
                             (uint64_t)sys_clock_hw_cycles_per_sec() /
                             (uint64_t)USEC_PER_SEC);
    int rc;

    do {
        rc = gpio_pin_get(dht_port, DHT_PIN);
        elapsed_cycles = k_cycle_get_32() - start_cycles;

        if ((rc < 0) || (elapsed_cycles > max_wait_cycles)) {
            return -1;
        }
    } while ((bool)rc == active);

    return (int)((uint64_t)elapsed_cycles * USEC_PER_SEC /
             (uint64_t)sys_clock_hw_cycles_per_sec());
    }

static int dht11_read(uint8_t *humidity_int, uint8_t *temperature_int)
    {
    uint8_t data[5] = { 0 };
    int lock;
    unsigned int bit_index;
    unsigned int byte_index;

    if (!device_is_ready(dht_port)) {
        printk("GPIOB port is not ready\n");
        return -ENODEV;
    }

    lock = irq_lock();

    if (gpio_pin_configure(dht_port, DHT_PIN, GPIO_OUTPUT_INACTIVE) != 0) {
        irq_unlock(lock);
        return -EIO;
    }

    k_busy_wait(18000);

    if (gpio_pin_configure(dht_port, DHT_PIN, GPIO_INPUT | GPIO_PULL_UP) != 0) {
        irq_unlock(lock);
        return -EIO;
    }

    k_busy_wait(40);

    if (signal_duration_us(true) < 0) {
        irq_unlock(lock);
        return -EIO;
    }

    if (signal_duration_us(false) < 0) {
        irq_unlock(lock);
        return -EIO;
    }

    if (signal_duration_us(true) < 0) {
        irq_unlock(lock);
        return -EIO;
    }

    for (bit_index = 0; bit_index < 40; bit_index++) {
        int low_us = signal_duration_us(false);
        int high_us;
        uint8_t bit;

        if (low_us < 0) {
            irq_unlock(lock);
            return -EIO;
        }

        high_us = signal_duration_us(true);
        if (high_us < 0) {
            irq_unlock(lock);
            return -EIO;
        }

        bit = (high_us > 50) ? 1U : 0U;
        byte_index = bit_index / 8U;
        data[byte_index] = (uint8_t)((data[byte_index] << 1) | bit);
    }

    irq_unlock(lock);

    if (((uint8_t)(data[0] + data[1] + data[2] + data[3])) != data[4]) {
        return -EIO;
    }

    *humidity_int = data[0];
    *temperature_int = data[2];

    return 0;
    }

static void dht11_reader_thread(void *, void *, void *)
    {
    uint8_t humidity;
    uint8_t temperature;
    int ret;

    if (!device_is_ready(dht_port)) {
        printk("GPIOB port is not ready\n");
        return;
    }

    while (true) {
        ret = dht11_read(&humidity, &temperature);
        if (ret != 0) {
            printk("Failed to read DHT11: %d\n", ret);
        } else {
            printk("DHT11 temp: %u C, humidity: %u %%\n",
                   temperature, humidity);
        }

        k_sleep(K_SECONDS(2));
    }
}

K_THREAD_DEFINE(dht11_reader_thread_id, 1024, dht11_reader_thread,
        NULL, NULL, NULL, 5, 0, 0);

int main(void)
{
    printk("DHT11 reader thread started\n");
    return 0;
}

现象如下所示。

image.png





关键词: Zephyr     蓝牙     湿度计    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]