驱动程序
#define DT_DRV_COMPAT aosong_dht22
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/device.h>
#include <zephyr/sys/printk.h>
#define DHT22_RST_LOW_DELAY_US 18000
#define DHT22_RST_HIGH_DELAY_US 40
#define DHT22_BIT_DELAY_US 28
#define DHT22_RETRY_MAX 200
struct dht22_config {
struct gpio_dt_spec gpio;
};
struct dht22_data {
float temp;
float humi;
};
static void dht22_set_pin_output(const struct gpio_dt_spec *gpio)
{ gpio_pin_configure_dt(gpio, GPIO_OUTPUT);
}
static void dht22_set_pin_input(const struct gpio_dt_spec *gpio)
{
gpio_pin_configure_dt(gpio, GPIO_INPUT);
}
static void dht22_idle(const struct gpio_dt_spec *gpio)
{
dht22_set_pin_output(gpio);
gpio_pin_set_dt(gpio, 1);
k_busy_wait(1000);
}
static void dht22_reset(const struct gpio_dt_spec *gpio)
{
dht22_idle(gpio);
dht22_set_pin_output(gpio);
gpio_pin_set_dt(gpio, 0);
k_busy_wait(DHT22_RST_LOW_DELAY_US);
gpio_pin_set_dt(gpio, 1);
k_busy_wait(DHT22_RST_HIGH_DELAY_US);
}
static uint8_t dht22_check_ack(const struct gpio_dt_spec *gpio)
{
uint8_t retry = 0;
dht22_set_pin_input(gpio);
while (gpio_pin_get_dt(gpio) && retry < DHT22_RETRY_MAX) {
retry++;
k_busy_wait(1);
}
if (retry >= DHT22_RETRY_MAX) return 1;
retry = 0;
while (!gpio_pin_get_dt(gpio) && retry < DHT22_RETRY_MAX) {
retry++;
k_busy_wait(1);
}
if (retry >= DHT22_RETRY_MAX) return 1;
return 0;
}
static uint8_t dht22_read_bit(const struct gpio_dt_spec *gpio)
{
uint8_t retry = 0;
while (gpio_pin_get_dt(gpio) && retry < DHT22_RETRY_MAX) {
retry++;
k_busy_wait(1);
}
retry = 0;
while (!gpio_pin_get_dt(gpio) && retry < DHT22_RETRY_MAX) {
retry++;
k_busy_wait(1);
}
k_busy_wait(DHT22_BIT_DELAY_US);
return gpio_pin_get_dt(gpio) ? 1 : 0;
}
static uint8_t dht22_read_byte(const struct gpio_dt_spec *gpio)
{
uint8_t byte_val = 0;
for (int i = 0; i < 8; i++) {
byte_val <<= 1;
byte_val |= dht22_read_bit(gpio);
}
return byte_val;
}
static int dht22_read(const struct device *dev)
{
const struct dht22_config *cfg = dev->config;
struct dht22_data *data = dev->data;
uint8_t buf[5] = {0};
dht22_reset(&cfg->gpio);
if (dht22_check_ack(&cfg->gpio) != 0) {
return -EIO;
}
for (int i = 0; i < 5; i++) {
buf[i] = dht22_read_byte(&cfg->gpio);
}
data->humi = (float)((buf[0] << 8) + buf[1]) / 10.0f;
data->temp = (buf[2] & 0x80) ?
-1.0f * (float)(((buf[2] & 0x7F) << 8) + buf[3]) / 10.0f :
(float)((buf[2] << 8) + buf[3]) / 10.0f;
return 0;
}
static int dht22_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
ARG_UNUSED(chan);
return dht22_read(dev);
}
static int dht22_channel_get(const struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct dht22_data *data = dev->data;
if (chan == SENSOR_CHAN_HUMIDITY) {
val->val1 = (int32_t)data->humi;
val->val2 = (int32_t)(data->humi * 100000) % 100000;
} else if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
val->val1 = (int32_t)data->temp;
val->val2 = (int32_t)(data->temp * 100000) % 100000;
}
return 0;
}
static const struct sensor_driver_api dht22_api = {
.sample_fetch = dht22_sample_fetch,
.channel_get = dht22_channel_get,
};
static int dht22_init(const struct device *dev)
{
const struct dht22_config *cfg = dev->config;
if (!device_is_ready(cfg->gpio.port)) return -ENODEV;
dht22_idle(&cfg->gpio);
return 0;
}
#define DHT22_INIT(inst)
static struct dht22_data data_##inst;
static struct dht22_config config_##inst = {
.gpio = GPIO_DT_SPEC_INST_GET(inst, gpios),
};
DEVICE_DT_INST_DEFINE(inst,
dht22_init,
NULL,
&data_##inst,
&config_##inst,
POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY,
&dht22_api);
DT_INST_FOREACH_STATUS_OKAY(DHT22_INIT)这里我重点说一下这个DEVICE_DT_INST_DEFINE宏,这个宏可以说是Zephyr区别于其他RTOS的特色点所在。
这个宏注册设备进内核,注册完后:内核才能找到它,应用能打开它,才能读取到温湿度。
DEVICE_DT_INST_DEFINE( inst, // 设备编号 dht22_init, // 初始化函数 NULL, // 电源管理(不用) &data_##inst, // 该设备的数据区 &config_##inst, // 该设备的配置区 POST_KERNEL, // 启动阶段 CONFIG_SENSOR_INIT_PRIORITY, // 优先级 &dht22_api // 驱动API);
同时呢这个宏DT_INST_FOREACH_STATUS_OKAY(DHT22_INIT),遍历设备树中所有 status = "okay" 且 compatible 匹配的 DHT22 节点,逐个调用 DHT22_INIT (inst)。
下面就是设备树代码
/ {
sensors {
dht22: dht22 {
compatible = "aosong,dht22";
gpios = <&gpioc 1 GPIO_ACTIVE_HIGH>;
status = "okay";
};
};
};然后就是应用层代码本质就是:找到设备 → 读取数据 → 打印结果
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/printk.h>
#define DHT22_NODE DT_INST(0, aosong_dht22)
const struct device *dht22 = DEVICE_DT_GET(DHT22_NODE);
int main(void)
{
struct sensor_value temp, humi;
printk("*** Booting Zephyr OS build v4.2.0 ***n");
printk("DHT22 设备初始化成功n");
while (1) {
int ret = sensor_sample_fetch(dht22);
if (ret == 0) {
sensor_channel_get(dht22, SENSOR_CHAN_AMBIENT_TEMP, &temp);
sensor_channel_get(dht22, SENSOR_CHAN_HUMIDITY, &humi);
printk("温度: %d.%d°C | 湿度: %d.%d%%RHn",
temp.val1, temp.val2 / 100000,
humi.val1, humi.val2 / 100000);
}
else {
printk("读取失败,错误码: %dn", ret);
}
k_sleep(K_SECONDS(2));
}
}1最关键:找到设备树里的 DHT22
#define DHT22_NODE DT_INST(0, aosong_dht22)
2. 根据设备节点,获取设备指针
const struct device *dht22 = DEVICE_DT_GET(DHT22_NODE);
拿到驱动里 DEVICE_DT_INST_DEFINE 注册进内核的设备
实际的读取到的数据图片如下

我要赚赏金
