第27章 DS18B20温度传感器

来源:互联网 发布:网络传播负面消息方法 编辑:程序博客网 时间:2024/05/21 08:55

27.1硬件原理

下图是我们温度传感器的接入引脚,3.3V 供电,io 口接 P13 的 GP0( GPIO0 的简称 )。
DS18B20 数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有 LTM8877,LTM8874 等等。主要根据应用场合的不同而改变其外观。封装后的 DS18B20 可用于电缆沟测温,高炉水循环测温,锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种非极限温度场合。耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。

27.2单总线的概念

目前常用的微机与外设之间进行数据传输的串行总线主要有 I2C 总线、 SPI 总线和 SCI总线。其中 I2C 总线以同步串行 2 线方式进行通信(一条时钟线,一条数据线) ,SPI 总线则以同步串行 3 线方式进行通信(一条时钟线,一条数据输入线,一条数据输出线),而 SCI 总线是以异步方式进行通信(一条数据输入线,一条数据输出线) 。这些总线至少需要两条或两条以上的信号线。
1-wire , 即 单 线 总 线 , 又 叫 单 总 线 。 近 年 来 , 美 国 的 达 拉 斯 半 导 体 公 司(DALLASSEMICONDUCTOR) 推出了一项特有的单总线(1-Wire Bus)技术。该技术与上述总线不同,它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的,因而这种单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等优点。

27.3 ds18b20 相关时序

 初始化(复位)时序图:

这里写图片描述

图1复位时序

(1) 先将数据线置高电平“ 1” 。
(2) 延时(该时间要求的不是很严格,但是尽可能的短一点)
(3) 数据线拉到低电平“ 0” 。
(4) 延时 750 微秒(该时间的时间范围可以从 480 到 960 微秒) 。
(5) 数据线拉到高电平“ 1” 。
(6) 延时等待(如果初始化成功则在 15 到 60 微秒时间之内产生一个由 DS18B20 所
返回的低电平“ 0” 。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制) 。
(7) 若 CPU 读到了数据线上的低电平“ 0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要 480 微秒。
(8) 将数据线再次拉高到高电平“ 1”后结束。

 写 ds18b20 时序图:

这里写图片描述

图2 写时序

(1) 数据线先置低电平“ 0” 。
(2) 延时确定的时间为 15 微秒。
(3) 按从低位到高位的顺序发送字节(一次只发送一位) 。
(4) 延时时间为 45 微秒。
(5) 将数据线拉到高电平。
(6) 重复上(1)到(6)的操作直到所有的字节全部发送完为止。
(7) 最后将数据线拉高。
 读 ds18b20 时序图:
这里写图片描述

图3写时序

(1)将数据线拉高“ 1” 。
(2)延时 2 微秒。
(3)将数据线拉低“ 0” 。
(4)延时 3 微秒。
(5)将数据线拉高“ 1” 。
(6)延时 5 微秒。
(7)读数据线的状态得到 1 个状态位,并进行数据处理。
(8)延时 60 微秒。

27.4驱动程序

关于字符设备驱动程序的使用,我们可以参照点亮 led 灯的那个实验,这里只给出跟ds18b20 密切相关的驱动程序,详细的程序请查看我们的驱动文件!

