新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 字符設備驅動-利用次設備號實現多路LED控制

        字符設備驅動-利用次設備號實現多路LED控制

        作者: 時間:2016-11-21 來源:網絡 收藏
        驅動源碼:
        #include
        .
        .
        #include
        int major;
        int minor = 0;
        static struct class *leddrv_class;
        static struct class_device *leddrv_class_devs[4];
        volatile unsigned long *gpfcon = NULL;
        volatile unsigned long *gpfdat = NULL;
        static int led_drv_open(struct inode *inode, struct file *file)
        {
        int minor = MINOR(inode->i_rdev); //MINOR(inode->i_cdev);
        switch(minor)
        {
        case 0:
        {
        // 配置3引腳為輸出
        //s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
        *gpfcon &= ~(0x3<<(4*2));
        *gpfcon |= (1<<(4*2));
        //s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
        *gpfcon &= ~(0x3<<(5*2));
        *gpfcon |= (1<<(5*2));
        //s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
        *gpfcon &= ~(0x3<<(6*2));
        *gpfcon |= (1<<(6*2));
        // 都輸出0
        //s3c2410_gpio_setpin(S3C2410_GPF4, 0);
        *gpfdat &= ~(1<<4);
        //s3c2410_gpio_setpin(S3C2410_GPF5, 0);
        *gpfdat &= ~(1<<5);
        //s3c2410_gpio_setpin(S3C2410_GPF6, 0);
        *gpfdat &= ~(1<<6);
        break;
        }
        case 1:
        {
        s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
        s3c2410_gpio_setpin(S3C2410_GPF4, 0);
        break;
        }
        case 2:
        {
        s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
        s3c2410_gpio_setpin(S3C2410_GPF5, 0);
        break;
        }
        case 3:
        {
        s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
        s3c2410_gpio_setpin(S3C2410_GPF6, 0);
        break;
        }
        }
        return 0;
        }
        static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
        {
        char val;
        int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        copy_from_user(&val, buf, 1);
        switch (minor)
        {
        case 0:
        {
        s3c2410_gpio_setpin(S3C2410_GPF4, (val & 0x1));
        s3c2410_gpio_setpin(S3C2410_GPF5, (val & 0x1));
        s3c2410_gpio_setpin(S3C2410_GPF6, (val & 0x1));
        break;
        }
        case 1:
        {
        s3c2410_gpio_setpin(S3C2410_GPF4, val);
        break;
        }
        case 2:
        {
        s3c2410_gpio_setpin(S3C2410_GPF5, val);
        break;
        }
        case 3:
        {
        s3c2410_gpio_setpin(S3C2410_GPF6, val);
        break;
        }
        }
        return 0;
        }
        static struct file_operations led_drv_fops = {
        .owner = THIS_MODULE,
        .open = led_drv_open,
        .write = led_drv_write,
        };
        static int led_drv_init(void)
        {
        major = register_chrdev(0, "led_drv", &led_drv_fops); // 注冊字符驅動, 告訴內核
        leddrv_class = class_create(THIS_MODULE, "leddrv"); //創建設備節點
        leddrv_class_devs[0] = class_device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "leddrv");
        for (minor = 1; minor < 4; minor++)
        {
        leddrv_class_devs[minor] = class_device_create(leddrv_class, NULL, MKDEV(major, minor), NULL, "leddrv%d", minor);
        if (unlikely(IS_ERR(leddrv_class_devs[minor])))
        return PTR_ERR(leddrv_class_devs[minor]);
        }
        gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
        gpfdat = gpfcon + 1;
        return 0;
        }
        static void led_drv_exit(void)
        {
        unregister_chrdev(major, "led_drv"); // 卸載
        for (minor = 0; minor < 4; minor++)
        {
        class_device_unregister(leddrv_class_devs[minor]);
        }
        class_destroy(leddrv_class);
        iounmap(gpfcon);
        }
        module_init(led_drv_init);
        module_exit(led_drv_exit);
        MODULE_LICENSE("GPL");
        ==================================================================================================
        測試程序:
        #include
        #include
        #include
        #include
        void print_usage(char *file)
        {
        printf("Usage:n");
        printf("%s n",file);
        printf("eg. n");
        printf("%s /dev/leds onn", file);
        printf("%s /dev/leds offn", file);
        printf("%s /dev/led1 onn", file);
        printf("%s /dev/led1 offn", file);
        }
        int main(int argc, char **argv)
        {
        int fd;
        char* filename;
        char val;
        if (argc != 3)
        {
        print_usage(argv[0]);
        return 0;
        }
        filename = argv[1];
        fd = open(filename, O_RDWR);
        if (fd < 0)
        {
        printf("error, cant open %sn", filename);
        return 0;
        }
        if (!strcmp("on", argv[2]))
        {
        // 亮燈
        val = 0;
        write(fd, &val, 1);
        }
        else if (!strcmp("off", argv[2]))
        {
        // 滅燈
        val = 1;
        write(fd, &val, 1);
        }
        else
        {
        print_usage(argv[0]);
        return 0;
        }
        }
        =================================================================================================
        實驗:
        ls -l /dev/leddrv
        ls -l /dev/leddrv1
        ./leddrvTest /dev/leddrv on
        ./leddrvTest /dev/leddrv off
        ./leddrvTest /dev/leddrv1 on
        ./leddrvTest /dev/leddrv2 on
        ./leddrvTest /dev/leddrv2 off
        ./leddrvTest /dev/leddrv3 on
        ./leddrvTest /dev/leddrv3 off
        運行程序時輸入不同的/dev/leddrv、/dev/leddrv1、/dev/leddrv2、/dev/leddrv3得到的次設備號不同,驅動程序中根據不同的次設備號控制不同的燈,輸入不同的on、off命令write時寫入的值不同,根據不同的值執行開關動作。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 通河县| 平罗县| 邵武市| 连云港市| 普定县| 调兵山市| 方正县| 蕉岭县| 西城区| 舞钢市| 宁南县| 抚宁县| 哈尔滨市| 什邡市| 天门市| 达州市| 通城县| 滕州市| 莱芜市| 兴国县| 巴林左旗| 隆化县| 剑川县| 临桂县| 金华市| 涟水县| 大化| 贡嘎县| 孝感市| 西盟| 商城县| 澎湖县| 新田县| 松桃| 鱼台县| 渭源县| 虎林市| 鹰潭市| 林州市| 龙海市| 广水市|