当前位置: 首页 > news >正文

DHT11-温湿度传感器

1、驱动模板

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include<mach/gpio-nrs.h>
#include<mach/gpio.h>
#include<linux/miscdevice.h>
#include<asm/ioctl.h>
#include<linux/interrupt.h>
#include<linux/irqreturn.h>
#include<linux/wait.h>
#include<linux/sched.h>
#include<linux/delay.h>#define DEV_NAME "dht11"
#define PIN_DHT11 S3C2410_GPF(6)static int open (struct inode * inode, struct file * file)
{printk("dht11 open ...\n");return 0;
}static ssize_t read (struct file * file, char __user * buf, size_t len, loff_t * offset)
{printk("dht11 read ...\n");return 0;
}static ssize_t write (struct file * file, const char __user * buf, size_t len, loff_t * offset)
{return 0;
}static int close(struct inode *node,struct file *file)
{printk("dht11 close\n");return 0;
}static struct file_operations fops = 
{.owner=THIS_MODULE,.open=open,.read=read,.write=write,
//	.unlocked_ioctl=ioctl,.release=close
};static struct miscdevice misc=
{.minor=MISC_DYNAMIC_MINOR,.name=DEV_NAME,.fops=&fops
};static int __init dht11_init(void)
{int ret=0;ret=misc_register(&misc);if(ret<0)goto err_misc_register;printk("dht11_init...\n");return ret;err_misc_register:misc_deregister(&misc);printk("misc_register  faidht11\n");return ret;
}static  void __exit dht11_exit(void)
{misc_deregister(&misc);printk("dht11_exit ...\n");
}module_init(dht11_init);
module_exit(dht11_exit);
MODULE_LICENSE("GPL");

2、基本概念

操作时序图

DHT11 采用单总线协议与单片机通信,单片机发送一次复位信号后,DHT11 从低功耗模式转换到高速模式,等待主机复位结束后,DHT11 发送响应信号,并拉高总线准备传输数据。一次完整的数据为 40bit,按照高位在前,低位在后的顺序传输。

数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数数据+8bit 校验和,一共 5 字节(40bit)数据。由于 DHT11 分辨率只能精确到个位,所以小数部分是数据全为 0。校验和为前 4 个字节数据相加,校验的目的是为了保证数据传输的准确性。

DHT11 只有在接收到开始信号后才触发一次温湿度采集,如果没有接收到主机发送复位信号,DHT11 不主动进行温湿度采集。当数据采集完毕且无开始信号后,DHT11 自动切换到低速模式。

初始化:主机开始发信号,至少拉低18ms低电平,然后拉高20~40us,等待响应

代码:

static void dht11_start(void)
{gpio_request(PIN_DHT11,"pin_dht11");gpio_direction_output(PIN_DHT11,DHT11_ON);msleep(40);gpio_set_value(PIN_DHT11,DHT11_OFF);mdelay(20);gpio_set_value(PIN_DHT11,DHT11_ON);udelay(30);gpio_direction_input(PIN_DHT11);
}

响应:首先应等待复位的高电平结束(如果没结束),等待80us的低电平结束从机,等待80us的高电平结束

代码:

static int dht11_response(void)
{int time =100;
//time=100,引脚为高电平1,一直等待,等待time为0时,就超时,如果在100以内,引脚为低电平,就不会超时
//等待引脚为低电平时,循环退出了,就往下走,且没有超时,就进入第二个循环while((time>0) && gpio_get_value(PIN_DHT11)){udelay(1);time--;}if(time<=0){printk("error\n");return -1;}
//此时电平为低电平,time=100,当time减为0时,就超时,但在100以内,变为高电平就不会超时time=100;while((time>0) && (!gpio_get_value(PIN_DHT11))){udelay(1);time--;}if(time<=0){printk("error2\n");return -1;}time=100;while((time>0) && gpio_get_value(PIN_DHT11)){udelay(1);time--;}if(time<=0){printk("error3\n");return -1;}return 0;
}

读数据:首先等待50us的低电平结束,然后等待35秒,如果电平是低,就代表是0,然后等待高电平结束,代表是1

static int get_bit(void)
{
//等待50us低电平结束int time = 100;while((time > 0) && (!gpio_get_value(PIN_DHT11))){udelay(1);time--;}if(time <= 0){printk("get_bit   1\n");return -1;}//等待35usudelay(35);//如果引脚电平是0,那么数据就是0if(0 == gpio_get_value(PIN_DHT11))return 0;
//再继续等待,直到低电平结束,数据是1time = 100;while((time > 0) && gpio_get_value(PIN_DHT11)){udelay(1);time--;}if(time <= 0){printk("get_bit   2\n");return -1;}return 1;
}

得到5个字节的数据:一个字节8个bit,所以循环8次,每次都左移一位

static int get_data(unsigned char *data)
{int i=0;int j=0;for(j=0;j<5;j++){data[j] = 0;for(i=0;i<8;i++){char tmp=0;data[j]<<=1;tmp=get_bit();if(tmp<0)return -1;data[j]|=tmp;}}return 0;
}

完整代码:


