您的位置:首页 > 其它

嵌入式采集温度DS18B20-platform驱动

2017-02-16 16:15 344 查看
我用的是FL2440开发板查看好datasheet后找到相应的管脚写的platform 总线编写

/*********************************************************************************

 *      Copyright:  (C) 2016 guanlei

 *                  All rights reserved.

 *

 *       Filename:  myds18b20.c

 *    Description:  This file 

 *                 

 *        Version:  1.0.0(2016年04月11日)

 *         Author:  guanlei <995318056@qq.com>

 *      ChangeLog:  1, Release initial version on "2016年04月11日 14时56分25秒"

 *                 

 ********************************************************************************/

#include <linux/module.h>  

#include <linux/init.h>  

#include <linux/kernel.h>  

#include <linux/fs.h> 

#include <linux/delay.h>  

#include <asm/irq.h>  

#include <mach/regs-gpio.h>  

#include <mach/hardware.h>  

#include <linux/cdev.h>  

#include <linux/device.h>  

#include <linux/kdev_t.h>  

#include <asm/uaccess.h>  

#include <linux/platform_device.h>  

#include <linux/gpio.h>

#define DEV_NAME        "ds18b20"  

#ifndef  DEV_MAJOR

#define  DEV_MAJOR      0 /* dynamic major by default  */

#endif

#define DS18B20_PIN            S3C2410_GPG(0)

#define DS18B20_PIN_OUT        S3C2410_GPIO_OUTPUT

#define DS18B20_PIN_IN         S3C2410_GPIO_INPUT

typedef unsigned  char  BYTE;

  dev_t devno;     

MODULE_LICENSE("GPL");  

static int dev_major = DEV_MAJOR;

static int dev_minor = 0;

struct cdev my_cdev;  

static struct class *ds18b20_class;

 BYTE data[2];

static struct platform_device s3c2440_ds18b20_device ={

    .name = "s3c2440_ds18b20",

    .id = 1,

    .dev ={

    },

}; 

unsigned char ds18b20_reset(void)

{

     s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_OUT);/* config output mode */

     s3c2410_gpio_setpin(DS18B20_PIN,1);/* send high and keep 100us */

     udelay(100);

     s3c2410_gpio_setpin(DS18B20_PIN,0) ;/* send low  and keep 600us */

     udelay(600);

     s3c2410_gpio_setpin(DS18B20_PIN, 1);   // 向18B20发送一个上升沿,此时可释放DS18B20总线  

     udelay(100);

     // 通过再次配置GPIG0引脚成输入状态,可以检测到DS18B20是否复位成功   

     s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_IN);  

     if(s3c2410_gpio_getpin(DS18B20_PIN))

     {

         printk("DS18b20 reset failed.\r\n"); 

         return 1;

     }

     printk("reset successed!\n");

     return 0;

}

void ds18b20_write_byte(unsigned char byte)

{

   unsigned char i;

   s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_OUT);

   /*  write 1 

    *  keep low 1us-15us

    * then keep bus high 15us - 60us

    *

    * write 0 

    * keep low 15us - 60us

    * then keeep bus high 1us - 15us 

    */

   for (i=0;i<8;i++)

   {

       s3c2410_gpio_setpin(DS18B20_PIN,0);

           /* 每次写之后延时 1us */

       udelay(1);

         /* write 1 or 0  */

       s3c2410_gpio_setpin(DS18B20_PIN,(byte&0x01)?1:0);

       udelay(60);

       /* release bus  */

       s3c2410_gpio_setpin(DS18B20_PIN,1); 

       byte >>= 1;

       udelay(15);

   }

    

   s3c2410_gpio_setpin(DS18B20_PIN, 1); //释放总线  

}

unsigned char ds18b20_read_byte(void )

{

    unsigned char i ;

    unsigned char dat = 0 ;

   

    for(i=0;i<8;i++)

    {

        s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_OUT);

        s3c2410_gpio_setpin(DS18B20_PIN,0); /* give a maicohong */

        dat >>= 1;

        udelay(1);

        s3c2410_gpio_setpin(DS18B20_PIN,1); /*  */

        s3c2410_gpio_cfgpin(DS18B20_PIN,DS18B20_PIN_IN);

        if(s3c2410_gpio_getpin(DS18B20_PIN))

        {

            dat |= 0x80;

        }

       udelay(60);

       

    }

    return dat;

}

static int ds18b20_open(struct inode *inode, struct file *file) 

{

    printk("open ds18b20");

    return 0;

}

static int ds18b20_read(struct file *filep,char *buff ,size_t len ,loff_t *offp)

{

    //unsigned char  temp_flag; /* above zero or below zero */

    //  unsigned short temp;

    int  err;

     ds18b20_reset(); /* reset  */

     udelay(120);

     ds18b20_write_byte(0xcc);//写入CCH命令,跳过读序列号过程;

     ds18b20_write_byte(0x44);//写入44H命令,开始温度转换,延时5 ms;

     udelay(5);

     ds18b20_reset();

     udelay(200);

     ds18b20_write_byte(0xcc);//写入CCH命令,跳过读序列号过程; 

     ds18b20_write_byte(0xbe); //写入BEH命令,读取寄存器; 

    

     data[0] = ds18b20_read_byte(); //温度的整数部分

     data[1] = ds18b20_read_byte(); //温度的小数部分

  /*   

     temp  = ((unsigned char)data[0]) << 8; 

     temp |=(unsigned char)data[1];

     temp = 0.0625*((double)temp);

  */

      err = copy_to_user(buff,(void *)data,len);

     return err? -EFAULT:len ;

}

