基于Tiny6410的ds18b20驱动

从网站上下载了lixin的mini2410的ds18b20代码,并做了修改,成功实现了Tiny6410的ds18b20驱动。感谢署名为lixin的网友!

 【程序清单】

ds18b20.c

    /******************************************Copyright(c)************************************************  
    ** 文件名称: ds18b20_drv.c  
    ** 作    者: lixin  
    ** 版    本: v1.0  
    ** 说    明: ds18b20驱动程序.工作过程及时序见ds18b20 datasheet  
    ** 修改记录: 2009-8-27创建  
    ** 最后修改时间: 2009-09-01  
    ******************************************************************************************************/  
    #include <linux/init.h>  
    #include <linux/module.h>  
    #include <linux/delay.h>  
    #include <linux/kernel.h>  
    #include <linux/moduleparam.h>  
    #include <linux/init.h>  
    #include <linux/types.h>  
    #include <linux/fs.h>  
    #include <mach/regs-gpio.h>  
    #include <linux/device.h>  
    #include <mach/hardware.h>  
    #include <linux/cdev.h>  
    #include <asm/uaccess.h>  
    #include <linux/errno.h>  
      
    #include "s3c6410_gpio.h"  
      
    //#define DEBUG  
    /* 相关引脚定义,方便以后移植 */  
    #define DEVICE_NAME "ds18b20"  
    #define DQ         8  
    #define CFG_IN     0  
    #define CFG_OUT    1  
      
    // ds18b20主次设备号(动态分配)  
    int ds18b20_major = 0;  
    int ds18b20_minor = 0;  
    int ds18b20_nr_devs = 1;  
      
    // 定义设备类型  
    static struct ds18b20_device {  
        struct cdev cdev;  
    };  
    struct ds18b20_device ds18b20_dev;  
      
    static struct class *ds18b20_class;  
      
    /* 函数声明 */  
    static int ds18b20_open(struct inode *inode, struct file *filp);  
    static int ds18b20_init(void);  
    static void write_byte(unsigned char data);  
    static unsigned char read_byte(void);  
    static ssize_t ds18b20_read(struct file *filp, char __user *buf,  
                                size_t count, loff_t *f_pos);  
    void ds18b20_setup_cdev(struct ds18b20_device *dev, int index);  
      
    /******************************************************************************************************  
    ** 函数名称: ds18b20_open()  
    ** 函数功能: 打开设备,初始化ds18b20  
    ** 入口参数: inode:设备文件信息; filp: 被打开的文件的信息  
    ** 出口参数: 成功时返回0,失败返回-1  
    ** 备    注:  
    ******************************************************************************************************/  
    static int ds18b20_open(struct inode *inode, struct file *filp)  
    {  
        int flag = 0;  
        /*struct ds18b20_device *dev;  
        dev = container_of(inode->i_cdev, struct ds18b20_device, cdev);  
        filp->private_data = dev;*/  
      
        flag = ds18b20_init();  
        if(flag & 0x01)  
        {  
    #ifdef DEBUG  
            printk(KERN_WARNING "open ds18b20 failed\n");  
    #endif  
        return -1;  
        }  
    #ifdef DEBUG  
        printk(KERN_NOTICE "open ds18b20 successful\n");  
    #endif  
        return 0;  
    }  
      
    /******************************************************************************************************  
    ** 函数名称: ds18b20_init()  
    ** 函数功能: 复位ds18b20  
    ** 入口参数: 无  
    ** 出口参数: retval:成功返回0,失败返回1  
    ** 备    注: 操作时序见ds18b20 datasheet  
    ******************************************************************************************************/  
    static int ds18b20_init(void)  
    {  
        int retval = 0;  
      
        s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
        s3c6410_gpio_pullup(DQ, 0);  
      
        s3c6410_gpio_setpin(DQ, 1);  
        udelay(2);  
        s3c6410_gpio_setpin(DQ, 0);        // 拉低ds18b20总线,复位ds18b20  
        udelay(500);                       // 保持复位电平500us  
      
        s3c6410_gpio_setpin(DQ, 1);        // 释放ds18b20总线  
        udelay(60);  
      
        // 若复位成功,ds18b20发出存在脉冲(低电平,持续60~240us)  
        s3c6410_gpio_cfgpin(DQ, CFG_IN);  
        retval = s3c6410_gpio_getpin(DQ);  
      
        udelay(500);  
        s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
        s3c6410_gpio_pullup(DQ, 0);  
        s3c6410_gpio_setpin(DQ, 1);        // 释放总线  
          
        return retval;  
    }  
      
    /******************************************************************************************************  
    ** 函数名称: write_byte()  
    ** 函数功能: 向18b20写入一个字节数据  
    ** 入口参数: data  
    ** 出口参数: 无  
    ** 备    注:  
    ******************************************************************************************************/  
    static void write_byte(unsigned char data)  
    {  
        int i = 0;  
      
        s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
        s3c6410_gpio_pullup(DQ, 1);  
      
        for (i = 0; i < 8; i ++)  
        {  
            // 总线从高拉至低电平时,就产生写时隙  
            s3c6410_gpio_setpin(DQ, 1);  
            udelay(2);  
            s3c6410_gpio_setpin(DQ, 0);  
            s3c6410_gpio_setpin(DQ, data & 0x01);  
            udelay(60);  
        data >>= 1;  
        }  
        s3c6410_gpio_setpin(DQ, 1);        // 重新释放ds18b20总线  
    }  
      
    /******************************************************************************************************  
    ** 函数名称: read_byte()  
    ** 函数功能: 从ds18b20读出一个字节数据  
    ** 入口参数: 无  
    ** 出口参数: 读出的数据  
    ** 备    注:  
    ******************************************************************************************************/  
    static unsigned char read_byte(void)  
    {  
        int i;  
        unsigned char data = 0;  
      
        for (i = 0; i < 8; i++)  
        {  
            // 总线从高拉至低,只需维持低电平17ts,再把总线拉高,就产生读时隙  
            s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
            s3c6410_gpio_pullup(DQ, 0);  
            s3c6410_gpio_setpin(DQ, 1);  
            udelay(2);  
            s3c6410_gpio_setpin(DQ, 0);  
            udelay(2);  
        s3c6410_gpio_setpin(DQ, 1);  
            udelay(8);  
            data >>= 1;  
        s3c6410_gpio_cfgpin(DQ, CFG_IN);  
        if (s3c6410_gpio_getpin(DQ))  
            data |= 0x80;  
        udelay(50);  
        }  
        s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
        s3c6410_gpio_pullup(DQ, 0);  
        s3c6410_gpio_setpin(DQ, 1);        // 释放ds18b20总线  
        return data;  
    }  
    /******************************************************************************************************  
    ** 函数名称: ds18b20_read()  
    ** 函数功能: 读出18b20的温度  
    ** 入口参数:   
    ** 出口参数:   
    ** 备    注:  
    ******************************************************************************************************/  
    static ssize_t ds18b20_read(struct file *filp, char __user *buf,  
                                size_t count, loff_t *f_pos)  
    {  
        int flag;  
        unsigned long err;  
        unsigned char result[2] = {0x00, 0x00};  
        //struct ds18b20_device *dev = filp->private_data;  
      
        flag = ds18b20_init();  
        if (flag)  
        {  
    #ifdef DEBUG  
            printk(KERN_WARNING "ds18b20 init failed\n");  
    #endif  
            return -1;  
        }  
          
        write_byte(0xcc);  
        write_byte(0x44);  
      
        flag = ds18b20_init();  
        if (flag)  
            return -1;  
      
        write_byte(0xcc);  
        write_byte(0xbe);  
      
        result[0] = read_byte();    // 温度低八位  
        result[1] = read_byte();    // 温度高八位  
          
        err = copy_to_user(buf, &result, sizeof(result));  
        return err ? -EFAULT : min(sizeof(result),count);  
    }  
      
    /**************************************************************  
     * 字符驱动程序的核心,应用程序所调用的open,read等函数最终会  
     * 调用这个结构中的对应函数  
     *************************************************************/  
    static struct file_operations ds18b20_dev_fops = {  
        .owner = THIS_MODULE,  
        .open = ds18b20_open,  
        .read = ds18b20_read,  
    };  
      
    /******************************************************************************************************  
    ** 函数名称: ds18b20_setup_cdev()  
    ** 函数功能: 初始化cdev  
    ** 入口参数: dev:设备结构体; index:  
    ** 出口参数: 无  
    ** 备    注:  
    ******************************************************************************************************/  
    void ds18b20_setup_cdev(struct ds18b20_device *dev, int index)  
    {  
        int err, devno = MKDEV(ds18b20_major, ds18b20_minor + index);  
      
        cdev_init(&dev->cdev, &ds18b20_dev_fops);  
        dev->cdev.owner = THIS_MODULE;  
        err = cdev_add(&(dev->cdev), devno, 1);  
        if (err)  
        {  
    #ifdef DEBUG  
            printk(KERN_NOTICE "ERROR %d add ds18b20\n", err);  
    #endif  
        }  
    }  
      
    /******************************************************************************************************  
    ** 函数名称: ds18b20_dev_init()  
    ** 函数功能: 为温度传感器分配注册设备号,初始化cdev  
    ** 入口参数: 无  
    ** 出口参数: 若成功执行,返回0  
    ** 备    注:  
    ******************************************************************************************************/  
    static int __init ds18b20_dev_init(void)  
    {  
        ds18b20_major = register_chrdev(ds18b20_major, DEVICE_NAME, &ds18b20_dev_fops);  
        if (ds18b20_major<0)  
        {  
        printk(DEVICE_NAME " Can't register major number!\n");  
        return -EIO;  
        }  
      
        ds18b20_class = class_create(THIS_MODULE, DEVICE_NAME);  
        device_create(ds18b20_class, NULL, MKDEV(ds18b20_major, ds18b20_minor), NULL, DEVICE_NAME);  
    #ifdef DEBUG  
        printk(KERN_WARNING "register ds18b20 driver successful!\n");  
    #endif  
        return 0;  
    }  
      
    /******************************************************************************************************  
    ** 函数名称: ds18b20_dev_exit()  
    ** 函数功能: 注销设备  
    ** 入口参数: 无  
    ** 出口参数: 无  
    ** 备    注:  
    ******************************************************************************************************/  
    static void __exit ds18b20_dev_exit(void)  
    {  
        device_destroy(ds18b20_class, MKDEV(ds18b20_major,ds18b20_minor));  
        class_unregister(ds18b20_class);  
        class_destroy(ds18b20_class);  
        unregister_chrdev(ds18b20_major, DEVICE_NAME);  
    #ifdef DEBUG  
        printk(KERN_WARNING "Exit ds18b20 driver!\n");  
    #endif  
    }  
      
    module_init(ds18b20_dev_init);  
    module_exit(ds18b20_dev_exit);  
    MODULE_LICENSE("Dual BSD/GPL");  
    MODULE_AUTHOR("xinli_whut@163.com");  
    /******************************************************************************************************  
    **                                         文件到此结束  
    ******************************************************************************************************/  


