跳到主要内容

DHT11

本文旨在详细介绍如何使用 Luckfox Pico Plus 来驱动 DHT11 温湿度传感器模块,我们采用的是微雪的 DHT11(温湿度传感器) 模块,屏幕的具体参数可以查看 DHT11(温湿度传感器)的产品wiki。您可以下载镜像文件和示例程序直接使用或按照步骤自己配置。

1. 快速使用

1.1 烧录镜像

烧录文章开头提供的镜像。

1.2 硬件连接

Luckfox Pico

Luckfox Pico Plus

Luckfox Pico Pro/Max

连接引脚对应关系

DHT11Pico / Plus / Pro / Max功能
VCC3V3电源输入
GNDGDN电源地
DOUTGPIO1_C7_d(55)通信端口

1.3 导入模块

连接好模块后上电,将示例程序中的 dht11_drv.ko 和 dht11 文件拷贝到开发板,导入模块:

insmod dht11_drv.ko

1.4 运行程序

chmod +x dht11
./dht11

2. 引脚配置

  • Luckfox Pico / Plus / Pro / Max 系列主要参考了 Raspberry Pi Pico 的引脚布局,通过引脚配置可以兼容部分 Raspberry Pi Pico 的外设。
    xxx

  • Luckfox Pico 不同型号支持的兼容设备列表参考Luckfox-Pico_support-List

  • 兼容设备选项本质上是多种引脚配置的组合,可以简化配置的步骤

  • Luckfox Pico 在 ubuntu 下由于没有 io 命令直接配置寄存器,配置兼容设备 Pico-LCD 时引脚无法配置为默认上拉,无法正常控制按键

  • 启动兼容设备配置时会覆盖原有配置,需要取消兼容设备到 Advanced Options 界面关闭启动的设备功能即可

3. 示例程序

3.1 dht11_drv.c

该代码是一个用于与 DHT11 传感器进行交互的 Linux 内核模块,它通过字符设备文件提供温度和湿度的读取接口。下面是对代码的解析:

数据结构定义

typedef struct DHT11_SENSOR_DATA
{
u16 temp; // Temperature
u16 hum; // Humidity
} dht11_data;
  • 功能:定义了一个结构体 DHT11_SENSOR_DATA,用于存储从DHT11传感器读取的温度和湿度数据。

DHT11_Read_DQ

static u8 DHT11_Read_DQ(void)
{
DHT11_IO_IN;
return gpio_get_value(dht11_gpio);
}
  • 功能:读取DHT11传感器的数据线状态。
  • 步骤:将数据线设置为输入模式(DHT11_IO_IN),然后使用 gpio_get_value 获取数据线的值。

DHT11_Rst

static void DHT11_Rst(void)
{
DHT11_DQ_Low;
delay_ms(20);
DHT11_DQ_High;
delay_us(30);
}
  • 功能:复位DHT11传感器,拉低数据线,等待一段时间后再拉高。
  • 步骤:将数据线拉低(DHT11_DQ_Low),延时20毫秒,然后将数据线拉高(DHT11_DQ_High)并延时30微秒。

DHT11_Check

static u8 DHT11_Check(void)
{
u8 retry = 0;
DHT11_IO_IN;
while ((DHT11_Read_DQ() == 1) && retry < 100)
{
retry++;
delay_us(1);
}
if (retry >= 100)
return 1;
else
retry = 0;
while ((DHT11_Read_DQ() == 0) && retry < 100)
{
retry++;
delay_us(1);
}
if (retry >= 100)
return 1;
return 0;
}
  • 功能:检查DHT11传感器是否存在,通过监控数据线状态。
  • 步骤:等待数据线从高电平变为低电平,再从低电平变为高电平。

DHT11_Read_Bit

static u8 DHT11_Read_Bit(void)
{
u8 retry = 0;
while ((DHT11_Read_DQ() == 1) && retry < 100)
{
retry++;
delay_us(1);
}
retry = 0;
while ((DHT11_Read_DQ() == 0) && retry < 100)
{
retry++;
delay_us(1);
}
delay_us(40);
if (DHT11_Read_DQ() == 1)
return 1;
else
return 0;
}
  • 功能:从DHT11传感器读取一个位。
  • 步骤:等待数据线从高电平变为低电平,再从低电平变为高电平,然后延时40微秒,最后读取数据线的状态。

DHT11_Read_Byte

static u8 DHT11_Read_Byte(void)
{
u8 i, dat;
dat = 0;
for (i = 0; i < 8; i++)
{
dat <<= 1;
dat |= DHT11_Read_Bit();
}
return dat;
}
  • 功能:从DHT11传感器读取一个字节(8位)。
  • 步骤:调用 DHT11_Read_Bit 函数8次,每次左移一位并与读取的位进行按位或操作。

DHT11_Read_Data

static u8 DHT11_Read_Data(u16 *temp, u16 *humi)
{
u8 buf[5];
u8 i;
DHT11_Rst();
if (DHT11_Check() == 0)
{
for (i = 0; i < 5; i++)
{
buf[i] = DHT11_Read_Byte();
}
if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
{
*humi = buf[0] << 8 | buf[1];
*temp = buf[2] << 8 | buf[3];
printk("buf=%d,%d,%d,%d,%d\n", buf[0], buf[1], buf[2], buf[3], buf[4]);
return 0;
}
else
return 1;
}
else
return 1;
}
  • 功能:从DHT11传感器读取温度和湿度数据。
  • 步骤:调用 DHT11_Rst 进行复位和初始化,然后通过调用 DHT11_Check 检查传感器是否存在。如果存在,继续通过调用 DHT11_Read_Byte 读取40位的数据,然后验证校验和。

DHT11_Init

