• 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);
        }
    }
  • 相关阅读:
    WinCE NAND flash
    正确选择报表工具的十大标准
    从技术岗位走向管理岗位:机会是留给有准备的人
    创业失败的七个原因及解决之道
    技术人员如何参与产品设计讨论:激活那一潭死水
    基于Android Studio搭建hello world工程
    基于Android Studio搭建Android应用开发环境
    JS数组去重的6种算法实现
    八款前端开发人员更轻松的实用在线工具
    海市蜃楼-嘉兴外蒲岛奇遇
  • 原文地址:https://www.cnblogs.com/hello2mhb/p/3280849.html
Copyright © 2020-2023  润新知