DHT11 实现温湿度传感器

news2024/9/23 7:32:05

DHT11
DHT11是一款含有已校准数字信号输出的温湿度复合传感器,它结合了电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。通过采用专用的数字模块采集技术和温湿度传感技术,DHT11确保了产品的高可靠性和长期稳定性 

DHT11时序部分主要为   DHT11启动时序,读取数字0和读取数字1

1 . DHT11启动时序 

主机首先将电平拉低,至少持续18us [ mdelay(20) ],随后再拉高;

static void dht11_start(void)
{
	gpio_direction_output(PIN_DHT11, 0);
	mdelay(20);
	gpio_set_value(PIN_DHT11, 1);
	udelay(30);
	gpio_direction_input(PIN_DHT11); 
//将引脚设置为输入模式开始读取数据
}

② 


随后读取HDT发送的响应,先是80us的低电平随后拉高至80us;
表明DHT11已经正确响应启动信号,即将开始传输数据

static int dht11_wait_repon(void)
{
	int time = 100;
	while(gpio_get_value(PIN_DHT11))   // wait H end
	{
		udelay(1);
		if(!time--)
			return -1;
	}

	time = 100;
	while(!gpio_get_value(PIN_DHT11) && time)  // wait 80us L end
	{
		udelay(1);
		if(!time--)
			return -2;
	}

	time = 100;
	while(gpio_get_value(PIN_DHT11))   // wait 80us H end
	{
		udelay(1);
		if(!time--)
			return -3;
	}

	return 0;
}

2 . 读取0/1


当在启动时序的最后拉高80us后,如果遇到拉低50us和拉高26-28us则表示读取到 ‘ 0 ’;

 当在启动时序最后 ,如果遇到了拉低50us和拉高70us则表示读取到 ‘ 1 ’ ; 

所以可以根据高电平拉高时间来判断读取的是 ‘ 0 ’ 或者 ‘ 1 ’;

 ②
判断数据是都传输正确 
数据接收完毕后,根据ret的值进行检验,如果hum_h、hum_l、temp_h、temp_l 相加的值的后8位和校验位不相等,那么此次数据作废。 

static int dht11_get_value(unsigned char * data)
{
	int i = 0;
	int j = 0;
	unsigned char sum = 0;
	for(i = 0; i < 5; i++)
	{
		data[i] = 0;
		for(j = 0; j < 8; j++)
		{
			char bit = dht11_get_bit();	
			if(bit < 0)
				return bit;
			data[i] <<= 1;
			data[i] |= bit;
		}
	}

	for(i = 0; i < 4; i++)
	{
		sum += data[i];
	}

	if(sum == data[4])
		return 4;
	else
		return -1;
}

 

=== 数据格式:

DHT11采用单总线双向串行通信协议,每次采集信号时,都需要单片机向DHT11发送开始信号。DHT11在接收到开始信号后,即发送40bit的数据给单片机。高位在前,数据格式为:

        湿度高8位+湿度低8位+温度高8位+温度低8位+8bit校验位

        其中8bit校验位的值应与前4个8位数据相加后的数的低8位相同,如果不同则放弃本次数据

 


实践流程:

①编写dht11.c

②make Makefile 与 make Kconfig

③make modules 生成 dht11,ko

④cp drivers/char/dht11.ko  /home/linux/nfs/rootfs

⑤编写dht11_app.c 在 /home/linux/nfs/rootfs下

⑥arm-linux-gcc  dht11_app.c  -o  dht_app 

⑦sudo minicom

⑧insmod  dht11.ko

⑨./dht11_app 



完整代码

dht11.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <asm/io.h>
#include <asm/string.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <asm-generic/errno-base.h>
#include <mach/gpio-nrs.h>
#include <mach/gpio.h>
#include <linux/delay.h>

#define DEV_NAME "dht11"
#define PIN_DHT11 S3C2410_GPF(6)

static void pin_init(void)
{
	gpio_request(PIN_DHT11, "dht11");
}

static void dht11_start(void)
{
	gpio_direction_output(PIN_DHT11, 0);
	mdelay(20);
	gpio_set_value(PIN_DHT11, 1);
	udelay(30);
	gpio_direction_input(PIN_DHT11);
}

static int dht11_wait_repon(void)
{
	int time = 100;
	while(gpio_get_value(PIN_DHT11))   // wait H end
	{
		udelay(1);
		if(!time--)
			return -1;
	}

	time = 100;
	while(!gpio_get_value(PIN_DHT11) && time)  // wait 80us L end
	{
		udelay(1);
		if(!time--)
			return -2;
	}

	time = 100;
	while(gpio_get_value(PIN_DHT11))   // wait 80us H end
	{
		udelay(1);
		if(!time--)
			return -3;
	}

	return 0;
}

