一、DHT11概述
1、简介
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。产品为4针单排引脚封装,连接方便。
2、 电气特性
3、接线
VCC接5V
GND接GND
DATA接P3^3
4、数据传输逻辑
只有一个数据线DATA ,单片机发送序列指令给DHT11模块,
模块一次完整的数据传输为40bit,高位先出。
5、数据格式:
8bit湿度整数数据 + 8bit 湿度小数数据
+ 8bit温度整数数据 + 8bit温度小数数据
+ 8bit 校验和
二、DHT11时序图分析
1、通讯过程时序图
2、检测DHT11温湿度传感器是否存在
根据下面的时序图,并检测模块是否存在,功能是否正常
主机发送开始信号->主机读取响应信号->开始接收数据->主机发送停止信号。
主机发送起始信号:
- 主机(MCU)首先将总线(数据线)拉低,并保持至少18ms的低电平时间。这个低电平信号是告诉DHT11传感器,主机准备开始通信。
- 随后,主机将总线拉高,并保持20~40μs的高电平时间。这个高电平信号的作用是告诉DHT11传感器,主机已经准备好接收数据。
DHT11响应信号:
- DHT11传感器在检测到起始信号后,会将总线拉低80μs左右,作为响应信号的开始。
- 然后,DHT11将总线拉高80μs左右,表示响应信号的结束,并准备开始发送数据。
3、数据发送
- DHT11传感器发送的数据总长度为40位(5字节),包括湿度整数部分(8位)、湿度小数部分(8位)、温度整数部分(8位)、温度小数部分(8位)和校验和(8位)。数据以高位先出的方式发送。
- 每一位数据的发送都遵循以下规则:
- 首先,DHT11将总线拉低50μs左右,表示数据位的开始。
- 然后,根据要发送的数据位是0还是1,DHT11将总线拉高的时间会有所不同:
- 如果发送的是0,则总线保持高电平的时间为26~28μs。
- 如果发送的是1,则总线保持高电平的时间为70μs。
三、根据时序图写出驱动S3c2440控制DHT11
构建了一个基本的Linux内核模块,用于通过GPIO接口与DHT11温湿度传感器进行通信。这个模块通过定义一系列的函数来实现对DHT11的初始化、发送启动信号、等待响应、读取数据位以及处理整个数据包的接收
#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");
dht11_start()
:发送启动信号给DHT11。首先拉低引脚20ms,然后拉高30μs,最后设置引脚为输入模式,等待DHT11的响应。dht11_wait_repon()
:等待DHT11的响应信号。DHT11会在接收到启动信号后,拉低引脚80μs,然后拉高80μs作为响应。dht11_get_bit()
:从DHT11读取一个数据位。DHT11通过拉低引脚50μs然后拉高或保持低电平(根据数据位是0还是1)来发送数据位。dht11_get_value()
:读取DHT11发送的完整数据包(40位),并将其存储在提供的数组中。同时,计算校验和并验证数据的正确性