Chinaunix首页 | 论坛 | 博客
  • 博客访问: 383209
  • 博文数量: 149
  • 博客积分: 25
  • 博客等级: 民兵
  • 技术积分: 220
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-27 14:53
文章分类

全部博文(149)

文章存档

2016年(3)

2015年(2)

2014年(144)

我的朋友

分类: 嵌入式

2014-09-07 21:43:29

试验过,能正常读取温度。
驱动程序如下:
//*********************************************************
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef unsigned char BYTE;

#define DS18B20_PIN   S3C2410_GPG14
#define DS18B20_PIN_OUTP S3C2410_GPG14_OUTP
#define DS18B20_PIN_INP   S3C2410_GPG14_INP
#define HIGH 1
#define LOW 0
#define DEV_NAME "DS18B20"
#define DEV_MAJOR 232
static BYTE data[2];
BYTE DS18b20_reset (void) 
    // 配置GPIOB0输出模式 
    s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP); 
     
    // 向18B20发送一个上升沿,并保持高电平状态约100微秒 
    s3c2410_gpio_setpin(DS18B20_PIN, HIGH); 
    udelay(100); 
     
    // 向18B20发送一个下降沿,并保持低电平状态约600微秒 
    s3c2410_gpio_setpin(DS18B20_PIN, LOW); 
    udelay(600); 
     
    // 向18B20发送一个上升沿,此时可释放DS18B20总线 
    s3c2410_gpio_setpin(DS18B20_PIN, HIGH); 
    udelay(100); 
     
    // 以上动作是给DS18B20一个复位脉冲 
    // 通过再次配置GPIOB1引脚成输入状态,可以检测到DS18B20是否复位成功 
    s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP); 
     
    // 若总线在释放后总线状态为高电平,则复位失败 
    if(s3c2410_gpio_getpin(DS18B20_PIN)){ printk("DS18b20 reset failed.\r\n"); return 1;} 

    return 0; 
}  


void DS18b20_write_byte (BYTE byte) 
    BYTE i; 
    // 配置GPIOB1为输出模式 
    s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP); 

    // 写“1”时隙: 
    //     保持总线在低电平1微秒到15微秒之间 
    //     然后再保持总线在高电平15微秒到60微秒之间 
    //     理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平 
    // 
    // 写“0”时隙: 
    //     保持总线在低电平15微秒到60微秒之间 
    //     然后再保持总线在高电平1微秒到15微秒之间 
    //     理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平 
    for (i = 0; i < 8; i++) 
    { 
        s3c2410_gpio_setpin(DS18B20_PIN, LOW); udelay(1); 
        if(byte & HIGH) 
        { 
             // 若byte变量的D0位是1,则需向总线上写“1” 
             // 根据写“1”时隙规则,电平在此处翻转为高 
             s3c2410_gpio_setpin(DS18B20_PIN, HIGH); 
        } 
        else  
        { 
             // 若byte变量的D0位是0,则需向总线上写“0” 
             // 根据写“0”时隙规则,电平在保持为低 
             // s3c2410_gpio_setpin(DS18B20_PIN, LOW); 
        } 
        // 电平状态保持60微秒 
        udelay(60); 

        s3c2410_gpio_setpin(DS18B20_PIN, HIGH); 
        udelay(15); 

        byte >>= 1; 
    } 
    s3c2410_gpio_setpin(DS18B20_PIN, HIGH); 
}  

BYTE DS18b20_read_byte (void) 
    BYTE i = 0; 
    BYTE byte = 0; 
    // 读“1”时隙: 
    //     若总线状态保持在低电平状态1微秒到15微秒之间 
    //     然后跳变到高电平状态且保持在15微秒到60微秒之间 
    //      就认为从DS18B20读到一个“1”信号 
    //     理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平 
    // 
    // 读“0”时隙: 
    //     若总线状态保持在低电平状态15微秒到30微秒之间 
    //     然后跳变到高电平状态且保持在15微秒到60微秒之间 
    //     就认为从DS18B20读到一个“0”信号 
    //     理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平 
    for (i = 0; i < 8; i++) 
    { 
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);  
        s3c2410_gpio_setpin(DS18B20_PIN, LOW); 

        udelay(1); 
        byte >>= 1; 

        s3c2410_gpio_setpin(DS18B20_PIN, HIGH); 
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP); 

        // 若总线在我们设它为低电平之后若1微秒之内变为高 
        // 则认为从DS18B20处收到一个“1”信号 
        // 因此把byte的D7为置“1” 
        if (s3c2410_gpio_getpin(DS18B20_PIN)) byte |= 0x80; 
        udelay(60); 
    } 
    return byte;        

