DHT11 实现温湿度传感器
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;elsereturn -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;elsereturn -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;elsereturn -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");