简介
在上一个章节中我们已经成功了安装了开发环境,并且运行了第一个demo,在本章节中我们将来驱动DHT11传感器。
1- 首先根据原理图确定我们需要使用的PIN是DH的第一个Pin
因为这里的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;
}示波器输出如下。

4- 连接DHT11

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;
}现象如下所示。

我要赚赏金