void DS18b20_proc(void)          
    while(DS18b20_reset()); 
     
    udelay(120); 
     
    DS18b20_write_byte(0xcc); 
    DS18b20_write_byte(0x44); 
     
    udelay(5); 
     
    while(DS18b20_reset()); 
    udelay(200); 
     
    DS18b20_write_byte(0xcc); 
    DS18b20_write_byte(0xbe); 
     
    data[0] = DS18b20_read_byte(); 
    data[1] = DS18b20_read_byte(); 
}  

static ssize_t s3c2440_18b20_read(struct file *filp, 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_18b20_fops =  
    .owner = THIS_MODULE, 
    .read = s3c2440_18b20_read, 
}; 

static int __init s3c2440_18b20_init(void) 
    if (register_chrdev(DEV_MAJOR, DEV_NAME, &s3c2440_18b20_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); 
     
    while(DS18b20_reset());    

static void __exit s3c2440_18b20_exit(void) 
    //devfs_remove(DEV_NAME); 
    unregister_chrdev(DEV_MAJOR, DEV_NAME); 
module_init(s3c2440_18b20_init); 
module_exit(s3c2440_18b20_exit); 
//**********************************************************
//驱动程序结束

测试程序如下:#include "stdio.h" 
#include "sys/types.h" 
#include "sys/ioctl.h" 
#include "stdlib.h" 
#include "termios.h" 
#include "sys/stat.h" 
#include "fcntl.h" 
#include "sys/time.h" 

main() 
    int fd; 
    unsigned char buf[2]; 
    unsigned short temp=0; 
double result=0; 
int flag=0; 

    if ((fd=open("/dev/DS18B20",O_RDWR | O_NDELAY | O_NOCTTY)) < 0) 
    { 
        printf("Open Device DS18B20 failed.\r\n"); 
        exit(1); 
    } 
    else 
    { 
        printf("Open Device DS18B20 successed.\r\n"); 
        while(1) 
        { 
            read(fd, buf, 1); 
printf("read data is 0x%02X-0x%02X\n",buf[1],buf[0]); 
            temp=((unsigned short)buf[1])<<8; 
temp|=(unsigned short)buf[0]; 
printf("no error here\n"); 
result=0.0625*((double)temp); 
printf("%f \r\n", result); 
            sleep(1); 
        } 
        close(fd); 
    } 

//测试程序结束
//******************************************************************

//测试程序的Makfile编写如下:
CROSS=arm-linux-

all: test_ds18b20

test_ds18b20: test_ds18b20.c
        $(CROSS)gcc -o test_ds18b20 test_ds18b20.c
        $(CROSS)strip test_ds18b20
clean:
        @rm -vf test_ds18b20 *.o *~
~                                                                            
~                                                                            
~                                  


//*******************************************************************
测试程序命名为:test_ds18b20.c
编译方法:驱动放到内核的driver/char下面,修改driver/char的Kconfig和Makefile文件,驱动名字命名为:DS18B20.c
在Kconfig下添加 
config DS18B20
        tristate "qianlong_DS18B20"
        depends on ARCH_S3C2440
        help
          Qianlong DS18B20

在Makefile中添加 
obj-$(CONFIG_DS18B20)           += DS18B20.o
DS18B20就是驱动的名字

测试时先insmod DS18B20.ko
mknod /dev/DS18B20 c 232 0 
./test1820 



示例图片:
阅读(1099) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~