Qt实现天气预报与PM2.5监测系统(4)DHT11模块驱动

Qt实现天气预报与PM2.5监测系统(4)DHT11模块驱动

硬件模块说明

器件(奥松 dht11)
DC:3.3-5.5v
温度:0 - 50°C (±2°C)
湿度:20 - 95 %RH(±5%)

DHT11应用电路
在使用时应在数据端加一个5K的上拉电阻。

工作时序图

初始化时序

读取数据0时序

读取数据1时序

DHT11驱动开发问题

不同频率CPU引起的时序操作问题
1.初始化时序不要加入无关操作,如调试,输出,减少对时序的影响。
2.时序操作连续化,单片机上可多次调用函数读取,但在高主频的CPU上要一次读取全部数据后再进行后期处理。

驱动程序

dht11驱动程序
nanopi2开发板的驱动开发流程可参考文档 :基于NanoPi2的Linux3.4内核GPIO驱动

/******************************************** 功能:DHT21 在nanopi2 s5p4418上驱动程序 GPIO=GPB26 ********************************************/

#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/interrupt.h> 
#include <linux/sched.h>
#include <linux/miscdevice.h>
#include <mach/platform.h>
#include <mach/devices.h>

#define DEVICE_NAME "dht11"
//nanopi2 4418
unsigned int GPIO = PAD_GPIO_B + 26;//模块GPIO脚

#define DPRINTK(x...) printk("<0>"x);

//#define DPRINTK(x...) 

typedef unsigned char  U8;
U8  U8comdata,U8temp[40],U8_data[5];
int init_dht(void)
{   
    int l_flag=0,h_flag=0,flag=0;
    int i=0,j=0;
    int bit_flag[40];
    unsigned tmp;

    DPRINTK("DHT11 init...");

    //GPIO设置为输出
        gpio_direction_output(GPIO, 0);//设置输出 
    //输出0
    gpio_set_value(GPIO, 0);  //输出低电平 
    //延时19ms
    mdelay(20);
    //输出1 
        gpio_set_value(GPIO, 1);  //输出高电平 
    //延时30us
    udelay(40); 
    //设置为输入
        gpio_direction_input(GPIO);//设置输入
    //读GPIO 
    tmp = gpio_get_value(GPIO) ;    
// DPRINTK("gpio=%d\n",tmp);

    if(!tmp)
    {   
        while(!(gpio_get_value(GPIO)) ){
            if((l_flag++)>85) break;            
            udelay(1);
        }//从机80us低电平

        while(gpio_get_value(GPIO)){

            if((h_flag++)>85) break;
            udelay(1);

        }//从机80us高电平
        //read 40bit data
        for(i=0;i<40;i++){
            flag = 0;
            while(!(gpio_get_value(GPIO)) ){
                if((flag++)>70) break;
                udelay(1);
            }//从机50us低电平
            flag =0;
            while(gpio_get_value(GPIO) ){
                if((flag++)>90) break;
                udelay(1);
            }//从机高电平//高电平大于70us为"1",否则26-28us为"0" 

            if(flag>30){
                U8temp[i]=1;
            }else{
                U8temp[i]=0;
            }
            bit_flag[i]=flag;            
        }
        for(i=0;i<40;i++){
            U8comdata<<=1;
            U8comdata|=U8temp[i];
            if((i+1)%8 == 0){
                U8_data[j]=U8comdata;
                j++;
            }

            DPRINTK("[%d]flag=%d,val=%d--",i,bit_flag[i],U8temp[i]);
        }
        DPRINTK("L 80us flag=%d\n",l_flag);
        DPRINTK("H 80us flag=%d \n",h_flag);            
    }else{DPRINTK("L err..\n");}    


    return 0;               
}
static int dht_read(struct file *file, char * buffer, size_t count, loff_t * ppos)
{
    init_dht();
    count = copy_to_user(buffer, U8_data, count);  
    return count;
}

static struct file_operations dht_fops={
    read:dht_read,
};

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

static int __init my_dht_init(void)

{
    int ret;
    ret = misc_register(&misc);
    printk(DEVICE_NAME " initialized\n");
    return 0;
}

static void __exit my_dht_exit(void)
{
    misc_deregister(&misc);
}


module_init(my_dht_init);
module_exit(my_dht_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("TONY");

驱动模块加载到内核
1. 在主机的linux系统编译好驱动模块 :4418_dht11.ko
2. 传文件到开发板 :sudo scp 4418_dht11.ko [email protected]:/home/fa
3. 在开发板设置文件权限:sudo chmod 111 4418_dht11.ko
4. 通过insmod命令加载模块到内核,结果如下图。

dht11数据读取测试程序

#include<stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>

#define DEV_F_DHT "/dev/dht11"


int get_dht_data(const int fd,float* temp,float* humi);

int main(int argc,char* argv[])
{
        float ftemp=0.0,fhumi=0.0;

        int fd_dht = -1;
        if( (fd_dht = open(DEV_F_DHT,O_RDWR)) < 0){
                printf("dht11 init error...\n");
            return -1;
        }else{
            printf("dht11 init...\n");
        }

        while(1){
           if(get_dht_data(fd_dht,&ftemp,&fhumi)==0){
               //读取到数据,可进行后续操作 
           }
            sleep(3);
        }

}


int get_dht_data(const int fd,float* temp,float* humi)
{
        char crr;
        int s;
        char data[5];
        int temp_d=0,humi_d=0;

        bzero(data,5);
        read(fd,data,5);
        crr = 0;

        for(s=0;s<4;s++){
                printf("data[%d]=%x\n",s,data[s]);
                crr+=data[s];
        }
        printf("data[4]=%x,crr=%x\n",data[4],crr);
        if(crr==data[4]){
                humi_d = data[0];
                temp_d = data[2];
                *humi = humi_d;
                *temp = temp_d;
                printf("\n+---RH=%d %%,T=%d oC.\n",humi_d,temp_d);                       
        }else{
                printf("crr err %X\n",crr);
                return -1;
        }
        return 0;
}



测试程序运行结果

你可能感兴趣的:(嵌入式,物联网,linux驱动,dht11传感器)