static void DHT11_Init(void)
{
DHT11_DQ_High;
DHT11_Rst();
DHT11_Check();
}
  • 功能:初始化DHT11传感器的IO口,并检测传感器的存在。
  • 步骤:将数据线拉高,然后调用 DHT11_Rst 进行复位,最后调用 DHT11_Check 等待传感器的回应。

DHT11_open

int DHT11_open(struct inode *inode, struct file *flips)
{
printk("--------------%s--------------\n", __FUNCTION__);
return 0;
}
  • 功能:字符设备文件的打开操作。

DHT11_read

static ssize_t DHT11_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
dht11_data Last_dht11_data;
printk("--------------%s--------------\n", __FUNCTION__);

if (DHT11_Read_Data(&Last_dht11_data.temp, &Last_dht11_data.hum) == 0)
{
if (copy_to_user(buf, &Last_dht11_data, sizeof(Last_dht11_data)))
{
return -EFAULT;
}
}
return 0;
}
  • 功能:字符设备文件的读取操作,从DHT11传感器读取温湿度数据。
  • 步骤:调用 DHT11_Read_Data 函数读取数据,然后将数据拷贝到用户空间。

DHT11_close

static int DHT11_close(struct inode *inode, struct file *flip)
{
printk("--------------%s--------------\n", __FUNCTION__);
return 0;
}
  • 功能:字符设备文件的关闭操作。

dht11_probe

static int dht11_probe(struct platform_device *pdev)
{
...
}
  • 功能:处理平台设备的探测和初始化。
  • 步骤:包括获取GPIO信息,注册字符设备,创建设备类和设备节点,以及初始化DHT11传感器。

dht11_remove

static int dht11_remove(struct platform_device *pdev)
{
...
}
  • 功能:处理平台设备的卸载。
  • 步骤:包括销毁设备节点、设备类,注销字符设备。

dht11_shutdown

static void dht11_shutdown(struct platform_device *pdev)
{
printk("-------%s-------------\n", __FUNCTION__);
}
  • 功能:处理设备关机操作。
  • 步骤:打印一条调试信息。

3.2 dht11_test.c

该代码是调用设备文件读取温湿度的示例代码。下面是对代码的解析:

打开设备文件

fd = open("/dev/dht11", O_RDONLY);
if (fd == -1)
{
perror("open dht11 error\n");
exit(-1);
}

使用 open 函数以只读方式打开名为 "/dev/dht11" 的字符设备文件。如果打开失败,输出错误信息并退出程序。

循环读取传感器数据

while (1)
{
sleep(1);
retval = read(fd, &Curdht11_data, sizeof(Curdht11_data));
if (retval == -1)
{
perror("read dht11 error");
printf("read dht11 error");
exit(-1);
}
if (Curdht11_data.temp != 0xffff)
printf("Temperature:%d.%d C,Humidity:%d.%d %%RH\n", Curdht11_data.temp >> 8, Curdht11_data.temp & 0xff, \
Curdht11_data.hum >> 8, Curdht11_data.hum & 0xff);
}

每隔1秒读取一次传感器数据。如果读取失败,输出错误信息并退出程序。如果温度值不是0xffff,就打印温度和湿度的信息。

关闭设备文件

close(fd);

使用 close 函数关闭设备文件。

3.3 编译程序

  1. 修改Makefile

    将 Makefile 中 <SDK Directory>修改为自己的 SDK 路径,如 /home/luckfox/luckfox-pico/

    ARCH=arm

    CROSS_COMPILE=<SDK Directory\>/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-
    export ARCH CROSS_COMPILE

    KERN_DIR = <SDK Directory>/sysdrv/source/kernel
    name=dht11
    PWD?=$(shell pwd)

    all:
    make -C $(KERN_DIR) M=$(PWD) modules
    $(CROSS_COMPILE)gcc $(name)_test.c -o $(name)
    echo $(PWD)

    clean:
    rm -f *.ko *.o *.mod *.mod.o *.mod.c *.symvers *.order *.cmd
    # make -C $(KERN_DIR) M=$(PWD) modules clean
    # rm -rf modules.order
    # rm -f $(name)_test
    obj-m += $(name)_drv.o
  2. 编译

    执行 make 对两个文件进行编译,把产物中的 dht11_drv.kodht11 拷贝到开发板上。

4. 实现效果

4.1 导入模块

insmod dht11_drv.ko

效果如下:

# insmod dht11_drv.ko
[ 57.655150] -------dht11_probe-------------
[ 57.655337] dht11-gpio: 55 is valid!
[ 57.655365] gpio 55 request success!
[ 57.655381] dht11_major =239
[ 57.681960] dht11 Initing...

4.2 读取温湿度

chmod +x dht11
./dht11

效果如下:

# chmod +x dht11
# ./dht11
Press CTRL+C to exit.
[ 91.447436] --------------DHT11_open--------------
open /dev/dht11 successfully
[ 93.447934] --------------DHT11_read--------------
[ 93.475741] buf=37,0,25,7,69
Temperature:25.7 C, Humidity:37.0 %RH
[ 94.476565] --------------DHT11_read--------------
Temperature:25.7 C, Humidity:37.0 %RH
[ 95.502423] --------------DHT11_read--------------
[ 95.532409] buf=37,0,25,7,69
Temperature:25.7 C, Humidity:37.0 %RH
[ 96.533221] --------------DHT11_read--------------
Temperature:25.7 C, Humidity:37.0 %RH
[ 97.559087] --------------DHT11_read--------------
[ 97.589061] buf=37,0,25,9,71
Temperature:25.9 C, Humidity:37.0 %RH
[ 98.589883] --------------DHT11_read--------------
Temperature:25.9 C, Humidity:37.0 %RH