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

我用的是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);   
    }   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值