首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 驱动开发 >

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

2012-09-09 
tiny 6410 ds18b20温度传感器采集数据偶尔出错误硬件 tiny 6410ds18b20 传感器系统:linux 2.3.68问题:读取

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"); 



测试代码!!
C/C++ code
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>#include <error.h>#include <time.h>#include <fcntl.h>#define DS18B20_MAGIC 'k'#define DS18B20_RESET _IO(DS18B20_MAGIC, 0)static int fd=0;static unsigned char a=0;static unsigned char b=0;/*****读取温度*****/static unsigned int ReadTemperature(void){    unsigned int t=0;    ioctl(fd, DS18B20_RESET, 0);       //初始化    a = 0xcc;    write(fd, &a, 1);  //跳过读序号列号的操作    a = 0x44;    write(fd, &a, 1);  //启动温度转换    sleep(1);    ioctl(fd, DS18B20_RESET, 0);    //初始化    a = 0xcc;    write(fd, &a, 1);    //跳过读序号列号的操作    a = 0xbe;    write(fd, &a, 1);    //读取温度寄存器    read(fd, &a, 1);   //读低8位    read(fd, &b, 1);   //读高8位    t = b;    t <<= 8;    t = t | a;    usleep(5000);    return t;}int main(int argc, char **argv){    int val;    float fval;        fd = open("/dev/ds18b20", O_RDWR);    if (fd < 0)    {        perror("open device ds18b20!");        return -1;    }    while(1)    {        val = ReadTemperature();        val <<= 16;        val >>= 16;   // 扩展符号位        printf("Temperature is ");        if (val < 0)        {            printf("-");            val = -val;        }        fval = val >> 4; // 整数        fval += (val & 0x000F) * 0.0625; // 小数        printf("%f \n",fval);        sleep(1);    }    close(fd);    return 0;}


[解决办法]
#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/types.h>

float change_to_temperature(char *temperature);

int main(int argc, char *argv[])
{
int fd;
int i = 10;
char temperature[2];
if((fd = open("/dev/18b20_driver", O_RDONLY)) < 0)
printf("open 18b20_driver file error!\n");


while(i--){
read(fd,temperature ,sizeof(temperature));
printf("temperature is: %f\n",change_to_temperature(temperature));
sleep(1);
}

return 0;
}

float change_to_temperature(char *temperature)
{
int tmp = 0;
tmp = (int)temperature[1] << 8;
tmp |= temperature[0];
return tmp * 0.0625;
}

热点排行