rnmrnm 发表于 2010-3-11 21:00:38

求助:arm linux下DS18b20驱动的复位问题

我在S3C2440平台上的Linux系统(2.6内核)下做了一个温度传感器DS18B20的驱动,但是复位不成功,我自己看了好多遍时序图,就是不能找到出问题的地方
请大家帮我看看,到底是什么问题
/*
*文件名字:qq2440_ds18b20.c
*功能描述:数字传感器ds18b20在linux下的驱动程序
*时间:2010-3-5
*版本:v1.0
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/devfs_fs_kernel.h>

#define DEV_NAME        "DS18B20"
#define DEV_MAJOR        236
#define DS18B20_PIN   S3C2410_GPB1
#define DS18B20_PIN_INP S3C2410_GPB1_INP
#define DS18B20_PIN_OUTP S3C2410_GPB1_OUTP

#define SKIP_ROM        0xCC
#define READ_ROM        0X33
#define CONVERT_T        0X44
#define READ_SCRATCHPAD        0XBE

#define HIGH        1
#define LOW                0

#define _DS18B20_DEBUG_
typedef unsigned charu_int8;        /*一个字节*/
typedef unsigned int   u_int32;        /*4个字节*/
typedef unsigned short int u_int16;        /*2个字节*/
typedef int int32;                                /*4个字节*/
typedef char int8;                                /*1个字节*/

u_int8 data;

/*DS18B20复位函数*/
/*复位成功\返回1,否则返回0*/
int32 ds18b20_reset(void)
{
        u_int8 i = 0;
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
        s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
        udelay(100);
        s3c2410_gpio_setpin(DS18B20_PIN, LOW);
        /*delay time 480us~960us*/
        udelay(500);
        /*向DS18B20发送一个上升沿,释放总线*/
        s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
        s3c2410_gpio_setpin(DS18B20_PIN, LOW);
        /*wait time 15~60us*/
//udelay(80);
        udelay(20);
//         s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
        /*如果复位成功,将产生60~240us的低电平*/
        while (s3c2410_gpio_getpin(DS18B20_PIN))   {
                if(++i > 30)        {
              printk("DS18B20 reset failed.\r\n");
              return 0;
                }
   }
#ifdef         _DS18B20_DEBUG_
                printk("DS18B20 reset success!\n");
#endif
        /*DS18B20发送存在脉冲60~240us*/
//        udelay(240);
        udelay(100);
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
        s3c2410_gpio_setpin(DS18B20_PIN, HIGH);   
        return 1;
}

/*S3C2440 send data to DS18B20*/
/*写一个字节*/
void ds18b20_write_byte(u_int8 data)
{
        u_int8 i;
   /*
        *各个写周期之间必须有1us的恢复时间
        *每个周期保持60us
        *
        *写1时:
        *保持总线低电平1us~15us之间
        *然后保持总线在高电平至少在15us~60us之间
        *
        *写0时:
        *保持总线低电平至少60us
        *然后保持总线在高电平至少1us
        */
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
        s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
        udelay(1);
        for (i = 0; i < 8; i++){
                s3c2410_gpio_setpin(DS18B20_PIN, LOW);
                /*数据先写低位,再写高位*/
      if (data & (1 << i)) {
                      s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
//                       udelay(16); //15+1
          }
                else{
                  s3c2410_gpio_setpin(DS18B20_PIN, LOW);
//                udelaydd(2);//1+1
            }
        udelay(60);
        s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
        udelay(1);
        /*数据先写低位,再写高位*/
    }       
        s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
}