static int dht11_get_bit(void)
{
	int time = 100;
	while(!gpio_get_value(PIN_DHT11))  // wait 50us L end
	{
		udelay(1);	
		if(!time--)
			return -1;
	}

	udelay(30);

	if(0 == gpio_get_value(PIN_DHT11))
		return 0;

	while(gpio_get_value(PIN_DHT11))   // wait 40us H end
	{
		udelay(1);	
		if(!time--)
			return -2;
	}

	return 1;
}

static int dht11_get_value(unsigned char * data)
{
	int i = 0;
	int j = 0;
	unsigned char sum = 0;
	for(i = 0; i < 5; i++)
	{
		data[i] = 0;
		for(j = 0; j < 8; j++)
		{
			char bit = dht11_get_bit();	
			if(bit < 0)
				return bit;
			data[i] <<= 1;
			data[i] |= bit;
		}
	}

	for(i = 0; i < 4; i++)
	{
		sum += data[i];
	}

	if(sum == data[4])
		return 4;
	else
		return -1;
}

static int open (struct inode * inode, struct file * file)
{
	pin_init();
	printk("dht11 open ...\n");
	return 0;
}

static ssize_t read (struct file * file, char __user * buf, size_t len, loff_t * offset)
{
	unsigned char data[4] = {0};
	int ret = 0;
	dht11_start();
	ret = dht11_wait_repon();
	if(ret < 0)
		goto err_wait;

	ret = dht11_get_value(data);
	if(ret < 0)
		goto err;

	copy_to_user(buf, data, sizeof(data));

	printk("dht11 read ...\n");
	return sizeof(data);

err_wait:
	printk("dht11_wait_repon err ... \n");
	return ret;

err:
	printk("dht11_get_value err ...\n");
	return ret;
}

static ssize_t write (struct file * file, const char __user * buf, size_t len, loff_t * offset)
{
	return 0;
}

static int close (struct inode * inode, struct file * file)
{
	printk("dht11 close ...\n");
	return 0;
}

static struct file_operations fops = 
{
	.owner = THIS_MODULE,
	.open = open,
	.read = read,
	.write = write,
	.release = close
};

static struct miscdevice misc = 
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEV_NAME,
	.fops = &fops
};

static int __init dht11_init(void)
{
	int ret = misc_register(&misc);
	if(ret < 0)
		goto err_misc_register;

	printk("dht11_init  ...\n");
	return ret;

err_misc_register:
	misc_deregister(&misc);
	printk("dht11 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");

hdt11_app.c 

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <asm/io.h>
#include <asm/string.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <asm-generic/errno-base.h>
#include <mach/gpio-nrs.h>
#include <mach/gpio.h>
#include <linux/delay.h>

#define DEV_NAME "dht11"
#define PIN_DHT11 S3C2410_GPF(6)

static void pin_init(void)
{
	gpio_request(PIN_DHT11, "dht11");
}

static void dht11_start(void)
{
	gpio_direction_output(PIN_DHT11, 0);
	mdelay(20);
	gpio_set_value(PIN_DHT11, 1);
	udelay(30);
	gpio_direction_input(PIN_DHT11);
}

static int dht11_wait_repon(void)
{
	int time = 100;
	while(gpio_get_value(PIN_DHT11))   // wait H end
	{
		udelay(1);
		if(!time--)
			return -1;
	}

	time = 100;
	while(!gpio_get_value(PIN_DHT11) && time)  // wait 80us L end
	{
		udelay(1);
		if(!time--)
			return -2;
	}

	time = 100;
	while(gpio_get_value(PIN_DHT11))   // wait 80us H end
	{
		udelay(1);
		if(!time--)
			return -3;
	}

	return 0;
}

static int dht11_get_bit(void)
{
	int time = 100;
	while(!gpio_get_value(PIN_DHT11))  // wait 50us L end
	{
		udelay(1);	
		if(!time--)
			return -1;
	}

	udelay(30);

	if(0 == gpio_get_value(PIN_DHT11))
		return 0;

	while(gpio_get_value(PIN_DHT11))   // wait 40us H end
	{
		udelay(1);	
		if(!time--)
			return -2;
	}

	return 1;
}

static int dht11_get_value(unsigned char * data)
{
	int i = 0;
	int j = 0;
	unsigned char sum = 0;
	for(i = 0; i < 5; i++)
	{
		data[i] = 0;
		for(j = 0; j < 8; j++)
		{
			char bit = dht11_get_bit();	
			if(bit < 0)
				return bit;
			data[i] <<= 1;
			data[i] |= bit;
		}
	}

	for(i = 0; i < 4; i++)
	{
		sum += data[i];
	}

	if(sum == data[4])
		return 4;
	else
		return -1;
}

static int open (struct inode * inode, struct file * file)
{
	pin_init();
	printk("dht11 open ...\n");
	return 0;
}

static ssize_t read (struct file * file, char __user * buf, size_t len, loff_t * offset)
{
	unsigned char data[4] = {0};
	int ret = 0;
	dht11_start();
	ret = dht11_wait_repon();
	if(ret < 0)
		goto err_wait;

	ret = dht11_get_value(data);
	if(ret < 0)
		goto err;

	copy_to_user(buf, data, sizeof(data));

	printk("dht11 read ...\n");
	return sizeof(data);

err_wait:
	printk("dht11_wait_repon err ... \n");
	return ret;

err:
	printk("dht11_get_value err ...\n");
	return ret;
}

static ssize_t write (struct file * file, const char __user * buf, size_t len, loff_t * offset)
{
	return 0;
}

static int close (struct inode * inode, struct file * file)
{
	printk("dht11 close ...\n");
	return 0;
}

static struct file_operations fops = 
{
	.owner = THIS_MODULE,
	.open = open,
	.read = read,
	.write = write,
	.release = close
};

static struct miscdevice misc = 
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEV_NAME,
	.fops = &fops
};

