硬件驱动之DST11温湿度传感器

一 操作流程及思路

一 传感器指标: 

二 接口图 

二 代码实现(结合DHT11的时序图)

        封装配置IO接口函数

#define SET_DQ_OUT   (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3)) | (0x1))) //设置输出
#define SET_DQ_IN        (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3))))  //设置输入
#define SET_DQ_HIGH        (*(pGPFBase+1) = ((*(pGPFBase+1)) | (0x1)))  //高电平
#define SET_DQ_LOW         (*(pGPFBase+1) = ((*(pGPFBase+1)) & ~(0x1)))   //低电平
#define GET_DQ_STAT        (*(pGPFBase+1) & (0x1))  //获得电平状态

        封装起始信号函数 和接受响应函数

static void send_dht11_start(void)
{
    SET_DQ_LOW;
    mdelay(20);
    SET_DQ_HIGH;
    SET_DQ_IN;

    return;
}

static int check_dht11_reply(void)
{
    int cnt = 0;

    while (GET_DQ_STAT && cnt < 24)
    {
        cnt++;
        udelay(10);
    }

    if (cnt >= 24)
    {
        return -1;
    }

    while (!GET_DQ_STAT);
    while (GET_DQ_STAT);

    return 0;
}

        封装接受信号的函数

 

static unsigned char dht11_readbyte(void)
{
    int cnt = 0;
    int i = 0;
    unsigned char ret = 0;

    for (i = 7; i >= 0; i--)
    {
        cnt = 0;
        while (!GET_DQ_STAT);

        while (GET_DQ_STAT)
        {
            cnt++;
            udelay(1);
        }

        if (cnt > 40)
        {
            ret |= (0x1 << i);
        }
    }

    return ret;
}

        platform代码框架总体实现

其分为三部分,内核设备层,内核驱动层,用户应用层

        decice.c

static struct resource res[] = {        //资源,分配其需要的资源
    [0] = {
       .start = 0x56000050,           // 物理地址起始
       .end = 0x56000050 + 8 - 1,     // 物理地址结束
       .name = "GPF",                //资源名称
       .flags = IORESOURCE_MEM,    //标识为内存资源
    },
};

static struct platform_device dht11_device = {    //platform框架,混杂设备注册的结构体初始化
    .name = "dht11",   //是否能配对成功,主要看这个
    .id = -1,
    .dev.release = dht11_release,
    .resource = res,
    .num_resources = sizeof(res) / sizeof(res[0]),
};

static void  dht11_release(struct device *dev)    //释放设备
{

    return;
}

static int __init init_dht11_device(void)  //初始化设备  
{
    int ret = 0;
    
    ret = platform_device_register(&dht11_device);
    if (ret != 0)
    {
        return -1;
    } 

    printk("platform dht11 device register success!\n");

    return 0;
}

static void __exit exit_dht11_device(void)          //注销设备
{
    platform_device_unregister(&dht11_device);    //注册混杂设备

    printk("platform dht11 device unregister success!\n");

    return;
}

module_init(init_dht11_device);
module_exit(exit_dht11_device);
MODULE_LICENSE("GPL");

driver.c 

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/irqreturn.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/delay.h>

static volatile unsigned int *pGPFBase = NULL;
static int dht11_probe(struct platform_device *device);
static int dht11_open(struct inode *node, struct file *fp);
static ssize_t dht11_read(struct file *fp, char __user *puser, size_t n, loff_t *off);
static int dht11_release(struct inode *node, struct file *fp);

#define SET_DQ_OUT         (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3)) | (0x1)))
#define SET_DQ_IN          (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3))))
#define SET_DQ_HIGH        (*(pGPFBase+1) = ((*(pGPFBase+1)) | (0x1)))
#define SET_DQ_LOW         (*(pGPFBase+1) = ((*(pGPFBase+1)) & ~(0x1)))
#define GET_DQ_STAT        (*(pGPFBase+1) & (0x1))    

