zoukankan      html  css  js  c++  java
  • Linux下18b20温度传感器驱动代码及测试实例

    驱动代码:

    #include    <linux/module.h>
    #include    <linux/fs.h>
    #include    <linux/kernel.h>
    #include    <linux/init.h>
    #include    <linux/delay.h>
    #include    <linux/cdev.h>
    #include    <linux/device.h>
    #include    <linux/gpio.h>
    #include    <plat/gpio-cfg.h>
    
    #define    DEVICE_NAME "TEM0"
    
    #define    TEM_SHOW_CODE 0x01
    
    //static struct cdev cdev;
    struct class *tem_class;
    //static dev_t devno;
    //static int major = 243;//可以用int alloc_chrdev_region(dev_t *dev,unsigned baseminor,
    //unsigned count,const char *name);向系统动态申请未被占用的设备号。
    
    struct tem_dev_t
    {
        struct cdev cdev;
    }tem_dev;
    
    /**
     *  * s3c_gpio_cfgpin() - Change the GPIO function of a pin.
     *   * @pin pin The pin number to configure.
     *    * @to to The configuration for the pin's function.
     *     *
     *      * Configure which function is actually connected to the external
     *       * pin, such as an gpio input, output or some form of special function
     *        * connected to an internal peripheral block.
     *         *
     *          * The @to parameter can be one of the generic S3C_GPIO_INPUT, S3C_GPIO_OUTPUT
     *           * or S3C_GPIO_SFN() to indicate one of the possible values that the helper
     *            * will then generate the correct bit mask and shift for the configuration.
     *             *
     *              * If a bank of GPIOs all needs to be set to special-function 2, then
     *               * the following code will work:
     *                *
     *                 *    for (gpio = start; gpio < end; gpio++)
     *                  *       s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
     *                   *
     *                    * The @to parameter can also be a specific value already shifted to the
     *                     * correct position in the control register, although these are discouraged
     *                      * in newer kernels and are only being kept for compatibility.
     *                       */
    unsigned int gpio=0;
    
    void tem_reset(void)
    {
        s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));//当x=0时是输入功能,x=1时是输出功能
        gpio_set_value(gpio, 1);
        udelay(100);//延迟0.1ms
        gpio_set_value(gpio, 0);
        udelay(600);
        gpio_set_value(gpio, 1);
        udelay(100);
        s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0));
    }
    
    void tem_wbyte(unsigned char data)
    {
        int i;
    
        s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));
        for (i = 0; i < 8; ++i)
        {
            gpio_set_value(gpio, 0);
            udelay(1);
    
            if (data & 0x01)
            {
                gpio_set_value(gpio, 1);
            }
            udelay(60);
            gpio_set_value(gpio, 1);
            udelay(15);
            data >>= 1;
        }
        gpio_set_value(gpio, 1);
    }
    
    unsigned char tem_rbyte(void)
    {
        int i;
        unsigned char ret = 0;
    
        for (i = 0; i < 8; ++i)
        {
            s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));
            gpio_set_value(gpio, 0);
            udelay(1);
            gpio_set_value(gpio, 1);
    
            s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0));
            ret >>= 1;
            if (gpio_get_value(gpio))
            {
                ret |= 0x80;    
            }
            udelay(60);
        }
        s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));
    
    
        return ret;
    }
    
    static ssize_t tem_read(struct file *filp, char *buf, size_t len, loff_t *offset)
    {
        unsigned char low, high;
    
        tem_reset();
        udelay(420);
        tem_wbyte(0xcc);
        tem_wbyte(0x44);
    
        mdelay(750);
        tem_reset();
        udelay(400);
        tem_wbyte(0xcc);
        tem_wbyte(0xbe);
    
        low = tem_rbyte();
        high = tem_rbyte();
    
        *buf = low / 16 + high * 16;
    
        *(buf + 1) = (low & 0x0f) * 10 / 16 + (high & 0x0f) * 100 / 16 % 10;
        return 0;
    }
    /*******************************************************************
    *
    *ioctl 还不准确,需要改进
    *    by mhb
    *
    **********************************************************************/
    int tem_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
    {  
       printk("in the ioctl!!\n");//debug 
       switch(cmd)
       {
       case TEM_SHOW_CODE:
           {
               int i;
               unsigned char fc,sn[6],crc;
               tem_reset();
               udelay(400);
               tem_wbyte(0x33);
               fc = tem_rbyte;
               for (i = 0; i < 5; i++)
               {
                   /* code */
                   sn[i]=tem_rbyte;
               }
               crc=tem_rbyte;
               printk("familycode=%x\n",fc);
               printk("serialnumber=%x%x%x%x%x%x\n",sn[5],sn[4],sn[3],sn[2],sn[1],sn[0]);
               printk("crc=%x\n",crc);
               break;
           }
       default:
           {
              return - ENOTTY;
           }
       }
    }
    
    static struct file_operations tem_fops = 
    {
        .owner    = THIS_MODULE,
        .read    = tem_read,
        .ioctl   =tem_ioctl,
    };
    
    static int __init tem_init(void)
    {
        int result;
        int major;
        int minor;
    
        cdev_init(&tem_dev.cdev,&tem_fops);/*init cdev*/
        tem_dev.cdev.owner=THIS_MODULE;
    //  devno = MKDEV(major, 0);
    //  result = register_chrdev_region(devno, 1, DEVICE_NAME);
        result = alloc_chrdev_region(&tem_dev.cdev.dev,0,1,DEVICE_NAME);
        major=MAJOR(tem_dev.cdev.dev);
        minor=MINOR(tem_dev.cdev.dev);
        if(major)
        { 
            printk("majior=%d\n",major);
            printk("minor=%d\n",minor);
        }else
            printk("can not get device num!!\n");
    
        if (result)
        {
            printk("register failed\n");    
            return result;
        }
    #ifdef CONFIG_OK210_BOARD_V2
         gpio=S5PV210_MP04(3);
    #else
         gpio=S5PV210_GPH3(1);
    #endif
    //    cdev_init(&cdev, &tem_fops);
    //    cdev.owner = THIS_MODULE;
    //    cdev.ops = &tem_fops;
        result = cdev_add(&tem_dev.cdev, tem_dev.cdev.dev, 1);
        if (result)
        {
            printk("cdev add failed\n");    
            goto fail1;
        }
    
        tem_class = class_create(THIS_MODULE, "tmp_class");/*在sys目录下创建tmp_class这个类,/sys/class/~*/
        if (IS_ERR(tem_class))
        {
            printk("class create failed\n");    
            goto fail2;
        }
    
        device_create(tem_class, NULL, tem_dev.cdev.dev, DEVICE_NAME, DEVICE_NAME);/*自动创建设备/dev/TEM0*/
        return 0;
    fail2:
        cdev_del(&tem_dev.cdev);
    fail1:
        unregister_chrdev_region(tem_dev.cdev.dev, 1);
        return result;
    }
    
    static void __exit tem_exit(void)
    {
        device_destroy(tem_class, tem_dev.cdev.dev);
        class_destroy(tem_class);
        cdev_del(&tem_dev.cdev);
        unregister_chrdev_region(tem_dev.cdev.dev, 1);
    }
    
    module_init(tem_init);
    module_exit(tem_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("mhb");

    测试代码:

    #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"
    #define TEM_SHOW 0x01
    main()
    {
        int fd;
    #if 1
        unsigned char buf[2];
    #else
        unsigned int tmp;
    #endif
        float result;
    
        if ((fd=open("/dev/TEM0",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, sizeof(buf));
    //            result = tmp * 1000;
    //            result = *(int *)buf;
                read(fd, buf, sizeof(buf));
    #if 0
                printf("%d\n", buf[0]);
                printf("%d\n", buf[1]);
                result = (float)buf[0];
                result /= 16;
                result += ((float)buf[1] * 16);
    #endif
    #if 0
        //        printf("%f .C\r\n", result);
                sleep(1);
    #else
                    printf("%d.%d C\r\n", buf[0], buf[1]);
                    sleep(1);
                    ioctl(fd,TEM_SHOW,0);
    #endif
            }
            close(fd);
        }
    }
  • 相关阅读:
    83. Remove Duplicates from Sorted List
    35. Search Insert Position
    96. Unique Binary Search Trees
    94. Binary Tree Inorder Traversal
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    111. Minimum Depth of Binary Tree
    169. Majority Element
    171. Excel Sheet Column Number
    190. Reverse Bits
  • 原文地址:https://www.cnblogs.com/hello2mhb/p/3280849.html
Copyright © 2011-2022 走看看