zoukankan      html  css  js  c++  java
  • ds18b20驱动及应用程序

    ------------------------------------------------------------------------------------------------------------------------------

    交叉编译器:arm-linux-gcc-4.5.4

    Linux内核版本:Linux-3.0

    主机操作系统:Centos 6.5

    开发板:FL2440

    温度传感器:ds18b20

    ------------------------------------------------------------------------------------------------------------------------------

    之前看过led的,platform_led的,platform_button的。当时以为看懂了,可是真的拿到一个模块要去写他的驱动的时候发现有些无从下手。于是借鉴了朋友的一篇混杂设备驱动,半抄半写的写出来了一个miscdevice类型的驱动。之后又在miscdevice与led的基础上写出来了cdev类型的驱动。并附上一个小小的测试程序。

    一、miscdevice驱动

      1 #include <linux/interrupt.h>  
      2 #include <linux/poll.h>  
      3 #include <linux/configfs.h>  
      4 #include <linux/module.h>  
      5 #include <linux/kernel.h>  
      6 #include <linux/fs.h>  
      7 #include <linux/clk.h>  
      8 #include <linux/init.h>  
      9 #include <linux/device.h>  
     10 #include <linux/miscdevice.h>  
     11 #include <linux/delay.h>  
     12 #include <linux/mm.h>  
     13 #include <plat/regs-timer.h>  
     14 #include <mach/regs-gpio.h>  
     15 #include <mach/map.h>  
     16 #include <mach/gpio-nrs.h>  
     17 #include <mach/regs-irq.h>  
     18 #include <asm/io.h>  
     19 #include <mach/hardware.h>  
     20 #include <asm/uaccess.h>  
     21 #include <asm/system.h>  
     22 #include <mach/regs-clock.h>  
     23 #include <asm/irq.h>  
     24 #include <linux/types.h>  
     25 #include <linux/moduleparam.h>  
     26 #include <linux/slab.h>  
     27 #include <linux/errno.h>  
     28 #include <linux/ioctl.h>  
     29 #include <linux/cdev.h>  
     30 #include <linux/string.h>  
     31 #include <linux/list.h>  
     32 #include <linux/pci.h>  
     33 #include <asm/atomic.h>  
     34 #include <asm/unistd.h>  
     35 #include <linux/miscdevice.h>  
     36 #include <linux/gpio.h>  
     37 
     38 /*********************************************************************************
     39  *      Copyright:  (C) 2016 2013dianxin_3
     40  *                  All rights reserved.
     41  *
     42  *       Filename:  ds18b20.c
     43  *    Description:  This file 
     44  *                 
     45  *        Version:  1.0.0(08/07/2016)
     46  *         Author:  xiaohexiansheng <1392195453@qq.com>
     47  *      ChangeLog:  1, Release initial version on "08/07/2016 02:21:17 PM"
     48  *                 
     49  ********************************************************************************/
     50 #define DRV_AUTHOR                          "xiaohexiansheng <wcchz@hotmail.com>"
     51 #define DRV_DESC                            "s3c2440 ds18b20 driver"
     52 #define DEVICE_NAME                         "ds18b20"
     53 
     54 #define LOW                                 0
     55 #define HIGH                                1
     56 typedef unsigned char BYTE;  
     57 
     58 static BYTE data[2];
     59 
     60 BYTE ds18b20_reset(void)
     61 {
     62     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);         //配置GP0输出模式
     63     s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);            //向ds18b20发送一个下降沿,并保持480us
     64     udelay(480);
     65     s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);            //向ds18b20发送一个上升沿,此时可释放ds18b20总线
     66     udelay(60);
     67 
     68 //以上动作是给ds18b20一个复位脉冲,通过配置GPIO引脚为输入模式可检测ds18b20是否复位成功
     69     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
     70 //若总线在释放后为高电平,则复位失败
     71     if(s3c2410_gpio_getpin(S3C2410_GPG(0)))
     72     {
     73         printk("ds18b20 reset failed.
    ");
     74         return 1;
     75     }
     76     udelay(240);
     77     return 0;
     78 }
     79 
     80 BYTE ds18b20_read_byte(void)
     81 {
     82     BYTE i = 0;
     83     BYTE byte = 0;
     84     // 读“1”时隙:   
     85     //     若总线状态保持在低电平状态1微秒到15微秒之间   
     86     //     然后跳变到高电平状态且保持在15微秒到60微秒之间   
     87     //      就认为从DS18B20读到一个“1”信号   
     88     //     理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平   
     89     // 读“0”时隙:   
     90     //     若总线状态保持在低电平状态15微秒到30微秒之间   
     91     //     然后跳变到高电平状态且保持在15微秒到60微秒之间   
     92     //     就认为从DS18B20读到一个“0”信号   
     93     //     理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平   
     94     for(i = 0; i < 8; i++)
     95     {
     96         s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);        
     97     
     98         s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
     99         udelay(1);
    100         byte >>= 1;
    101         s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
    102         s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
    103         // 若总线在我们设它为低电平之后若1微秒之内变为高   
    104         // 则认为从DS18B20处收到一个“1”信号   
    105         // 因此把byte的D7为置“1”  
    106         if(s3c2410_gpio_getpin(S3C2410_GPG(0)))
    107             byte |= 0x80;
    108         udelay(50);
    109     }
    110     return byte;
    111 }
    112 
    113 BYTE ds18b20_write_byte(BYTE byte)
    114 {
    115     BYTE i;
    116     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);            // 配置GPG0为输出模式
    117     // 写“1”时隙:   
    118     //     保持总线在低电平1微秒到15微秒之间   
    119     //     然后再保持总线在高电平15微秒到60微秒之间   
    120     //     理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平     
    121     // 写“0”时隙:   
    122     //     保持总线在低电平15微秒到60微秒之间   
    123     //     然后再保持总线在高电平1微秒到15微秒之间   
    124     //     理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平   
    125     for(i = 0; i < 8; i++)
    126     {
    127         s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
    128         udelay(15);
    129         if(byte & HIGH)
    130         {
    131             // 若byte变量的D0位是1,则需向总线上写“1”   
    132             // 根据写“1”时隙规则,电平在此处翻转为高
    133             s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
    134         }
    135         else
    136         {
    137             // 若byte变量的D0位是0,则需向总线上写“0”   
    138             // 根据写“0”时隙规则,电平在保持为低
    139             s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
    140         }
    141         // 电平状态保持60微秒
    142         udelay(45);
    143 
    144         s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);        //释放总线
    145         udelay(1);
    146         byte >>= 1;
    147     }
    148     s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);        //释放总线
    149 }
    150 
    151 void ds18b20_proc(void)                //读取温度
    152 {
    153     while(ds18b20_reset());            //循环判断DS18B20直到复位,延时120ms;
    154     udelay(120);
    155     ds18b20_write_byte(0xcc);        //写入CCH命令,跳过读序列号过程;
    156     ds18b20_write_byte(0x44);        //写入44H命令,开始温度转换,延时5 ms;
    157     udelay(5);
    158 
    159     while(ds18b20_reset());            //循环判断DS18B20直到复位,延时200 ms;
    160     udelay(200);
    161     ds18b20_write_byte(0xcc);        //写入CCH命令,跳过读序列号过程;
    162     ds18b20_write_byte(0xbe);        //写入BEH命令,读取寄存器;
    163 
    164     data[0] = ds18b20_read_byte();            //读温度整数部分;
    165     data[1] = ds18b20_read_byte();            //读温度小数部分
    166 }
    167 
    168 static ssize_t s3c2440_ds18b20_read(struct file *filp, char *buff, size_t len, loff_t *off)
    169 {
    170     ds18b20_proc();
    171 
    172     buff[0] = data[0];
    173     buff[1] = data[1];
    174 
    175     return 1;
    176 }
    177 
    178 static struct file_operations s3c2440_ds18b20_fops =
    179 {
    180     .owner = THIS_MODULE,
    181     .read = s3c2440_ds18b20_read,
    182 };
    183 
    184 static struct miscdevice misc =
    185 {
    186     .minor = MISC_DYNAMIC_MINOR,
    187     .name = DEVICE_NAME,
    188     .fops = &s3c2440_ds18b20_fops,
    189 };
    190 
    191 static int __init s3c2440_ds18b20_init(void)
    192 {
    193     int result;
    194     result = misc_register(&misc);
    195     printk(DEVICE_NAME "initialized.
    ");
    196     
    197     while(ds18b20_reset());            
    198     return result;
    199 }
    200 
    201 static void __exit s3c2440_ds18b20_exit(void)
    202 {
    203     misc_deregister(&misc);
    204 }
    205 
    206 module_init(s3c2440_ds18b20_init);
    207 module_exit(s3c2440_ds18b20_exit);
    208 MODULE_AUTHOR(DRV_AUTHOR);
    209 MODULE_DESCRIPTION(DRV_DESC);
    210 MODULE_LICENSE("GPL");

    二、cdevdevice驱动

      1 #include <linux/module.h>
      2 #include <linux/init.h>
      3 #include <linux/kernel.h>
      4 #include <linux/fs.h>
      5 #include <linux/delay.h>
      6 #include <asm/irq.h>
      7 #include <mach/regs-gpio.h>
      8 #include <mach/hardware.h>
      9 #include <linux/cdev.h>
     10 #include <linux/device.h>
     11 #include <linux/kdev_t.h>
     12 #include <asm/uaccess.h>
     13 #include <linux/platform_device.h>
     14 #include <linux/gpio.h>
     15 
     16 /*********************************************************************************
     17  *      Copyright:  (C) 2016 2013dianxin_3
     18  *                  All rights reserved.
     19  *
     20  *       Filename:  ds18b20.c
     21  *    Description:  This file 
     22  *                 
     23  *        Version:  1.0.0(08/08/2016)
     24  *         Author:  xiaohexiansheng <1392195453@qq.com>
     25  *      ChangeLog:  1, Release initial version on "08/08/2016 03:44:48 PM"
     26  *                 
     27  ********************************************************************************/
     28 #define DRV_AUTHOR                          "xiaohexiansheng <1392195453@qq.com>"
     29 #define DRV_DESC                            "S3C2440 ds18b20 driver"
     30 
     31 #define DEV_NAME                            "ds18b20"
     32 #define DISABLE                             0
     33 #define DRV_MAJOR_VER                       1
     34 #define DRV_MINOR_VER                       0
     35 #define DRV_REVER_VER                       0
     36 
     37 #define LOW                                 0
     38 #define HIGH                                1
     39 
     40 #ifndef DEV_MAJOR
     41 #define DEV_MAJOR                           0
     42 #endif
     43 
     44 int dev_major = DEV_MAJOR;
     45 int dev_minor = 0;
     46 int debug = DISABLE;
     47 
     48 static struct cdev          *ds18b20_cdev;
     49 
     50 typedef unsigned char BYTE;
     51 static BYTE data[2];
     52 
     53 BYTE ds18b20_reset(void)
     54 {
     55     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
     56     s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
     57     udelay(480);
     58     s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
     59     udelay(60);
     60 
     61     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
     62     if(s3c2410_gpio_getpin(S3C2410_GPG(0)))
     63     {
     64         printk("ds18b20 reset failed.
    ");
     65         return 1;
     66     }
     67     udelay(240);
     68     return 0;
     69 }
     70 
     71 BYTE ds18b20_read_byte(void)
     72 {
     73     BYTE i = 0;
     74     BYTE byte = 0;
     75 
     76     for(i = 0; i < 8; i++)
     77     {
     78         s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
     79         s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
     80         udelay(1);
     81         byte >>= 1;
     82         s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
     83         s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
     84         if(s3c2410_gpio_getpin(S3C2410_GPG(0)))
     85             byte |= 0x80;
     86         udelay(50);
     87     }
     88     return byte;
     89 }
     90 
     91 BYTE ds18b20_write_byte(BYTE byte)
     92 {
     93     BYTE i;
     94     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
     95     for(i = 0; i < 8; i++)
     96     {
     97         s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
     98         udelay(15);
     99         if(byte & HIGH)
    100         {
    101             s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
    102         }
    103         else
    104         {
    105             s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
    106         }
    107         udelay(45);
    108 
    109         s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
    110         udelay(1);
    111         byte >>= 1;
    112     }
    113     s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
    114     return 0;
    115 }
    116 
    117 void ds18b20_proc(void)
    118 {
    119         while(ds18b20_reset());
    120         udelay(120);
    121         ds18b20_write_byte(0xcc);
    122         ds18b20_write_byte(0x44);
    123         udelay(5);
    124 
    125         while(ds18b20_reset());
    126         udelay(200);
    127         ds18b20_write_byte(0xcc);
    128         ds18b20_write_byte(0xbe);
    129           
    130         data[0] = ds18b20_read_byte();
    131         data[1] = ds18b20_read_byte();
    132 }
    133 
    134 static ssize_t s3c2440_ds18b20_read(struct file *filp, char *buff, size_t len, loff_t *off)
    135 {
    136         ds18b20_proc();
    137 
    138         buff[0] = data[0];
    139         buff[1] = data[1];
    140 
    141         return 1;
    142 }
    143 
    144 static struct file_operations ds18b20_fops =
    145 {
    146 
    147     .owner = THIS_MODULE,
    148     .read = s3c2440_ds18b20_read,
    149 };
    150 
    151 static int __init s3c_ds18b20_init(void)
    152 {
    153     int                     result;
    154     dev_t                   devno;
    155 
    156     if(0 != ds18b20_reset())
    157     {
    158         printk(KERN_ERR "s3c2440 ds18b20 hardware initialize failure.
    ");
    159         return -ENODEV;
    160     }
    161 
    162     if(0 != dev_major)
    163     {
    164         devno = MKDEV(dev_major, 0);
    165         result = register_chrdev_region(devno, 1, DEV_NAME);
    166     }
    167     else
    168     {
    169         result = alloc_chrdev_region(&devno, dev_minor, 1, DEV_NAME);
    170         dev_major = MAJOR(devno);
    171     }
    172 
    173     if(result < 0)
    174     {
    175         printk(KERN_ERR "s3c %s driver cannot use major %d.
    ", DEV_NAME, dev_major);
    176         return -ENODEV;
    177     }
    178     printk(KERN_DEBUG "s3c %s driver use major %d.
    ", DEV_NAME, dev_major);
    179 
    180     if(NULL == (ds18b20_cdev = cdev_alloc()))
    181     {
    182         printk(KERN_ERR "s3c %s driver cannot register cdev: result = %d.
    ", DEV_NAME, result);
    183         unregister_chrdev_region(devno, 1);
    184         return -ENOMEM;
    185     }
    186 
    187     ds18b20_cdev -> owner = THIS_MODULE;
    188     cdev_init(ds18b20_cdev, &ds18b20_fops);
    189 
    190     result = cdev_add(ds18b20_cdev, devno, 1);
    191     if(0 != result)
    192     {
    193         printk(KERN_ERR "s3c %s driver cannot register cdev: result = %d.
    ", DEV_NAME, result);
    194         goto ERROR;
    195     }
    196 
    197     printk(KERN_ERR "s3c %s driver[major=%d] Version %d.%d.%d installed successfully.
    ",DEV_NAME, dev_major, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);
    198     return 0;
    199 
    200 ERROR:
    201     printk(KERN_ERR "s3c %s driver installed failure./", DEV_NAME);
    202     cdev_del(ds18b20_cdev);
    203     unregister_chrdev_region(devno, 1);
    204     return result;
    205 }
    206 
    207 static void __exit s3c_ds18b20_exit(void)
    208 {
    209     dev_t devno = MKDEV(dev_major, dev_minor);
    210 
    211     cdev_del(ds18b20_cdev);
    212     unregister_chrdev_region(devno, 1);
    213 
    214     printk(KERN_ERR "s3c %s driver version %d.%d.%d removed!
    ", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);
    215     return;
    216 }
    217 
    218 module_init(s3c_ds18b20_init);
    219 module_exit(s3c_ds18b20_exit);
    220 
    221 module_param(debug, int, S_IRUGO);
    222 module_param(dev_major, int ,S_IRUGO);
    223 
    224 MODULE_AUTHOR(DRV_AUTHOR);
    225 MODULE_DESCRIPTION(DRV_DESC);
    226 MODULE_LICENSE("GPL");

    注:cdev的驱动需要手动创建设备节点,而misc不需要

    三、测试程序

     1 /*********************************************************************************
     2  *      Copyright:  (C) 2016 2013dianxin_3
     3  *                  All rights reserved.
     4  *
     5  *       Filename:  dsapp.c
     6  *    Description:  This file 
     7  *                 
     8  *        Version:  1.0.0(08/08/2016)
     9  *         Author:  xiaohexiansheng <1392195453@qq.com>
    10  *      ChangeLog:  1, Release initial version on "08/08/2016 10:19:25 AM"
    11  *                 
    12  ********************************************************************************/
    13 #include <stdio.h>
    14 #include <sys/types.h>
    15 #include <sys/ioctl.h>
    16 #include <stdlib.h>
    17 #include <termios.h>
    18 #include <sys/stat.h>
    19 #include <fcntl.h>
    20 #include <sys/time.h>
    21 
    22 /********************************************************************************
    23  *  Description:
    24  *   Input Args:
    25  *  Output Args:
    26  * Return Value:
    27  ********************************************************************************/
    28 int main (int argc, char **argv)
    29 {
    30     int fd;
    31     double result = 0;
    32     unsigned char buff[2];
    33     unsigned short temp = 0;
    34     int flag = 0;
    35 
    36     if ((fd=open("/dev/ds18b20",O_RDWR | O_NDELAY | O_NOCTTY)) < 0)
    37     {
    38         perror("open device ds18b20 failed.
    ");
    39         exit(1);
    40     }
    41     while(1)
    42     {
    43         printf("open device ds18b20 success.
    ");
    44         read(fd, buff, sizeof(buff));
    45         temp=((unsigned short)buff[1])<<8;
    46         temp|=(unsigned short)buff[0];
    47         result=0.0625*((double)temp);
    48         printf("temperature is %4f 
    ", result);
    49         sleep(2);
    50     }
    51     close(fd);
    52 
    53     return 0;
    54 } /* ----- End of main() ----- */
  • 相关阅读:
    manjora20安装搜狗输入法
    manjora20使用体验
    deepin20体验
    deepin20搜狗输入法使用
    deepin20使用snap并设置代理
    C#服务器端使用office组件
    华为多屏互动看学英语
    ThinkPad S5立体声混响以及语音识别
    mate10碎屏机当成小电脑使用尝试
    刷机错误ERROR:STATUS_BROM_CMD__FAIL
  • 原文地址:https://www.cnblogs.com/xiaohexiansheng/p/5778473.html
Copyright © 2011-2022 走看看