static struct platform_driver dht11_driver = {
    .probe = dht11_probe,
    .driver.name = "dht11",       //用于匹配的名称
};

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = dht11_open,
    .read = dht11_read,
    .release = dht11_release,
};

static struct miscdevice misc_dht11 = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "dht11",
    .fops = &fops,
};  

static int dht11_open(struct inode *node, struct file *fp)
{
    SET_DQ_OUT;
    SET_DQ_HIGH;

    return 0;
}   

static int dht11_release(struct inode *node, struct file *fp)
{
    SET_DQ_OUT;
    SET_DQ_HIGH;

    return 0;
}

static void send_dht11_start(void)
{
    SET_DQ_LOW;
    mdelay(20);
    SET_DQ_HIGH;
    SET_DQ_IN;

    return;
}

static int check_dht11_reply(void)
{
    int cnt = 0;

    while (GET_DQ_STAT && cnt < 24)
    {
        cnt++;
        udelay(10);
    }

    if (cnt >= 24)
    {
        return -1;
    }

    while (!GET_DQ_STAT);
    while (GET_DQ_STAT);

    return 0;
}

static unsigned char dht11_readbyte(void)
{
    int cnt = 0;
    int i = 0;
    unsigned char ret = 0;

    for (i = 7; i >= 0; i--)
    {
        cnt = 0;
        while (!GET_DQ_STAT);

        while (GET_DQ_STAT)
        {
            cnt++;
            udelay(1);
        }

        if (cnt > 40)
        {
            ret |= (0x1 << i);
        }
    }

    return ret;
}

static ssize_t dht11_read(struct file *fp, char __user *puser, size_t n, loff_t *off)
{
    int ret = 0;
    unsigned char data[5] = {0};

#if 1
    send_dht11_start();
    ret = check_dht11_reply();
    if (-1 == ret)
    {
        return -1;
    }
    
    data[0] = dht11_readbyte();
    data[1] = dht11_readbyte();
    data[2] = dht11_readbyte();
    data[3] = dht11_readbyte();
    data[4] = dht11_readbyte();

    SET_DQ_OUT;
    SET_DQ_HIGH;

    if (data[0] + data[1] + data[2] + data[3] == data[4])
    {
        copy_to_user(puser, data, sizeof(data)-1);
    }
    else 
    {
        return -2;
    }
#endif
    return sizeof(data)-1;
}

static int dht11_probe(struct platform_device *device)
{
    int ret = 0;
    
    ret = misc_register(&misc_dht11);
    if (ret != 0)
    {
        return -1;
    }

    pGPFBase = ioremap(device->resource[0].start, device->resource[0].end - device->resource[0].start);
    if (NULL == pGPFBase)
    {
        return -1;
    }

    return 0;
}

static int __init init_dht11_driver(void)
{
    int ret = 0;

    ret = platform_driver_register(&dht11_driver);
    if (ret != 0)
    {
        return -1;
    }

    printk("platform dht11 driver init success!\n");

    return 0;
}

static void __exit exit_dht11_driver(void)
{
    platform_driver_unregister(&dht11_driver);

    printk("platform dht11 driver exit success!\n");

    return;
}

module_init(init_dht11_driver);
module_exit(exit_dht11_driver);
MODULE_LICENSE("GPL");

./app

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>

int main(void)
{
    int fd = 0;
    unsigned char data[4] = {0};
    char temp[32] = {0};
    char hum[32] = {0};
    ssize_t nret = 0;

    fd = open("/dev/dht11", O_RDWR);
    if (-1 == fd)
    {
        perror("fail to open");
        return -1;
    }

    sleep(2);
#if 1
    while (1)
    {
        nret = read(fd, data, sizeof(data));
        sprintf(temp, "%d.%d", data[2], data[3]);
        sprintf(hum, "%d.%d", data[0], data[1]);
        printf("%d, temp = %s, hum = %s\n", nret, temp, hum);
        sleep(2);
    }

#endif

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值