Openwrt开发指南 第28章 DHT11 温湿度传感器

时间:2025-07-26  作者:Diven  阅读:0

开发环境:

Openwrt开发指南 第28章 DHT11 温湿度传感器

主机:Ubuntu12.04

开发板:RT5350

Openwrt:Openwrt15.05

1 硬件原理

下图是我们温度传感器的接入引脚,3.3V 供电,io 口接 P13 的 GP0( GPIO0 的简称 )。DHT11数字温湿度传感器 是一款含有已校准数字信号输出的温湿度复合传感器,应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和很好的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能 8 位单片机相连接。因此该产品具有品质很好、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11 传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测型号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。

2 DHT11 相关时序

  • 初始化(复位)时序图

1.png

  1. 控制器首先至少拉低 18ms,然后拉高 20-40us 后等待 DHT11 的应答
  2. 当 DHT11 检测到信号后,首先将总线拉低约 80us 然后在拉高 80us 作为应答信号。
  • 读取数据时序图

2.png

  • 表示 0 的时序如下

3.png

  • 表示 1 的时序如下

4.png

  1. DHT11 以低电平应答主机,然后拉高总线准备输出。输出 0 信号和 1 信号都是以低电平开始高电平结束。
  2. DHT11 输出 0、 1 信号的低电平时间相同,而高电平的时间不同,输出 0 信号时高电平约 26-28us,而当输出 1 信号时高电平约为 70us。

3 驱动程序

关于字符设备驱动程序的使用,我们可以参照点亮 led 灯的那个实验,这里只给出跟DHT11 密切相关的驱动程序,详细的程序请查看我们的驱动文件!

//配置连接温度传感器的引脚#define DHT11_L *GPIO21_0_DATA &= ~(1< < 0) //低电平#define DHT11_H *GPIO21_0_DATA |= (1< < 0) //高电平#define DHT11_OUT *GPIO21_0_DIR |= (1< < 0) //输出#define DHT11_IN*GPIO21_0_DIR &= ~(1< < 0) //输入#define DHT11_STA*GPIO21_0_DATA & 0x01//寄存器定义volatile unsigned long *GPIO21_0_DIR;volatile unsigned long *GPIO21_0_DATA;//初始化函数必要资源定义//用于初始化函数当中//devICe number;dev_t dev_num;//struct devstruct cdev dht11_cdev;//auto "mknode /dev/dht11 c dev_num minor_num"struct class *dht11_class = NULL;struct devICe *dht11_device = NULL;//从dht11中读取一个字节static unsigned char read_byte(void){unsigned char r_val = 0; unsigned char t_count = 0; //计时器,防止超时; unsigned char i;for(i = 0 ; i < 8 ; i++){t_count = 0;while(!DHT11_STA){udelay(1);t_count++;if(t_count >250){printk("read_byte error1n");return 100;}}t_count = 0;udelay(32);if(DHT11_STA == 1){r_val < <= 1;r_val |= 1;}else{r_val < <= 1;continue;}while( DHT11_STA == 1 ){udelay(2);t_count++;if(t_count >250){printk("read_byte error2n");return 100;} }}return r_val;}//从dht11中读出数据static unsigned int read_dht11(void){ unsigned char t_count = 0; //计时器; unsigned int dht11 = 0; unsigned char h_i = 0 , h_f = 0; unsigned char t_i = 0 , t_f = 0; unsigned char check_sum = 0; DHT11_OUT; DHT11_L; mdelay(30); // >18ms; DHT11_H; udelay(30); DHT11_IN; while(DHT11_STA == 1) { udelay(1);t_count++;if(t_count > 50){ printk("device error: dht11!n");return 0;} } t_count = 0; while(!DHT11_STA) {udelay(1);t_count++;if(t_count > 250){printk("read_dht11 error1n");return 0;} } t_count = 0; udelay(50); while(DHT11_STA) {udelay(1);t_count++;if(t_count > 250){printk("read_dht11 error2n");return 0;} } h_i = read_byte(); h_f = read_byte(); t_i = read_byte(); t_f = read_byte(); check_sum = read_byte(); if(check_sum == (h_i+h_f+t_i+t_f) || (h_i!=100 && t_i != 100)) {dht11 = t_i;dht11 < <= 8;dht11 += h_i; } else {dht11 = 0;printk("read_dht11 error3n"); } return dht11;}//openstatic int dht11_open(struct inode *inode, struct file *file){printk("dht11 drive open...n");DHT11_OUT;DHT11_H;return 0;}//closestatic int dht11_close(struct inode *inode , struct file *file){return 0;}//readstatic ssize_t dht11_read(struct file *file, char __user *buffer,size_t len, loff_t *pos){unsigned int dht11; printk("dht11 drive read...n");dht11 = read_dht11();copy_to_user(buffer, &dht11, 4);return 4;}//structstatic const struct file_operations dht11_fops = {.owner = THIS_Module,.open = dht11_open,.release = dht11_close,.read = dht11_read,};//条件值变量,用于指示资源是否正常使用unsigned char init_flag = 0;unsigned char add_code_flag = 0;//initstatic __init int dht11_init(void){int ret_v = 0;printk("dht11 drive init...n");//函数alloc_chrdev_region主要参数说明://参数2: 次设备号//参数3: 创建多少个设备if( ( ret_v = alloc_chrdev_region(&dev_num,0,1,"dht11") ) < 0 ){goto dev_reg_error;}init_flag = 1; //标示设备创建成功;printk("The drive info of dht11:nmajor: %dnminor: %dn",MAJOR(dev_num),MINOR(dev_num));cdev_init(&dht11_cdev,&dht11_fops);if( (ret_v = cdev_add(&dht11_cdev,dev_num,1)) != 0 ){goto cdev_add_error;}dht11_class = class_create(THIS_Module,"dht11");if( IS_ERR(dht11_class) ){goto class_c_error;}dht11_device = device_create(dht11_class,NULL,dev_num,NULL,"dht11");if( IS_ERR(dht11_device) ){goto device_c_error;}printk("auto mknod success!n");//------------ 请在此添加您的初始化程序 --------------// GPIO21_0_DATA = (volatile unsigned long *)ioremap(0x10000620, 4);GPIO21_0_DIR = (volatile unsigned long *)ioremap(0x10000624, 4); //如果需要做错误处理,请:goto dht11_error; add_code_flag = 1;//---------------------- END ---------------------------// goto init_success;dev_reg_error:printk("alloc_chrdev_region failedn");return ret_v;cdev_add_error:printk("cdev_add failedn"); unregister_chrdev_region(dev_num, 1);init_flag = 0;return ret_v;class_c_error:printk("class_create failedn");cdev_del(&dht11_cdev); unregister_chrdev_region(dev_num, 1);init_flag = 0;return PTR_ERR(dht11_class);device_c_error:printk("device_create failedn");cdev_del(&dht11_cdev); unregister_chrdev_region(dev_num, 1);class_destroy(dht11_class);init_flag = 0;return PTR_ERR(dht11_device);//------------------ 请在此添加您的错误处理内容 ----------------//dht11_error:add_code_flag = 0;return -1;//-------------------- END -------------------// init_success:printk("dht11 init success!n");return 0;}//exitstatic __exit void dht11_exit(void){printk("dht11 drive exit...n");if(add_code_flag == 1) { //---------- 请在这里释放您的程序占有的资源 ---------// printk("free your resources...n"); iounmap(GPIO21_0_DATA);iounmap(GPIO21_0_DIR); printk("free finishn"); //---------------------- END -------------------//} if(init_flag == 1){//释放初始化使用到的资源;cdev_del(&dht11_cdev); unregister_chrdev_region(dev_num, 1);device_unregister(dht11_device);class_destroy(dht11_class);}}//module loadingmodule_init(dht11_init);module_exit(dht11_exit);//some infomationMODULE_LICENSE("GPL v2");MODULE_AUTHOR("from Jafy");MODULE_DESCRIPTION("dht11 drive");