//配置连接温度传感器的引脚#define DS18B20_L       *GPIO21_0_DATA &= ~(1<<0)  //低电平   #define DS18B20_H       *GPIO21_0_DATA |=  (1<<0)  //高电平#define DS18B20_OUT         *GPIO21_0_DIR  |=  (1<<0)  //输出 #define DS18B20_IN      *GPIO21_0_DIR  &= ~(1<<0)  //输入    #define DS18B20_STA     *GPIO21_0_DATA & 0x01   //寄存器定义volatile unsigned long *GPIO21_0_DIR;volatile unsigned long *GPIO21_0_DATA;  /****************  基本定义 **********************///初始化函数必要资源定义//用于初始化函数当中//device number;    dev_t dev_num;//struct dev    struct cdev ds18b20_cdev;//auto "mknode /dev/ds18b20 c dev_num minor_num"struct class *ds18b20_class = NULL;struct device *ds18b20_device = NULL;/********************  ds18b20有关的函数   ****************************///复位ds18b20传感器static unsigned char ds18b20_reset(void){    unsigned char ret = 0;    unsigned char count = 0;    DS18B20_OUT;    DS18B20_H;    udelay(100);                DS18B20_L;              udelay(600);                DS18B20_H;              udelay(45);             DS18B20_IN;             do    {        ret = DS18B20_STA;        udelay(1);                  count++;    }    while(ret != 0 && count<50);    DS18B20_OUT;    udelay(400);                DS18B20_H;              return ret;}//从ds18b20读取一个字节static unsigned char read_byte(void){    unsigned char i,byte=0;    DS18B20_OUT;    DS18B20_H;    udelay(100);    for(i = 0; i<8; i++)    {        byte >>= 1;        DS18B20_L;        udelay(4);        DS18B20_H;        udelay(2);        if(DS18B20_STA == 1)            byte |= 0x80;        udelay(10);    }    return byte;}//向ds18b20写入一个字节static unsigned char write_byte(unsigned char byte){    unsigned char i;    DS18B20_OUT;    DS18B20_H;    udelay(100);    for(i = 0; i<8; i++)    {        DS18B20_L;        if( byte & 0x01 )            DS18B20_H;        else            DS18B20_L;        udelay(40);        DS18B20_H;        byte >>= 1;    }    udelay(10);}//从ds18b20中读出温度数据static unsigned int read_temp(void){    unsigned int t = 0 , l = 0;    if(ds18b20_reset())    {        printk("step1,reset_ds18b20 error!\n");        return 0;    }    write_byte(0xcc);    write_byte(0x44);    udelay(4);    if(ds18b20_reset())    {        printk("step2,reset_ds18b20 error!\n");        return 0;    }    write_byte(0xcc);    write_byte(0xbe);    l = read_byte();    t = read_byte();    t <<= 8;    t += l;    return t;}/**********************************************************************//**************** 结构体 file_operations 成员函数 *****************///openstatic int ds18b20_open(struct inode *inode, struct file *file){    printk("ds18b20 drive open...\n");    DS18B20_OUT; //初始化该引脚为输出;    return 0;}//closestatic int ds18b20_close(struct inode *inode , struct file *file){    return 0;}//readstatic ssize_t ds18b20_read(struct file *file, char __user *buffer,            size_t len, loff_t *pos){    unsigned int temp;    printk("ds18b20 drive read...\n");    temp = read_temp();    copy_to_user(buffer, &temp, 4);    return 4;}/***************** 结构体: file_operations ************************///structstatic const struct file_operations ds18b20_fops = {    .owner   = THIS_MODULE,    .open    = ds18b20_open,    .release = ds18b20_close,       .read    = ds18b20_read,};/*************  functions: init , exit*******************///条件值变量,用于指示资源是否正常使用unsigned char init_flag = 0;unsigned char add_code_flag = 0;//initstatic __init int ds18b20_init(void){    int ret_v = 0;    printk("ds18b20 drive init...\n");    //函数alloc_chrdev_region主要参数说明:    //参数2: 次设备号    //参数3: 创建多少个设备    if( ( ret_v = alloc_chrdev_region(&dev_num,0,1,"ds18b20") ) < 0 )    {        goto dev_reg_error;    }    init_flag = 1; //标示设备创建成功;    printk("The drive info of ds18b20:\nmajor: %d\nminor: %d\n",        MAJOR(dev_num),MINOR(dev_num));    cdev_init(&ds18b20_cdev,&ds18b20_fops);    if( (ret_v = cdev_add(&ds18b20_cdev,dev_num,1)) != 0 )    {        goto cdev_add_error;    }    ds18b20_class = class_create(THIS_MODULE,"ds18b20");    if( IS_ERR(ds18b20_class) )    {        goto class_c_error;    }    ds18b20_device = device_create(ds18b20_class,NULL,dev_num,NULL,"ds18b20");    if( IS_ERR(ds18b20_device) )    {        goto device_c_error;    }    printk("auto mknod success!\n");    //------------   请在此添加您的初始化程序  --------------//    GPIO21_0_DATA = (volatile unsigned long *)ioremap(0x10000620, 4);    GPIO21_0_DIR =  (volatile unsigned long *)ioremap(0x10000624, 4);        //如果需要做错误处理,请:goto ds18b20_error;        add_code_flag = 1;    //----------------------  END  ---------------------------//     goto init_success;dev_reg_error:    printk("alloc_chrdev_region failed\n");     return ret_v;cdev_add_error:    printk("cdev_add failed\n");    unregister_chrdev_region(dev_num, 1);    init_flag = 0;    return ret_v;class_c_error:    printk("class_create failed\n");    cdev_del(&ds18b20_cdev);    unregister_chrdev_region(dev_num, 1);    init_flag = 0;    return PTR_ERR(ds18b20_class);device_c_error:    printk("device_create failed\n");    cdev_del(&ds18b20_cdev);    unregister_chrdev_region(dev_num, 1);    class_destroy(ds18b20_class);    init_flag = 0;    return PTR_ERR(ds18b20_device);//------------------ 请在此添加您的错误处理内容 ----------------//ds18b20_error:    add_code_flag = 0;    return -1;//--------------------          END         -------------------//init_success:    printk("ds18b20 init success!\n");    return 0;}//exitstatic __exit void ds18b20_exit(void){    printk("ds18b20 drive exit...\n");      if(add_code_flag == 1)    {              //----------   请在这里释放您的程序占有的资源   ---------//        printk("free your resources...\n");                        iounmap(GPIO21_0_DATA);        iounmap(GPIO21_0_DIR);        printk("free finish\n");                               //----------------------     END      -------------------//    }                                   if(init_flag == 1)    {        //释放初始化使用到的资源;        cdev_del(&ds18b20_cdev);        unregister_chrdev_region(dev_num, 1);        device_unregister(ds18b20_device);        class_destroy(ds18b20_class);    }}/**************** module operations**********************///module loadingmodule_init(ds18b20_init);module_exit(ds18b20_exit);//some infomationMODULE_LICENSE("GPL v2");MODULE_AUTHOR("from Jafy");MODULE_DESCRIPTION("ds18b20 drive");27.5应用程序int main(int argc, char **argv){    int fd;    float t;    unsigned int tmp = 0;    //打开温度传感器驱动模块    fd = open("/dev/ds18b20", O_RDWR | O_NONBLOCK);    if (fd < 0)    {        printf("can't open!\n");        return -1;    }    read(fd, &tmp, sizeof(tmp));    t = tmp * 0.0625;    printf("the current temperature is %f\n",t);    close(fd);    return 0;}

编译模块驱动,不熟悉的朋友可看LED驱动相关。

make package/kernel/ds18b20/compile V=99

编译模块驱动和应用程序

make package/ds18b20_app/compile V=99make package/ds18b20_app/install V=99make package/index V=99

复制文件传给开发板测试

ald@ald888:/work/openwrt/trunk/bin/ramips/packages/base$ cpkmod-ds18b20_3.14.25-1_ramips_24kec.ipk /mnt/hgfs/share/ald@ald888:/work/openwrt/trunk/bin/ramips/packages/base$ cpds18b20_app_1_ramips_24kec.ipk /mnt/hgfs/share/

这里写图片描述

27.6实验结果

这里写图片描述

本章附件

点击进入下载

原创粉丝点击