Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1350013
  • 博文数量: 244
  • 博客积分: 10311
  • 博客等级: 上将
  • 技术积分: 3341
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-14 21:50
文章分类

全部博文(244)

文章存档

2013年(6)

2012年(5)

2011年(16)

2010年(11)

2009年(172)

2008年(34)

分类: LINUX

2009-05-07 13:11:59

    在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; i8; 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; i8; 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_DESCRIPTION("DS18B20 driver for s3c2410");
MODULE_LICENSE("GPL");
目前能正确读出温度,还没仔细测试过,不知道有没有bug。
 
阅读(2509) | 评论(7) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-11-03 21:57:52

在源码下的/linux-2.6.32.2/arch/arm/plat-s3c24xx/gpio.h里面

newcch2009-09-14 11:28:11

不好意思,可能我转的那个网址也没出处! 转只是便于记下解决问题的方法,除此之外别外其它目的! 有空我也写自己的东西。

chinaunix网友2009-09-10 19:35:32

转载也不注明一下出处,太让我伤心了!

newcch2009-08-11 13:14:58

编译成模块也行,要是编译到内核就得修改makefile 和kconfig,网上资料很多,查查吧

chinaunix网友2009-08-10 10:24:00

请问一下:怎样把ds18b20驱动程序编译进linux内核?