s3c6410_gpio.h

    /******************************************Copyright(c)************************************************  
    ** 文件名称: s3c6410_gpio.h  
    ** 作    者: tandesir  
    ** 版    本: v1.0  
    ** 说    明: s3c6410 gpio操作  
    ** 修改记录: 2011-9-27创建  
    ** 最后修改时间: 2011-10-5  
    ******************************************************************************************************/  
    #ifndef __S3C6410_GPIO_H__  
    #define __S3C6410_GPIO_H__  
      
    #include <linux/kernel.h>  
    #include <linux/init.h>  
    #include <linux/module.h>  
    #include <linux/interrupt.h>  
    #include <linux/ioport.h>  
    #include <linux/gpio.h>  
    #include <linux/io.h>  
      
    #include <mach/hardware.h>  
    #include <mach/map.h>   
    #include <mach/regs-gpio.h>  
    #include <mach/gpio-bank-n.h>  
    #include <mach/regs-clock.h>   
    #include <asm/irq.h>  
      
    #include <plat/gpio-core.h>  
    #include <plat/gpio-cfg.h>  
      
    void s3c6410_gpio_cfgpin(unsigned int pin, unsigned int function)  
    {  
        //s3c_gpio_cfgpin(pin,function);  
            unsigned int tmp;   
            tmp = readl(S3C64XX_GPNCON);   
            tmp = (tmp & ~(3<<pin*2))|(function<<pin*2);   
            writel(tmp, S3C64XX_GPNCON);   
    }  
      
    void s3c6410_gpio_pullup(unsigned int pin, unsigned int to)  
    {  
            //s3c_gpio_setpull(pin,to);  
            unsigned int tmp;   
            tmp = readl(S3C64XX_GPNPUD);   
            tmp = (tmp & ~(3<<pin*2))|(to<<pin*2);   
            writel(tmp, S3C64XX_GPNPUD);   
    }  
      
    unsigned int s3c6410_gpio_getpin(unsigned int pin)   
    {   
            unsigned int tmp;  
        tmp = readl(S3C64XX_GPNDAT);   
        tmp = tmp & (1 << (pin));    
      
        return tmp;   
    }  
      
    void s3c6410_gpio_setpin(unsigned int pin, unsigned int dat)  
    {  
            unsigned int tmp;   
        tmp = readl(S3C64XX_GPNDAT);   
        tmp &= ~(1 << (pin));   
        tmp |= ( (dat) << (pin) );   
        writel(tmp, S3C64XX_GPNDAT); ;  
    }  
      
    #endif  

 

