当前位置: 代码迷 >> 驱动开发 >> tiny 6410 ds18b20 温度传感器采集数据偶尔出异常
  详细解决方案

tiny 6410 ds18b20 温度传感器采集数据偶尔出异常

热度:751   发布时间:2016-04-28 10:47:59.0
tiny 6410 ds18b20 温度传感器采集数据偶尔出错误

硬件 tiny 6410 ds18b20 传感器 
系统:linux 2.3.68
问题:读取的数据有时候会产生错误,例如突然变成0度 或者1000度 然后在恢复。
驱动代码。
C/C++ code
驱动代码/* *    Temperature sensor driver for zc6410 *         register list: *    DQ:EINT8(GPN8) *    GPNCON:0x7F008830 *    GPNDAT:0x7F008834 *    GPNPUD:0x7F008838 * *    register contorl: *    GPN8[17:16]    00=input 01=output 10=Ext.interrupt[8] 11=reserved * */#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <linux/cdev.h>#include <linux/miscdevice.h>#include <linux/ioctl.h>#include <linux/io.h>#include <linux/ioport.h>#include <asm/uaccess.h>//#include <regs-gpio.h>//#include <mach/hardware.h>#define DEBUG_18B20 0#define DEVICE_NAME "ds18b20"#define DSDATA 0x7F008830#define DATAOUTP 1#define DATAINP 0#define DS18B20_MAGIC 'k'#define DS18B20_RESET _IO(DS18B20_MAGIC, 0)static void *pVmem = NULL;#define s3c6410_gpio_cfgpin(pin, state) \    (state?({unsigned int vmem; vmem = ioread32(pin); vmem &= ~(3<<16); vmem |= 1<<16; iowrite32(vmem, pin);}):({unsigned int vmem; vmem = ioread32(pin); vmem &= ~(3<<16); iowrite32(vmem, pin);}))#define s3c6410_gpio_setpin(pin, state) \    (state?({unsigned int vmem; vmem = ioread32(pin+4); vmem |= (1<<8); iowrite32(vmem, pin+4);}):({unsigned int vmem; vmem = ioread32(pin+4); vmem &= ~(1<<8); iowrite32(vmem, pin+4);}))#define s3c6410_gpio_getpin(pin) ((ioread32(pin+4)>>8) & 1)static ssize_t ds18b20_read(struct file *filp, char __user *buff, size_t count, loff_t *offp){  volatile int i, size=count;  unsigned char ddat = 0;  if (size > 2)    size = 1;    for (i=0; i<8; i++)  {    ddat >>= 1;    s3c6410_gpio_cfgpin(pVmem, DATAOUTP);    s3c6410_gpio_setpin(pVmem, 0);    udelay(4);  //4us    s3c6410_gpio_setpin(pVmem, 1);    s3c6410_gpio_cfgpin(pVmem, DATAINP);    if ( s3c6410_gpio_getpin(pVmem) )    {      ddat |= 0x80;    }    udelay(80);  // >70us    s3c6410_gpio_cfgpin(pVmem, DATAOUTP);    s3c6410_gpio_setpin(pVmem, 1);    udelay(3);  // >1us  }  s3c6410_gpio_cfgpin(pVmem, DATAINP);    if(copy_to_user(buff, &ddat, size))  {    return -1;  }  return size;}static ssize_t ds18b20_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp){  volatile int i, size=count;  char ddat=0;    if (size > 2)  size = 1;      if (copy_from_user(&ddat, buff, size))  {    printk("write data error\n");    return -1;  }    s3c6410_gpio_cfgpin(pVmem, DATAOUTP);  for (i=0; i<8; i++)  {    s3c6410_gpio_setpin(pVmem, 0);    udelay(5); //5us    if (ddat & 0x01)    {      s3c6410_gpio_setpin(pVmem, 1);    }     udelay(80);  // >70us    s3c6410_gpio_setpin(pVmem, 1);        udelay(3);  // >1us    ddat >>= 1;  }  s3c6410_gpio_cfgpin(pVmem, DATAINP);  return size;}static int ds18b20_ioctl( struct inode *inode,     struct file *file, unsigned int cmd, unsigned long arg){  int ret = 0;  switch(cmd)   {    //case DS18B20_RESET:  // reset    case 0:  // reset      s3c6410_gpio_cfgpin(pVmem, DATAOUTP);      s3c6410_gpio_setpin(pVmem, 1);      udelay(27);      s3c6410_gpio_setpin(pVmem, 0);      udelay(500);  // 500us      s3c6410_gpio_setpin(pVmem, 1);      udelay(27);      s3c6410_gpio_cfgpin(pVmem, DATAINP);      udelay(60);      ret = s3c6410_gpio_getpin(pVmem);      msleep(3);    default:      return -EINVAL;  }  return ret;}static int ds18b20_open(struct inode *inode, struct file *file){  /* GPN8[17:16] = 00 */  s3c6410_gpio_cfgpin(pVmem, DATAINP);  #if DEBUG_18B20  printk("context of 0x%x is 0x%x\n", DSDATA, ioread32(pVmem));#endif  return 0;}static int ds18b20_release(struct inode *inode, struct file *file){  return 0;}static struct file_operations ds18b20_fops = {  .owner = THIS_MODULE,  .open    = ds18b20_open,  .release = ds18b20_release,   .unlocked_ioctl = ds18b20_ioctl,  .read = ds18b20_read,  .write = ds18b20_write,   //.compat_ioctl = ds18b20_ioctl,};static struct miscdevice misc = {  .minor = MISC_DYNAMIC_MINOR,  .name = DEVICE_NAME,  .fops = &ds18b20_fops,};// register ds18b20static int __init dev_init(void){  int ret;  ret = misc_register(&misc);  if(!request_mem_region(DSDATA, 0x8, DEVICE_NAME))      goto error;  pVmem = ioremap(DSDATA, 0x8);    printk(DEVICE_NAME"\tinitialized\n");  return ret;error:    misc_deregister(&misc);    return -EFAULT; /* bad address */}// unregister ds18b20static void __exit dev_exit(void){  iounmap(pVmem);  release_mem_region(DSDATA, 0x8);  misc_deregister(&misc);}module_init(dev_init);module_exit(dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("modified by __eabi");