主题 : 哎呀,ds18b20 驱动失败 复制链接 | 浏览器收藏 | 打印
级别: 侠客
UID: 9105
精华: 0
发帖: 95
金钱: 755 两
威望: 307 点
综合积分: 190 分
注册时间: 2009-09-17
最后登录: 2017-09-13
楼主  发表于: 2011-02-21 22:30

 哎呀,ds18b20 驱动失败

程序网上参考的,也看了datasheet没有问题啊。

可是到这里

  while(Read_DS()==0)
    {
        printk(DEVICE_NAME " Convert....\n");
        msdelay(50);
        err++;
        if(err==10)
        {
            printk(DEVICE_NAME " Convert fail\n");
            return -1;
        }

    }
就过不去了。

老是转换失败。



#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "DS18B20"
#define DS18B20_MAJOR 250       //这里要确定自己的这个主设备号 mknod /dev/DS18B20 c 250 0
#define DS_PIN S3C2410_GPB1     //这可以找一个自己方便的管脚,只要是引出的GPIO都可以
#define OUT S3C2410_GPB1_OUTP   //设置成输出端口
#define IN S3C2410_GPB1_INP     //设置成输入端口
#define DIS_UP 1
#define EN_UP 0
#define Search 0x00F0           //好型没怎么用啊!!
#define Read_ROM 0x0033         //just for one
#define Skip_ROM 0x00CC         //跳rom的时序
#define Convert 0x0044          //ds18b20的固定时序,管脚识别到该信号开始对测到的温度进行转换
#define Write 0x004E            //TH---TL---Config
#define Read 0x00BE             //ds18b20的固定时序,管脚识别到该信号时开始从外界获取温度

#define bit_9 0x001F
#define bit_10 0x003F
#define bit_11 0x005F
#define bit_12 0x007F

#define uint16 unsigned int

//unsigned int ROM_DATA[8];

void usdelay(unsigned int i)    //延时 i us 对于不同系统可能会有所差别,请适当修改
{
    unsigned int j;
    for(i=i;i>0;i--)
        for(j=90;j>0;j--);
}

void msdelay(unsigned int i)    //延时 i us
{
    for(i=i;i>0;i--)
        usdelay(1000);
}

void SetL(void)
{
    s3c2410_gpio_cfgpin(DS_PIN,OUT);
    s3c2410_gpio_setpin(DS_PIN,0);
}

void SetH(void)
{
    s3c2410_gpio_cfgpin(DS_PIN,OUT);
    s3c2410_gpio_setpin(DS_PIN,1);
}

unsigned int Read_DS(void)
{
    unsigned int i;
    s3c2410_gpio_cfgpin(DS_PIN,IN);
    s3c2410_gpio_pullup(DS_PIN,EN_UP);
    __asm("nop");
    __asm("nop");
    __asm("nop");
    i=s3c2410_gpio_getpin(DS_PIN);
    if(i!=0)
        i=1;
    return i;

}

unsigned int ds_start(void) //初始化ds18b20
{
    unsigned int flag=1;
    int err=0;
      /*
    During the initialization sequence the bus master transmits (TX) the reset pulse by pulling the 1-Wire bus low for a minimum of 480us.
    The bus master then releases the bus and goes into receive mode (RX).  
    When the bus is released, the 5k pullup resistor pulls the 1-Wire bus high.
    When the DS18B20 detects  this rising edge, it waits 15us to 60us and then transmits a presence pulse by pulling the 1-Wire bus low for 60us to 240us.
    */

    SetH();
    usdelay(2);
    SetL();
    usdelay(600);            //560延时要大于480u
    SetH();
    usdelay(1);             //稍作延时

    while(Read_DS()!=0)     //ds18B20初始化成功会返回一个低电平,此时跳出循环,执行下面的操作
    {
        printk(DEVICE_NAME " Wait....\n");
        usdelay(5);
        err++;                 //扫描最多次数.
        if(err==20)
        {
            printk(DEVICE_NAME " Start fail\n");
            return -1;
        }
    }

    printk(DEVICE_NAME " Start sucess\n");
    flag=0;
    SetH();                    //初始化成功后赋为高电平准备从外界读入温度
    usdelay(400);
    return flag;
}