Makefile

    # Comment/uncomment the following line to disable/enable debugging  
    DEBUG = n  
      
    # Add your debugging flag (or not) to CFLAGS  
    # "-O" is needed to expand inlines  
    ifeq ($(DEBUG),y)  
      DEBFLAGS = -O -g -DDEBUG   
    else  
      DEBFLAGS = -O2  
    endif  
      
    EXTRA_CFLAGS += $(DEBFLAGS)  
    #EXTRA_CFLAGS += -I$(LDDINC)  
      
    ifneq ($(KERNELRELEASE),)  
    # call from kernel build system  
      
    #scull-objs := main.o pipe.o access.o  
      
        obj-m   := ds18b20.o  
      
      
    else  
      
        KERNELDIR :=/home/tandesir/work/linux-2.6.38  
        PWD       := $(shell pwd)  
      
    modules:  
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules  
      
    clean:  
        rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions  
      
    depend .depend dep:  
        $(CC) $(CFLAGS) -M *.c > .depend  
      
      
    ifeq (.depend,$(wildcard .depend))  
    include .depend  
    endif  
      
    endif  


 

【测试程序】

ds18b20_test.c

    /******************************************Copyright(c)************************************************  
    ** 文件名称: ds18b20_test.c  
    ** 作    者: lixin  
    ** 版    本: v1.0  
    ** 说    明: ds18b20测试程序,精度:0.25度,如有需要,还可以进一步提高。  
    ** 修改记录: 2009-8-27创建  
    ** 最后修改时间: 2009-09-01  
    ******************************************************************************************************/  
    #include <stdio.h>  
    #include <stdlib.h>  
    #include <unistd.h>  
    #include <linux/ioctl.h>  
      
    // 函数声明  
    void ds18b20_delay(int i);  
      
    int main()  
    {  
        int fd, i;  
        unsigned char result[2];           // 从ds18b20读出的结果,result[0]存放低八位  
        unsigned char integer_value = 0;  
        float temperature, decimal_value;  // 温度数值,decimal_value为小数部分的值  
        fd = open("/dev/ds18b20", 0);  
        if (fd < 0)  
        {  
            perror("open device failed\n");  
        exit(1);  
        }  
        while (1)  
        {  
            i++;  
            read(fd, &result, sizeof(result));  
            integer_value = ((result[0] & 0xf0) >> 4) | ((result[1] & 0x07) << 4);  
            // 精确到0.25度  
            decimal_value = 0.5 * ((result[0] & 0x0f) >> 3) + 0.25 * ((result[0] & 0x07) >> 2);  
        // decimal_value = 0.5 * ((result[0] & 0x0f) >> 3) + 0.25 * ((result[0] & 0x07) >> 2)+ 0.125 * ((result[0] & 0x03) >> 1)+ 0.0625 * ((result[0] & 0x01) >>0);  
            temperature = (float)integer_value + decimal_value;  
        printf("The temperature is %6.2f\n",temperature);  
        //printf("The temperature is %6.4f\n",temperature);  
        if (i % 20 == 0)  
            printf("\n");  
        ds18b20_delay(50);  
        }  
    }  
      
    /******************************************************************************************************  
    ** 函数名称: ds18b20_delay()  
    ** 函数功能: 延时  
    ** 入口参数: i  
    ** 出口参数: 无  
    ** 备    注:  
    ******************************************************************************************************/  
    void ds18b20_delay(int i)  
    {  
        int j, k;  
        for (j = 0; j < i; j++)  
            for(k = 0; k < 50000; k++);  
    }  
    /******************************************************************************************************  
    **                                         文件到此结束  
    ******************************************************************************************************/  

 

【学习参考】

2012-6-9

(1) tiny6410温度传感器详细开发步骤

(编译步骤,这个写得不错,不过里面“巨人”的称谓有点怪,我现在只是一名学生,开博只是为了交流学习,欢迎各位共同研究感兴趣的话题。我的编译步骤后续更新会添加)


 原文出书如下:

转载请标明出处,仅供学习交流,勿用于商业目的

Copyright @ http://blog.csdn.net/tandesir


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值