static int __init dht11_init(void)
{
	int ret = misc_register(&misc);
	if(ret < 0)
		goto err_misc_register;

	printk("dht11_init  ...\n");
	return ret;

err_misc_register:
	misc_deregister(&misc);
	printk("dht11 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.coloradmin.cn/o/2084808.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

android studio 新建java工程, 安卓新建项目,android studio2024 如何新建java项目

主要解决&#xff0c;新增安卓工程&#xff0c;没有java选项 1. 点击左上角FIle -> New -> 2. 选择 no activity 选项&#xff0c; 然后next 3. langua 就可以选择java 了。name自己定义项目名称&#xff0c;项目存储地址&#xff0c;包名。 配置完成选择finish. 4. fin…

【C++】vector(下)--上篇

个人主页~ vector&#xff08;上&#xff09;~ vector 二、vector的模拟实现1、了解组成2、vector.h&#xff08;1&#xff09;为什么有了size_t参数的vector构造函数还要再写一个int参数的重载vector构造函数&#xff08;2&#xff09;为什么reserve不用memcpy&#xff08;3&…

Mysql剖析(三)----MySql的事务详解

事务&#xff08;Transaction&#xff09;&#xff1a;一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中的各种数据项的一个程序执行单元&#xff08;unit&#xff09;。事务通常由高级数据库操纵语言或编程语言(如SQL、C或Java)书写的用户程序的执行所引…

Python脚本实现向飞书发送卡片消息

目录 1 先创建一个卡片消息2 Python脚本2.1 告警测试2.2 告警恢复 总结 1 先创建一个卡片消息 飞书卡片搭建工具 根据自己的需要创建一个消息卡片&#xff1a; 可以在 卡片源代码 中看到这个卡片的代码信息 2 Python脚本 2.1 告警测试 test.py 文件 ""&quo…

MacOS安装Docker Desktop

目录 安装Docker Desktop 1.下载 2.安装 3.验证 安装Docker Desktop 1.下载 访问Docker官方网站下载页面&#xff1a;https://www.docker.com/products/docker-desktop 选择自己所需的版本下载即可 2.安装 3.验证 1.查询版本号 docker --version 2.也可以运行一个简单的…

【vue、Electron】搭建一个Electron vue项目过程、将前端页面打包成exe 桌面应用

文章目录 前言使用 electron-vue 创建项目1. 安装 vue-cli&#xff08;如果未安装&#xff09;2. 使用 electron-vue 模板创建项目3. 安装和配置 electron-builder4. 运行Electron项目5. 打包应用 可能遇到的问题解决Electron vue首次启动巨慢无法加载执行npm run electron:bui…

从地图信息实时检测路口的各向通行状况、红绿灯及溢出情况

高德地图、百度地图都能获得实时的道路信息。 C# 编写的路况信息爬虫可获得准实时&#xff08;1分钟间隔&#xff09;的路口的各向通行状况、红绿灯及溢出情况。 优势&#xff1a; 投入少&#xff0c;效果好&#xff0c;无需安装设备&#xff1b; 缺陷&#xff1a; 时间间隔…

数据集不够用?3DGS助力生成带标注的全新扩展数据!

作者主页&#xff1a;https://louiszengcn.github.io/ 论文标题&#xff1a; Realistic Surgical Image Dataset Generation Based On 3D Gaussian Splatting 导读&#xff1a; 近年来&#xff0c;随着AI技术的飞速发展&#xff0c;数据量的增加为数据驱动的神经网络提供了更强…

汽车免拆诊断案例 | 2012 款大众速腾车发动机偶尔抖动

故障现象 一辆2012款大众速腾车&#xff0c;搭载CST发动机和干式双离合变速器&#xff0c;累计行驶里程约为17万km。车主反映&#xff0c;发动机偶尔抖动。 故障诊断 接车后试车&#xff0c;确认发动机怠速偶尔抖动&#xff0c;且在D挡起步时抖动明显。用故障检测仪检测&…

专题◉万字长文!盘点过去一年最出圈的Prompt项目教程,有3份在悄悄更新

1. OpenAI 官方出品 | 提示工程最权威的教程 (最新版) 2023年6月&#xff0c;OpenAI 发布了一篇〖*GPT Best Practice (GPT 最佳实践)* 〗教程&#xff0c;详细介绍 ChatGPT Prompt 交互策略&技巧&#xff0c;并且给出了示例说明。 一年时间过去了&#xff0c;OpenAI 不…

Unity射击游戏开发教程:(33)控制飞机左右移动

在本文中,我将介绍如何在玩家朝该方向移动时添加向左和向右转动的动画。 我们已经将左转和右转动画导入到我们的项目中。在我使用的动画中,它们只有两帧,因为我们希望飞机倾斜得很快,这样玩家在按下相应按钮时就能直接感觉到转弯。 </

为什么帕金森病患者在紧张或焦虑状态下震颤会加重?

为什么帕金森病患者在紧张或焦虑状态下震颤会加重&#xff1f; 帕金森病患者在紧张或焦虑状态下震颤加重的原因可能与多个因素有关。首先&#xff0c;帕金森病与大脑中多巴胺水平的降低有关&#xff0c;这种神经递质的失衡会影响运动控制。当患者感到紧张时&#xff0c;大脑皮…

嵌入式软件开发之状态机与事件驱动分析

状态机是一种程序架构,事件驱动也是一种程序架构,在某些开发场景里面,两者是可以一同合并使用的。 事件驱动的概念 生活中有很多事件驱动的例子,上自习瞒着老师偷睡觉就是很生动的一个。 我们都是从高中时代走过来的,高中的学生苦啊,觉得睡觉是世界上最奢侈的东西, 有时…

运维监控工具 PIGOSS BSM :PostgreSQL数据库监控指标

在PostgreSQL数据库中&#xff0c;为了确保其稳定运行和性能优化&#xff0c;我们需要监控一系列关键的指标。以下是一些主要的PostgreSQL监控指标介绍&#xff1a; 连接数&#xff08;Connections&#xff09;&#xff1a; 定义&#xff1a;连接数是指当前正在与数据库建立连…

数据库管理-第236期 数据库一体机的价值(20240829)

数据库管理236期 2024-08-29 数据库管理-第236期 数据库一体机的价值&#xff08;20240829&#xff09;1 误区2 硬件3 操作系统4 数据库总结 数据库管理-第236期 数据库一体机的价值&#xff08;20240829&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&#xff…

深入探索【Hadoop】生态系统:Hive、Pig、HBase及更多关键组件(上)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《大数据前沿&#xff1a;技术与应用并进》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Hadoop简介 2、Hadoop生态系统的构成概览 3、…

native 添加堆栈

第一种方法 montecarloh53b getVehicleModel:default error: frameworks/native/services/surfaceflinger/Android.bp:248:1: module "surfaceflinger" variant "android_arm64_armv8-a": depends on //system/unwinding/libbacktrace:libbacktrace which …

YarnClient发送和接收请求源码解析

YarnClient发送和接收请求流程 Yarn是通过RPC协议通信的&#xff0c;协议类型可以通过查看RpcKind类得知&#xff0c;总共有三种类型&#xff1a; RPC_BUILTIN ((short) 1), // Used for built in calls by tests RPC_WRITABLE ((short) 2), // Use WritableRp…

CentOS 7安装和配置 NFS

前言 NFS 是 Network File System 的缩写&#xff0c;即网络文件系统。功能是让客户端通过网络访问不同主机上磁盘里的数据&#xff0c;主要用在类 Unix 系统上实现文件共享的一种方法。本例演示 CentOS 7 下安装和配置 NFS 的基本步骤。 环境说明 CentOS 7&#xff08;Mini…

Agent Q介绍:具有规划和自愈能力的下一代人工智能代理的研究突破

近年来&#xff0c;大型语言模型&#xff08;LLM&#xff09;的功能已经改变了自然语言处理和理解&#xff0c;取得了令人瞩目的里程碑式成就。尽管取得了这些进步&#xff0c;大型语言模型在交互环境中仍面临巨大挑战&#xff0c;尤其是在需要多步骤推理的任务中&#xff0c;如…