Chinaunix首页 | 论坛 | 博客
  • 博客访问: 515468
  • 博文数量: 87
  • 博客积分: 4086
  • 博客等级: 上校
  • 技术积分: 900
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-23 15:55
文章分类

全部博文(87)

文章存档

2012年(3)

2010年(13)

2009年(7)

2008年(64)

我的朋友

分类: LINUX

2008-07-10 15:07:07

    昨天在2410板子上挂了一个ds18b20温度传感器,网上找了好久都没找到linux下的驱动程序,于是按照以前在51上写的驱动改写了一个,把源文件奉上,与大家共享。
 
    注意,我使用的是gph9与18b20通信,如果您用的引脚不一样,只需要修改这三个宏:
 
#define   DQ             S3C2410_GPH9
#define   CFG_IN         S3C2410_GPH9_INP
#define   CFG_OUT        S3C2410_GPH9_OUTP

/*包含了这么多的头文件,也不知道有的有没有用*/

#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/uaccess.h>
#include <linux/clk.h>

#include <asm-arm/arch-s3c2410/regs-gpio.h>
#include <asm/io.h>
#include <asm/arch/map.h>
#include <asm-arm/plat-s3c24xx/clock.h>
#include <asm/arch/regs-clock.h>


/*和引脚相关的宏定义*/
#define DQ S3C2410_GPH9
#define CFG_IN S3C2410_GPH9_INP
#define CFG_OUT S3C2410_GPH9_OUTP

static int opencount = 0;

unsigned char init_ds(void)//ds18b20复位,返回0成功,返回1失败
{
  unsigned char ret = 0;

  s3c2410_gpio_cfgpin(DQ, CFG_OUT);
  s3c2410_gpio_pullup(DQ, 0);

  s3c2410_gpio_setpin(DQ, 1);
  s3c2410_gpio_setpin(DQ, 0);
  udelay(500);

  s3c2410_gpio_setpin(DQ, 1);
  udelay(50);

  s3c2410_gpio_cfgpin(DQ, CFG_IN);
  udelay(200);
  ret = s3c2410_gpio_getpin(DQ);

  s3c2410_gpio_cfgpin(DQ, CFG_OUT);
  s3c2410_gpio_pullup(DQ, 0);
  s3c2410_gpio_setpin(DQ, 1);
  
  return ret;
}

void write_byte(char data)//向18b20写一个字节
{
  char i = 0;

  s3c2410_gpio_cfgpin(DQ, CFG_OUT);
  s3c2410_gpio_pullup(DQ, 1);

  for(i=0; i<8; i++){
    s3c2410_gpio_setpin(DQ, 0);
    udelay(10);
    s3c2410_gpio_setpin(DQ, 1);
    s3c2410_gpio_setpin(DQ, data&0x01);
    udelay(60);
    s3c2410_gpio_setpin(DQ, 1);
    udelay(2);
    data >>= 1;
  }
}

unsigned char read_byte(void)//从18b20读一个字节
{
  unsigned char i;
  unsigned char data=0;

  s3c2410_gpio_cfgpin(DQ, CFG_OUT);
  s3c2410_gpio_pullup(DQ, 0);

  for(i=0; i<8; i++)
    {
      s3c2410_gpio_setpin(DQ, 0);
      udelay(1);
      s3c2410_gpio_setpin(DQ, 1);

      s3c2410_gpio_cfgpin(DQ, CFG_IN);

      udelay(10);
      
      data >>= 1;
      if(s3c2410_gpio_getpin(DQ))
    data |= 0x80;

      udelay(50);
      s3c2410_gpio_cfgpin(DQ, CFG_OUT);
      s3c2410_gpio_pullup(DQ, 0);
      s3c2410_gpio_setpin(DQ, 1);
      udelay(2);
    }
  return data;
}
  
/*文件的写函数,没有实际意义,用户不能写文件*/    
static ssize_t ds18b20_write(struct file *filp, const char *buffer,
             size_t count, loff_t *ppos)
{
  return 10;//随便返回一个正整数
}

/*18b20的读函数,读出的温度只保留了整数*/
static ssize_t ds18b20_read(struct file *filp, char *buffer,
             size_t count, loff_t *ppos)
{
  unsigned char a=0, b=0;
  unsigned int t=0;
  unsigned char temp=0;
  unsigned char flag;

  flag = init_ds();
  if(flag&0x01)
    return -1;

  write_byte(0x0cc);
  write_byte(0x44);

  udelay(500);

  flag = init_ds();
  if(flag&0x01)
    return -1;

  write_byte(0x0cc);
  write_byte(0x0be);

  a = read_byte();
  b = read_byte();
  
  flag = init_ds();


  temp = ((b & 0x7) << 4)) | (a >> 4);
  copy_to_user(buffer, &temp, 1);
  return 1;
}

static int ds18b20_open(struct inode *node, struct file *file)
{
  unsigned char flag;

  if(opencount == 1)
    return -EBUSY;
  
  flag = init_ds();

  if(flag&0x01)
    {
      printk("uable to open device!\n");
      return -1;
    }
  else
   {
      opencount++;
      printk("device opened!\n");
      return 0;
   }
}

static int ds18b20_release(struct inode *node, struct file *file)
{
  opencount--;
  printk("device released!\n");
  return 0;
}

static struct file_operations ds18b20_fops = {
  .owner = THIS_MODULE,
  .write = ds18b20_write,
  .read = ds18b20_read,
  .release = ds18b20_release,
  .open = ds18b20_open,
};

static int ds18b20_probe(struct platform_device *pdev)
{
  int ret;

  s3c2410_gpio_cfgpin(DQ, CFG_OUT);
  s3c2410_gpio_setpin(DQ, 0);
  ret = register_chrdev(0, "ds18b20", &ds18b20_fops);
  if(!ret)
    printk("--------------Uable to register driver!-------------------\n");
  
  printk("Probe for ds18b20 finished!\n");
  return 0;
}

static struct platform_driver ds18b20 =
{
  .probe = ds18b20_probe,
  .driver = {
    .name = "s3c2410-ds",
    .owner = THIS_MODULE,
  },
};

int __init ds18b20_init(void)
{
  printk("Initial driver for ds18b20......................\n");
  return platform_driver_register(&ds18b20);
}

void __exit ds18b20_exit(void)
{
  return platform_driver_unregister(&ds18b20);
}

module_init(ds18b20_init);
module_exit(ds18b20_exit);

MODULE_AUTHOR("yanqiang-liu@163.com");
MODULE_DESCRIPTION("DS18B20 driver for s3c2410");
MODULE_LICENSE("GPL");

 

目前能正确读出温度,还没仔细测试过,不知道有没有bug。

阅读(1769) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~