4 应用程序

int main(int argc, char **argv){int fd;unsigned int dht11 = 0;unsigned int humi,temp;//打开温度传感器驱动模块fd = open("/dev/dht11", O_RDWR | O_NONBLOCK);if (fd < 0){printf("can't open /dev/dht11n");return -1;}read(fd, &dht11, sizeof(dht11));temp = dht11 >>8;humi = dht11 &0x000000ff;printf("the current temperature is: %dn",temp);printf("the current humidity is: %dn",humi);close(fd);return 0;}

5 实验结果

5.png
审核编辑:汤梓红

猜您喜欢

随着科技的不断进步,各种电子设备之间的连接方式不断更新换代。其中,USB接口作为通用的连接标准,应用于各种设备中。本文将重点介绍USB5-MICROB_7.4X...
2025-04-22 04:31:12

贴片电阻,电子产品中 ubiquitous 的小元件,其阻值往往并非直接印在表面,而是用字母数字组合表示。别担心,读懂这些「神秘代码」其实很简单!对于三位数的标...
2025-04-14 15:03:39

您是否还在为贴片电阻上那些复杂的数字编码而烦恼?还在费力查阅表格进行阻值换算?现在,有了贴片电阻换算软件,这些问题都将迎刃而解!这款软件操作简便,输入三位数或四...
2025-04-14 15:02:21

PVC管件在市场上种类繁多,主要根据使用场景和连接方式的不同而有所区别。从形状上看,PVC管件可以分为弯头、三通、法兰、接头等多种类型。弯头用于改变管道方向,三...
2010-12-07 00:00:00

在选择电流传感器或磁传感器时,规格尺寸是一个关键因素。不同类型的传感器在应用领域和安装方式上存在差异,因此了解尺寸规格非常重要。电流传感器通常有多种尺寸可供选择...
2010-02-10 00:00:00

刀具在我们的日常生活中是重要配件,除了常见的厨刀,其刀类也各具特色。军刀是用于军事用途的刀具,通常具有较强的攻击性和防御性,设计上注重实用与威慑。户外刀是专为露...
2015-11-18 00:00:00

截止阀是常见的管道阀门,主要用于控制流体的流动。根据不同的标准,截止阀可以分为多种类型。按结构形式分类,截止阀可分为直流式和角度式。直流式截止阀的流体流动方向与...
2010-02-21 00:00:00

大功率贴片电阻,顾名思义,就是在尺寸小巧的贴片电阻封装内,实现了更高的功率承受能力。这使得它们成为电子设备小型化和高功率密度设计中的关键元件。 相较于传统插件电...
2025-04-14 15:02:05

1812封装的贴片电阻,指的是长宽分别为1.8mm和1.2mm的矩形表面贴装电阻。它的小巧尺寸使其成为电子产品小型化和轻量化趋势下的理想选择,广泛应用于各种电子...
2025-04-14 15:02:42

采样电阻作为电流检测和电路保护的重要组成部分,是关键配件。随着市场上采样电阻品牌的增多,选择一个可靠且性能优越的品牌变得尤为重要。LIZ(丽智)作为近年来崭露头...
2014-01-05 12:27:15