基于Linux内核的1-wair总线驱动(…

来源:互联网 发布:常用的网络传输介质有 编辑:程序博客网 时间:2024/05/18 20:08

********************************************************************************

                   驱动代码:ds18b20_drv

********************************************************************************

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

MODULE_LICENSE("GPL");

#defineDS18B20_RESET   (0x10009)
#defineDS18B20_REL    (0x10011)

#defineSKIP_ROM   0xcc
#defineCOVERTT    0x44
#defineREAD_MEM   0xbe
#define WRITE_MEM  0x4e

#defineNINE_BIT   0x1f
#defineTEN_BIT    0x3f
#defineELE_BIT    0x5f
#defineTWL_BIT    0x7f

#define TH 100
#define TL  0

#define TEMP_H 10000
#define TEMP_L  -10000

static unsigned long *gpio_con;
static unsigned long *gpio_dat;

static void gpio_cfg_out(unsignedchar val)
{
    *gpio_con&= ~0xf;
    *gpio_con |=0x1;
    if (val ==0) {
       *gpio_dat &= ~0x1;
    } else{
       *gpio_dat |= 0x1;
    }
}

static unsigned chargpio_cfg_in(void)
{
    *gpio_con&= ~0xf;
    return*gpio_dat & 0x1;
}


static void ds18b20_write8(unsigned char data)
{
    int i =0;
    for (;i<8; i++) {
       if ((data & 0x1) == 1) {
           gpio_cfg_out(0);
           udelay(3);
           gpio_cfg_out(1);
           udelay(80);
       } else {
           gpio_cfg_out(0);
           udelay(80);
           gpio_cfg_out(1);
           udelay(3);
       }
       data >>= 1;
    }
}


static unsigned char ds18b20_read8(void)
{
    int i =0;
    unsignedchar bit;
    unsignedchar data = 0;
   
    for (;i<8; i++) {
       gpio_cfg_out(0);
       udelay(2);
       gpio_cfg_out(1);
       udelay(5);
       bit = gpio_cfg_in();
       data |= (bit << i);
       udelay(5);
       gpio_cfg_out(1);
       udelay(60);
    }
    returndata;
}


static void ds18b20_reset(void)
{
    unsignedchar ret = 0;

   gpio_cfg_out(0);
   udelay(500);
   gpio_cfg_out(1);
   udelay(30);
    ret =gpio_cfg_in();
   udelay(500);
#if 0
    if (ret ==0) {
       printk("reset ok.\n");
    } else{
       printk("reset failed.\n");
    }
#endif
}

static voidds18b20_config_rel(unsigned char rel)
{
   ds18b20_reset();
   ds18b20_write8(SKIP_ROM);
   ds18b20_write8(WRITE_MEM);
   ds18b20_write8(TH);
   ds18b20_write8(TL);

   switch (rel) {
       case 9:
           ds18b20_write8(NINE_BIT);
           break;
       case 10:
           ds18b20_write8(TEN_BIT);
           break;
       case 11:
           ds18b20_write8(ELE_BIT);
           break;
       case 12:
           ds18b20_write8(TWL_BIT);
           break;
    }
}

static int ds18b20_open(struct inode*inode, struct file *file)
{
    return0;
}

static int ds18b20_release(structinode *inode, struct file *file)
{
    return0;
}

void bubbleSort(int arr[], intcount)
{
    int i =count, j;
    inttemp;

   while (i > 0) {
       for (j=0; i
           if (arr[j] > arr[j+1]) {
               temp = arr[j];
               arr[j] = arr[j+1];
               arr[j+1] = temp;
           }
       }
       i--;
    }
}

static ssize_t ds18b20_read(structfile *file, char *buf, size_t count, loff_t *pos)
{
    unsignedchar h8, l8;
    int i, temp= 0, tvalsum;
    intvalue[12];

   ds18b20_reset();
   ds18b20_write8(SKIP_ROM);
   ds18b20_write8(COVERTT);
   udelay(700);

   mdelay(750);

   for (i=0; i<12; ++i) {
       ds18b20_reset();
       ds18b20_write8(SKIP_ROM);
       ds18b20_write8(READ_MEM);

       l8 = ds18b20_read8();
       h8 = ds18b20_read8();

       temp = (h8 << 8) | l8;
       if (temp & 0x8000) {
           temp = ~temp + 1;
       }
       temp *= 50;
       temp >>= 3;
       if ((temp > TEMP_H) || (temp < TEMP_L)) {
           --i;
           temp = 0;
           continue;
       }
       value[i] = temp;
    }

   bubbleSort(value, 12);

   for (i=4, tvalsum=0; i<8; ++i) {
       tvalsum += value[i];
    }

   temp = (tvalsum) / 4;
   if(copy_to_user(buf, &temp, 4))
  return -EFAULT;
 return count;
}

static int ds18b20_ioctl(struct inode*inode, struct file *file, unsigned int cmd, unsigned longarg)
{
    unsignedchar rel;
   if(copy_from_user(&rel, (unsigned char *)arg, 1))
  return -EFAULT;

   switch (cmd) {
       case DS18B20_RESET:
           ds18b20_reset();
           break;
       case DS18B20_REL:
           ds18b20_config_rel(rel);
           break;
       default:
           return -1;
    }

   return 0;
}

static struct file_operationsds18b20_fops = {
    .owner =THIS_MODULE,
   .open  = ds18b20_open,
    .release =ds18b20_release,
   .read  = ds18b20_read,
   .unlocked_ioctl = ds18b20_ioctl,
};

static struct miscdeviceds18b20_miscdev = {
   .minor  = MISC_DYNAMIC_MINOR,
   .name   = "ds18b20",
   .fops   =&ds18b20_fops,
};

static int ds18b20_init(void)
{
   misc_register(&ds18b20_miscdev);

   gpio_con = ioremap(0xe0200c20, 8);
    gpio_dat =gpio_con + 1;

   return 0;
}

static void ds18b20_exit(void)
{
   iounmap(gpio_con);
   misc_deregister(&ds18b20_miscdev);
}

module_init(ds18b20_init);
module_exit(ds18b20_exit);

********************************************************************************

                   Makefile文件

********************************************************************************

ifeq ($(KERNELRELEASE),)

KERNELDIR ?=/home/linux/linux-3.0.8/
PWD := $(shell pwd)

modules:
 $(MAKE) -C $(KERNELDIR) M=$(PWD)modules

modules_install:
 $(MAKE) -C $(KERNELDIR) M=$(PWD)modules_install

test:test.c


clean:
 rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c.tmp_versions Module* module* test

.PHONY: modules modules_install clean

else
    obj-m :=ds18b20_drv.o
endif

********************************************************************************

               测试代码:test

********************************************************************************

#include
#include
#include
#include
#include
#include
#include


#define DS18B20_RESET 0x10001
#define DS18B20_REL  0x10002


int main(int argc, char *argv[])
{
 int fd;
 int data;
 unsigned char relbit;
 
 fd = open("/dev/ds18b20", O_RDWR);
 if (fd < 0)
 {
  printf("open ds18b20failed.\n");
  exit(-1);
 }
 if (argc < 2)
 {
  printf("usage:\n %s<9|10|11|12>\n", argv[0]);
  exit(-1);
 }
 relbit = strtoul(argv[1], NULL, 10);
 while (1) {
  ioctl(fd, DS18B20_REL,&relbit);
  read(fd, &data,sizeof(data));
  usleep(200000);
  printf("%f\n", (float)data /100);
 }
 close(fd);
 return 0;
}



 

0 0
原创粉丝点击