void ds_send(unsigned int uidata)    //发送一个字节数据
{
    unsigned int i;
    printk("The send data is %d\n",uidata);
    for(i=0;i<8;i++)
    {
    /*
    Both types of write time slots are initiated by the master pulling the 1-Wire bus low.
    To generate a Write 1 time slot, after pulling the 1-Wire bus low,
    the bus master must release the 1-Wire bus within 15us. When the bus is released, the 5k pullup resistor will pull the bus high.                                        
    To generate a Write 0 time slot, after pulling the 1-Wire bus low,
    the bus master must continue to hold the bus low for the duration of the time slot (at least 60us).
    */
        SetL();
        usdelay(3);
        if((uidata&1)!=0)    //写1
        {
            SetH();
            usdelay(80);    //保持高电平60us
        }
        else
        {
            usdelay(80);    //写低电平直接保持
            SetH();
        }
        uidata>>=1;
    }

}

unsigned int ds_read(void)    //接收一个字节数据
{
    unsigned int uidata=0;
    unsigned int i;
    for(i=0;i<8;i++)
    {
        SetL();
        /*
        A read time slot is initiated by the master device pulling the 1-Wire bus low for a minimum of 1us and then releasing the bus
        */
        usdelay(2);                 //2 3 保持至少1us
//        s3c2410_gpio_setpin(DS_PIN,1);          //放1
//      s3c2410_gpio_cfgpin(DS_PIN,IN);         //设置为输入
        SetH();
        /*
         Output data from the DS18B20 is valid for 15us after the falling edge that initiated the read time slot.
        */
        usdelay(7);                 //1 2 3 4 5(e)
        if(Read_DS()==1)
            uidata+=0x0100;  
        uidata>>=1;  
        /*
        All read time slots must be a minimum of 60us in duration with a minimum of a 1us recovery time between slots.
        */
        usdelay(65);                //延时60us,满足读时隙的时间长度要求
        SetH();                        //释放总线
    }
    printk("--- The recieve data is %d\n",uidata);
    return uidata;
}

void ds_init(unsigned int TH,unsigned int TL,unsigned int bit_nmb)
{

    SetH();
    usdelay(80);
    if(ds_start()==0)            //初始化成功
    {
        ds_send(Skip_ROM);      //复位
        ds_send(Write);         //跳过ROM匹配,报警设定
        ds_send(TH);            //TH
        ds_send(TL);            //TL
        ds_send(bit_nmb);         //转换位数
    }
}

unsigned int read_tem(void)
{
    unsigned int th,tl;
    int err=0;
    ds_init(100,0,bit_12);
    th=tl=0;
    if(ds_start() != 0)
    {
        return -1;
    }
    ds_send(Skip_ROM);
    ds_send(Convert);
    msdelay(50);

    while(Read_DS()==0)
    {
        printk(DEVICE_NAME " Convert....\n");
        msdelay(50);
        err++;
        if(err==10)
        {
            printk(DEVICE_NAME " Convert fail\n");
            return -1;
        }

    }

    if(ds_start() != 0)
    {
        return -1;
    }
    ds_send(Skip_ROM);
    ds_send(Read);
    tl=ds_read();
    th=ds_read();
    
    th<<=8;
    tl|=th;

    printk("the th data is %d\n",th);
    printk("the tl data is %d\n",tl);
    printk("read_tmp success\n");
    return tl;
}

static int ds18b20_ioctl(
        struct inode *inode,
        struct file *file,
        unsigned int cmd,unsigned long arg)
{
    return 0;
}

static ssize_t ds18b20_read(struct file *pFile, uint16 __user *pData, size_t count, loff_t *off )
{
    uint16 tmp,ret;
    tmp =read_tem();
    ret=copy_to_user(pData, &tmp, sizeof(tmp)); //将读取得的DS18B20数值复制到用户区
    if(ret>0)
    {
        printk("copy data failed\n");
        return -1;
    }
    return 0;
}

static struct file_operations ds18b20_fops = {

    .owner = THIS_MODULE,
    .ioctl = ds18b20_ioctl,
    .read = ds18b20_read,

};