#if 1
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include<mach/gpio-nrs.h>
#include<mach/gpio.h>
#include<linux/miscdevice.h>
#include<asm/ioctl.h>
#include<linux/interrupt.h>
#include<linux/irqreturn.h>
#include<linux/wait.h>
#include<linux/sched.h>
#include<linux/delay.h>
#include <linux/workqueue.h>#define DEV_NAME "dht11"
#define PIN_DHT11 S3C2410_GPF(6)
#define DHT11_ON  1
#define DHT11_OFF 0static void dht11_start(void)
{gpio_request(PIN_DHT11,"pin_dht11");gpio_direction_output(PIN_DHT11,DHT11_ON);msleep(40);gpio_set_value(PIN_DHT11,DHT11_OFF);mdelay(20);gpio_set_value(PIN_DHT11,DHT11_ON);udelay(30);gpio_direction_input(PIN_DHT11);
}static int dht11_response(void)
{int time =100;while((time>0) && gpio_get_value(PIN_DHT11)){udelay(1);time--;}if(time<=0){printk("error\n");return -1;}time=100;while((time>0) && (!gpio_get_value(PIN_DHT11))){udelay(1);time--;}if(time<=0){printk("error2\n");return -1;}time=100;while((time>0) && gpio_get_value(PIN_DHT11)){udelay(1);time--;}if(time<=0){printk("error3\n");return -1;}return 0;
}static int get_bit(void)
{int time = 100;while((time > 0) && (!gpio_get_value(PIN_DHT11))){udelay(1);time--;}if(time <= 0){printk("get_bit   1\n");return -1;}udelay(35);if(0 == gpio_get_value(PIN_DHT11))return 0;time = 100;while((time > 0) && gpio_get_value(PIN_DHT11)){udelay(1);time--;}if(time <= 0){printk("get_bit   2\n");return -1;}return 1;
}static int get_data(unsigned char *data)
{int i=0;int j=0;for(j=0;j<5;j++){data[j] = 0;for(i=0;i<8;i++){char tmp=0;data[j]<<=1;tmp=get_bit();if(tmp<0)return -1;data[j]|=tmp;}}return 0;
}static int open (struct inode * inode, struct file * file)
{printk("dht11 open ...\n");return 0;
}static ssize_t read (struct file * file, char __user * buf, size_t len, loff_t * offset)
{int ret=0;unsigned char data[5]={0};dht11_start();ret=dht11_response();if(ret<0)return -1;ret=get_data(data);if(ret<0)return -1;copy_to_user(buf,data,sizeof(data));printk("dht11 read ...\n");return sizeof(data);
}static ssize_t write (struct file * file, const char __user * buf, size_t len, loff_t * offset)
{return 0;
}static int close(struct inode *node,struct file *file)
{printk("dht11 close\n");return 0;
}//static dev_t dev_num;
static struct file_operations fops = 
{.owner=THIS_MODULE,.open=open,.read=read,.write=write,
//	.unlocked_ioctl=ioctl,.release=close
};static struct miscdevice misc=
{.minor=MISC_DYNAMIC_MINOR,.name=DEV_NAME,.fops=&fops
};static int __init dht11_init(void)
{int ret=0;ret=misc_register(&misc);if(ret<0)goto err_misc_register;printk("dht11_init...\n");return ret;err_misc_register:misc_deregister(&misc);printk("misc_register  faidht11\n");return ret;
}static  void __exit dht11_exit(void)
{misc_deregister(&misc);printk("dht11_exit ...\n");
}module_init(dht11_init);
module_exit(dht11_exit);
MODULE_LICENSE("GPL");

http://www.dtcms.com/a/361964.html

相关文章:

  • 基于单片机智能饮水机/智能热水壶
  • Redis 如何实现分布式锁,以及redis的适应场景分析
  • 【跨平台编译】【树莓派】在x86上编译树莓派上运行的CC++代码,搭建树莓派4B的跨平台编译环境
  • ccache编译加速配置
  • Meteor主题友链页面自研
  • Qt 的信号signal的参数是否会在内部被拷贝?
  • Vue3 中 Proxy 在组件封装中的妙用
  • 【网络安全入门基础教程】网络安全零基础学习方向及需要掌握的技能
  • Electron 应用生命周期管理:app 模块核心 API
  • 【 HarmonyOS 】错误描述:The certificate has expired! 鸿蒙证书过期如何解决?
  • 光学神经网络与人工智能应用
  • 网络流量分析——熟悉Wireshark
  • 【洛谷】【模板】栈、有效的括号、验证栈序列、后缀表达式、(stack相关算法题)
  • 腾讯位置商业授权微信小程序获取城市列表
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(二十三)控件中常用文本格式
  • 玩转OurBMC第二十一期:前端页面仪表盘的设计与使用实践
  • js 海康视频插件的具体步骤
  • QMainWindow使用QTabWidget添加多个QWidget
  • Simulink库文件-一种低通滤波模块搭建方法
  • 优化正则表达式性能:预编译与模式匹配的最佳实践
  • 均值滤波和中值滤波的简介、C语言实现和实测
  • 边缘计算设备 RK3576芯片
  • CGroup 资源控制组 + Docker 网络模式
  • NLP大语言模型数据准备
  • NLP技术突破:浅层与深层语义分析全解析
  • 嵌入式学习(day37) 数据库 Sqlite相关命令函数
  • Salesloft OAuth漏洞影响范围大幅增加,波及所有集成应用
  • 可编辑115页PPT | 某纸制品制造企业数字化转型战略规划项目建议书
  • 闭包的简单讲解
  • 三、数据结构