static struct file_operations ds18b20_ops = {

    .owner = THIS_MODULE,

    .read  = ds18b20_read,

    //.release = ds18b20_release,

};

static int  s3c2440_ds18b20_probe(struct platform_device *pdev)

{

    int ret ,err,result;

 

    /*alloc the device for device   */

    if( 0 != dev_major)

    {

      devno = MKDEV(dev_major,dev_minor);

      result = register_chrdev_region(devno,1,DEV_NAME);

    }

    else

    {

        result = alloc_chrdev_region(&devno,dev_minor,1,DEV_NAME);

        dev_major = MAJOR(devno);   

    }

    /* alloc for device major failure */

    if(result<0)

    {

        printk("alloc_chdrev_region error");

        printk("%s driver can't get major %d\n", DEV_NAME, dev_major);

        return result;

    }

    printk("%s driver get major %d\n", DEV_NAME, dev_major);

   /* init ds18b20_device and register cdev */

   cdev_init (&my_cdev,&ds18b20_ops);

   my_cdev.owner = THIS_MODULE;

   err = cdev_add(&my_cdev,devno,1);

   if(err<0)

    {

        printk("cdev error");

        goto ERROR;

    }

 

   /* creat device node  */

   ds18b20_class = class_create(THIS_MODULE,DEV_NAME);

    if(IS_ERR(ds18b20_class))

    {

        printk("Err:failed in ds18b20_class\n");

        goto ERROR;

    }

    device_create(ds18b20_class,NULL,devno,NULL,DEV_NAME);

    printk(DEV_NAME"initialized\n"); 

    return 0;

ERROR:

   printk("s3c %s driver version %d=dev_major,%d=dev_minor install failure",DEV_NAME,DEV_MAJOR,dev_minor);

   cdev_del(&my_cdev);

   unregister_chrdev_region(devno,1);

   return -1;

}

static void __exit s3c2440_ds18b20_remove(void)

{

    cdev_del(&my_cdev);

    unregister_chrdev_region(devno,1);

    class_destroy(ds18b20_class);

    device_destroy(ds18b20_class,devno);

}

static struct platform_driver s3c2440_ds18b20_driver ={

    .probe   = s3c2440_ds18b20_probe,

    .remove  = s3c2440_ds18b20_remove,

    .driver  = {

         .name  = "s3c2440_ds18b20",

         .owner = THIS_MODULE,

    },

};

static int __init s3c2440_ds18b20_init ( void )

{

    int  ret = 0;

    

  

    ret = platform_device_register(&s3c2440_ds18b20_device);

    if(ret)

    {

        printk("cant not register platform__device_register");

        goto fail_reg_plat_dev;

    }

    ret = platform_driver_register(&s3c2440_ds18b20_driver);

    

    if(ret)

    {

        printk("cant not register platform_driver_register");

        goto  fail_reg_plat_drv;

    }

    printk("initial") ;

    return ret;

fail_reg_plat_drv:

    platform_driver_unregister(&s3c2440_ds18b20_driver);

    return -1;

fail_reg_plat_dev:

  return ret ;

}

static void s3c2440_ds18b20_exit(void)

{

    platform_driver_unregister(&s3c2440_ds18b20_driver);

}

module_init(s3c2440_ds18b20_init);

module_exit(s3c2440_ds18b20_exit);

相应的MAKEFILE

CC=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc

KDIR?=/home/guanlei/fl2440/kernel/linux-3.0

obj-m:=myds18b20.o

default:
$(MAKE) -C $(KDIR) M=`pwd` modules
make clean

clean:
rm -f *.ko.* *.o *mod.c *.order *.symvers

相应的简单的测试程序

#include <stdio.h>  

#include <sys/types.h>   

#include <sys/ioctl.h>   

#include <stdlib.h>   

#include <termios.h>  

#include <sys/stat.h>  

#include <fcntl.h>   

#include <sys/time.h>   

  

main()   

{   

    int fd;   

    unsigned char buf[2];   

    unsigned short temp=0;   

double result=0;   

int flag=0;   

  

    if ((fd=open("/dev/ds18b20",O_RDWR | O_NDELAY | O_NOCTTY)) < 0)   

    {   

        printf("Open Device DS18B20 failed.\r\n");   

        exit(1);   

    }   

    else   

    {   

        printf("Open Device DS18B20 successed.\r\n");   

        while(1)   

        {   

                    read(fd, buf, sizeof(buf));   

                    printf("read data is 0x%02X-0x%02X\n",buf[1],buf[0]);   

                    temp=((unsigned short)buf[1])<<8;   

                    temp|=(unsigned short)buf[0];   

                //  printf("no error here\n");   

                    result=0.0625*((double)temp);   

                    printf("temperature is %4f \r\n", result);   

                    sleep(2);   

        }   

        close(fd);   

    }   

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DS18B20 嵌入式