搜索
bottom↓
回复: 0

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

[复制链接]

出0入0汤圆

发表于 2010-3-11 21:00:38 | 显示全部楼层 |阅读模式
我在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 char  u_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[2];

/*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[2];
                u_int16 word;       
        }temp;
        */
        data[0] = 0;
        data[1] = 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[0] = %d\n", data[0]);
        /*读取低字节*/
        data[0] = ds18b20_read_byte();
#ifdef         _DS18B20_DEBUG_
//        printk(KERN_INFO"temp.data[0] = %d\n", temp.data[0]);
#endif
        /*读取高字节*/
        data[1] = ds18b20_read_byte();
#ifdef         _DS18B20_DEBUG_
//        printk(KERN_INFO"temp.data[1] = %d\n", temp.data[1]);
#endif

#ifdef         _DS18B20_DEBUG_
//        temp.word >>= 4;
//        printk(KERN_INFO"temperture.word = %d\n", temp.word);
//        printk(KERN_INFO"temp.data[0] = %d\n", temp.data[0]);
//        printk(KERN_INFO"temp.data[1] = %d\n", temp.data[0]);
#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[0] = data[0];
        buf[1] = data[1];

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 02:16

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表