static int __init ds18b20_init(void)

{
    int ret;
    ret = register_chrdev(DS18B20_MAJOR, DEVICE_NAME, &ds18b20_fops);
    if (ret < 0) {
        printk(DEVICE_NAME " can't register major number\n");
        return ret;
    }

    s3c2410_gpio_cfgpin(DS_PIN, OUT);
    s3c2410_gpio_setpin(DS_PIN, 1);
    printk(DEVICE_NAME " initialized\n");
    printk("<0>""initialized\n");

    return 0;
}

static void __exit ds18b20_exit(void)
{
    unregister_chrdev(DS18B20_MAJOR, DEVICE_NAME);
    printk(DEVICE_NAME " rmmodule\n");
}

module_init(ds18b20_init);
module_exit(ds18b20_exit);
MODULE_AUTHOR("benjamin_xc@163.com"); // 驱动程序的作者
MODULE_DESCRIPTION("DS18B20 Driver"); // 一些描述信息
MODULE_LICENSE("GPL");
专注于嵌入式&Linux
级别: 骑士
UID: 12802
精华: 3
发帖: 237
金钱: 1355 两
威望: 271 点
综合积分: 534 分
注册时间: 2010-01-13
最后登录: 2014-03-18
1楼  发表于: 2011-02-21 23:13
期待LZ成功
级别: 侠客
UID: 9105
精华: 0
发帖: 95
金钱: 755 两
威望: 307 点
综合积分: 190 分
注册时间: 2009-09-17
最后登录: 2017-09-13
2楼  发表于: 2011-02-22 21:09

 回 1楼(lknlfy) 的帖子

好的, 谢谢
级别: 新手上路
UID: 35323
精华: 0
发帖: 25
金钱: 135 两
威望: 27 点
综合积分: 50 分
注册时间: 2010-12-30
最后登录: 2017-09-13
3楼  发表于: 2011-02-23 14:15
已经移植好了的,看附件

DS18B20_linux驱动.rar (806 K) 下载次数:211
级别: 侠客
UID: 9105
精华: 0
发帖: 95
金钱: 755 两
威望: 307 点
综合积分: 190 分
注册时间: 2009-09-17
最后登录: 2017-09-13
4楼  发表于: 2011-02-23 22:11

 回 3楼(lsc123456) 的帖子

先谢谢 再下载。
级别: 侠客
UID: 9105
精华: 0
发帖: 95
金钱: 755 两
威望: 307 点
综合积分: 190 分
注册时间: 2009-09-17
最后登录: 2017-09-13
5楼  发表于: 2011-02-23 23:07
唉 还是不行,把光脚从 GPB1-GPF0 初始化都失败 郁闷,代码看了一百遍了             
级别: 侠客
UID: 9105
精华: 0
发帖: 95
金钱: 755 两
威望: 307 点
综合积分: 190 分
注册时间: 2009-09-17
最后登录: 2017-09-13
6楼  发表于: 2011-02-23 23:24
是不是管教被占用了


悲摧呀


<4>The send data is 68
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Wait....
<4>DS18B20 Start fail
the currently temperature is 268435456.000000
级别: 侠客
UID: 9105
精华: 0
发帖: 95
金钱: 755 两
威望: 307 点
综合积分: 190 分
注册时间: 2009-09-17
最后登录: 2017-09-13
7楼  发表于: 2011-02-24 22:08
好了 程序的问题。。。要不要贴个呢。。。
级别: 新手上路
UID: 36297
精华: 0
发帖: 1
金钱: 5 两
威望: 1 点
综合积分: 2 分
注册时间: 2011-01-14
最后登录: 2017-09-13
8楼  发表于: 2011-06-04 09:24
请问楼主,我也遇到了这样的问题,请问是程序问题吗,请赐教!!!
有容乃大,无欲则刚
级别: 新手上路
UID: 54819
精华: 0
发帖: 9
金钱: 45 两
威望: 9 点
综合积分: 18 分
注册时间: 2011-09-06
最后登录: 2012-04-20
9楼  发表于: 2011-09-06 18:44
学习了,正在调试
有容乃大,无欲则刚