/*S3C2440 recevie data from DB18B20*/
/*读一个字节*/
int32 ds18b20_read_byte(void)
{
        u_int8 i = 0;
        u_int8 rbyte = 0;
   /*
        *总线从高电平拉低后,保持至少1us
//*总线在低电平时保持1us~15us
        *然后跳到高电平状且保持15us~60us之间
        *若总线在我们设它为高电平后在1s内变为低电平,认为读到了0信号
        *如果总线不变则认为读到了1信号
        */
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
        for (i = 0; i < 8; i++){       
                s3c2410_gpio_setpin(DS18B20_PIN, LOW);
                udelay(1);
                s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
                s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
//                s3c2410_gpio_setpin(DS18B20_PIN, LOW);
                /*DS18B20从读时间片产生后的15us输出的数据有效*/
                udelay(4);
//                udelay(10);
                if (s3c2410_gpio_getpin(DS18B20_PIN))
                           rbyte |= (1 << i);
                else
            rbyte &= ~(1 << i);
                /*等待读一个读时间周期完*/
                udelay(60);
                s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);

   }
        return rbyte;
}

/*温度读取过程*/       
int32 ds18b20_proc(void)
{
        u_int8 i = 0;
        /*
        union
        {
                u_int8 byte;
                u_int16 word;       
        }temp;
        */
        data = 0;
        data = 0;

        while (!ds18b20_reset())
        {
                if (++i > 5)        {
#ifdef         _DS18B20_DEBUG_
                        printk("ds18b20_proc error!\n");
#endif
                        return 0;
                }
        }
        udelay(120);
        /*跳过读时序操作*/
        ds18b20_write_byte(SKIP_ROM);
        /*启动温度测量*/
        ds18b20_write_byte(CONVERT_T);
        udelay(5);
//        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
//        while (!s3c2410_gpio_getpin(DS18B20_PIN));
//        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);

        while (!ds18b20_reset())
        {
                if (++i > 5)        {
#ifdef        _DS18B20_DEBUG_
                        printk("ds18b20_proc error!\n");
#endif
                        return 0;
                }
        }
        udelay(200);
        ds18b20_write_byte(SKIP_ROM);
        /*读取温度寄存器*/
        ds18b20_write_byte(READ_SCRATCHPAD);

        printk(KERN_INFO"data = %d\n", data);
        /*读取低字节*/
        data = ds18b20_read_byte();
#ifdef         _DS18B20_DEBUG_
//        printk(KERN_INFO"temp.data = %d\n", temp.data);
#endif
        /*读取高字节*/
        data = ds18b20_read_byte();
#ifdef         _DS18B20_DEBUG_
//        printk(KERN_INFO"temp.data = %d\n", temp.data);
#endif

#ifdef         _DS18B20_DEBUG_
//        temp.word >>= 4;
//        printk(KERN_INFO"temperture.word = %d\n", temp.word);
//        printk(KERN_INFO"temp.data = %d\n", temp.data);
//        printk(KERN_INFO"temp.data = %d\n", temp.data);
#endif
        return 1;
}

/*
static int s3c2440_ds18b20_open(struct inode *inode, struct file *file)
{
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
        temp.word = 0;
//        return 1;
}
*/

static ssize_t s3c2440_ds18b20_read(struct file *file, char *buf, size_t len, loff_t *off)
{
        ds18b20_proc();
        buf = data;
        buf = data;

        return 1;
}

static struct file_operations s3c2440_ds18b20_fops = {
        .owner = THIS_MODULE,
        .read = s3c2440_ds18b20_read,
};

static int __init s3c2440_ds18b20_init(void)
{
        /*注册设备号,指定驱动入口指针*/
        if (register_chrdev(DEV_MAJOR, DEV_NAME, &s3c2440_ds18b20_fops) < 0)
    {
                printk(DEV_NAME":Register major failed.\r\n");   
                return-1;
   }
        devfs_mk_cdev(MKDEV(DEV_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,DEV_NAME);

#ifdef _DS18B20_DEBUG_
        printk("DS18B20 init succed!\r\n");
#endif
        return 0;
}

static void __exit s3c2440_ds18b20_exit(void)
{
        devfs_remove(DEV_NAME);
        unregister_chrdev(DEV_MAJOR, DEV_NAME);
}

module_init(s3c2440_ds18b20_init);
module_exit(s3c2440_ds18b20_exit);
页: [1]
查看完整版本: 求助:arm linux下DS18b20驱动的复位问题