DHT11
DHT11是一款含有已校准数字信号输出的温湿度复合传感器,它结合了电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。通过采用专用的数字模块采集技术和温湿度传感技术,DHT11确保了产品的高可靠性和长期稳定性
DHT11时序部分主要为 DHT11启动时序,读取数字0和读取数字1
1 . DHT11启动时序
①
主机首先将电平拉低,至少持续18us [ mdelay(20) ],随后再拉高;
cpp
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已经正确响应启动信号,即将开始传输数据
cpp
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位和校验位不相等,那么此次数据作废。
cpp
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
cpp#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
cpp#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");