新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM-LINUX按鍵中斷驅動程序

        ARM-LINUX按鍵中斷驅動程序

        作者: 時間:2016-11-11 來源:網絡 收藏

        驅動程序

        本文引用地址:http://www.104case.com/article/201611/316606.htm

        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #includeinterrupt.h>
        #include
        #include
        #include


        #define DEV_NAME "qjz_buttons"http://DEV_NAME要與應用程序的open調用的NAME一樣
        static int buttons_major,buttons_minor=0;//定義設備號
        static struct cdev buttons_cdev;//定義設備結構
        static struct class *buttons_class;
        static dev_t dev;

        struct button_irq_desc
        {
        int irq;
        int pin;
        int pin_setting;
        int number;
        char *name;
        };

        static struct button_irq_desc button_irqs[ ]=
        {
        {IRQ_EINT1,S3C2410_GPF1,S3C2410_GPF1_EINT1,0,"KEY1"},
        {IRQ_EINT4,S3C2410_GPF4,S3C2410_GPF4_EINT4,1,"KEY2"},
        {IRQ_EINT2,S3C2410_GPF2,S3C2410_GPF2_EINT2,2,"KEY3"},
        {IRQ_EINT0,S3C2410_GPF0,S3C2410_GPF0_EINT0,3,"KEY4"},
        };
        static volatile int key_values[]={0,0,0,0};
        static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
        static volatile int ev_press = 0;

        static irqreturn_t buttons_interrupt(int irq,void *dev_id)
        {
        struct button_irq_desc *button_irqs=(struct button_irq_desc *)dev_id;
        int up = s3c2410_gpio_getpin(button_irqs->pin);
        if(!up)
        {
        key_values[button_irqs->number]=(button_irqs->number+1);
        }
        ev_press = 1;
        wake_up_interruptible(&button_waitq);
        return IRQ_RETVAL(IRQ_HANDLED);
        }

        static int buttons_open(struct inode *inode,struct file *filp)
        {
        int i,err;
        unsigned long irq_type;
        irq_type=ioread32(S3C2410_EXTINT0);//設置中斷類型為上升沿
        irq_type&=~(3<<1 | 3<<5 | 3<<9 | 3<<17 );
        irq_type|=(3<<1 | 3<<5 | 3<<9 | 3<<17 );
        iowrite32(irq_type,S3C2410_EXTINT0);
        for(i = 0;i < 4; i++)
        {
        s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);
        err = request_irq(button_irqs[i].irq, buttons_interrupt, NULL, button_irqs[i].name,(void*)&button_irqs[i]);
        if(err)//成功返回值0,失敗返回一個負的錯誤碼
        break;
        }
        if(err)//失敗就要釋放已經注冊成功的中斷
        {
        i--;
        for(;i>=0;i--)
        {
        disable_irq(button_irqs[i].irq);
        free_irq(button_irqs[i].irq,(void*)&button_irqs[i]);
        }
        return -EBUSY;
        }
        return 0;
        }
        static int buttons_close(struct inode *inode,struct file *file)
        {
        int i;
        for(i=0;i<4;i++)
        {
        disable_irq(button_irqs[i].irq);
        free_irq(button_irqs[i].irq,(void*)&button_irqs[i]);
        }
        return 0;
        }

        static int buttons_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
        {
        unsigned long err;
        if(!ev_press)
        {
        if(filp->f_flags & O_NONBLOCK)
        return -EAGAIN;
        else
        wait_event_interruptible(button_waitq,ev_press);
        }
        ev_press = 0;
        err=copy_to_user(buff,(const void*)key_values,count);
        memset((void*)key_values,0,sizeof(key_values));
        return err?-EFAULT:4;
        }

        static unsigned int buttons_poll(struct file *filp,poll_table *wait)
        {
        unsigned int mask = 0;
        poll_wait(filp,&button_waitq,wait);
        if(ev_press)
        mask |=POLLIN|POLLRDNORM;
        return mask;
        }
        static struct file_operations buttons_fops =
        {
        .owner = THIS_MODULE,
        .open = buttons_open,
        .release = buttons_close,
        .read = buttons_read,
        .poll = buttons_poll,
        };


        static int __init buttons_init(void)
        {
        int result;
        if(buttons_major)
        {
        dev = MKDEV(buttons_major,buttons_minor);
        result = register_chrdev_region(dev,1,DEV_NAME);
        }
        else
        {
        result = alloc_chrdev_region(&dev,buttons_minor,1,DEV_NAME);
        buttons_major = MAJOR(dev);
        }
        if(result < 0)
        {
        printk(KERN_WARNING "buttons:cant get major %dn",buttons_major);
        return result;
        }
        else
        {
        printk(KERN_WARNING"registered oknbuttons_major = %dn",buttons_major);
        }
        /*led_setup_cdev(&leds_cdev,0);*/
        cdev_init(&buttons_cdev,&buttons_fops);
        buttons_cdev.owner = THIS_MODULE;
        buttons_cdev.ops = &buttons_fops;
        result = cdev_add(&buttons_cdev,dev,1);
        if(result < 0)
        {
        printk(KERN_WARNING"cdev_add failed!n");
        return result;
        }
        else
        {
        printk(KERN_WARNING"cdev_add is ok!!n");
        }
        buttons_class = class_create(THIS_MODULE,DEV_NAME);
        if(IS_ERR(buttons_class))
        {
        printk(KERN_ALERT"err:fail in buttons_class!n");
        return -1;
        }
        else
        {
        printk(KERN_WARNING"SUCCESS IN buttons_CLASS!n");
        }
        class_device_create(buttons_class,NULL,MKDEV(buttons_major,0),NULL,DEV_NAME);
        /*class_device_create(leds_class,NULL,dev,NULL,DEV_NAME);*/
        printk(KERN_WARNING"buttons Module initialed!n");
        return 0;
        }

        static void __exit buttons_exit(void)
        {
        int devno = MKDEV(buttons_major,buttons_minor);
        unregister_chrdev_region(devno,1);
        cdev_del(&buttons_cdev);
        class_device_destroy(buttons_class,devno);
        class_destroy(buttons_class);
        printk(KERN_WARNING"buttons module exit!n");
        }

        module_init(buttons_init);
        module_exit(buttons_exit);
        MODULE_LICENSE("Dual BSD/GPL");
        MODULE_DESCRIPTION("buttons device drver");
        MODULE_AUTHOR("xxx");

        應用程序

        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include

        int main(void)
        {
        int i;
        int buttons_fd;
        int key_value[4];
        buttons_fd=open("/dev/qjz_buttons",0);
        if(buttons_fd < 0)
        {
        perror("open buttons fail");
        exit(1);
        }
        for(;;)
        {
        fd_set reads;
        int ret;
        FD_ZERO(&reads);
        FD_SET(buttons_fd,&reads);
        ret = select(buttons_fd+1,&reads,NULL,NULL,NULL);
        if(ret<0)
        {
        perror("select");
        exit(1);
        }
        if(ret ==0)
        {
        printf("timeoutn");
        }
        else if(FD_ISSET(buttons_fd,&reads))
        {
        int ret=read(buttons_fd,key_value,sizeof(key_value));
        printf("%dn",ret);
        //if(ret !=sizeof(key_value))
        //{
        //if(errno !=EAGAIN)//教程中這里是有的,但是不知道為什么每次讀不出來按鍵值,屏蔽后,就可以讀出來!如圖!
        //perror("read buttonsn");
        //continue;
        //}
        //else
        //{
        for(i=0;i<4;i++)
        {
        if(key_value[i] !=0)
        printf("K%d pressd,key value=0x%dn",i+1,key_value[i]);}
        continue;
        // }
        }
        }
        close(buttons_fd);
        return 0;
        }

        奶奶的,怎么按一次有的時候會出現多次按下去的情況那?還是驅動的問題!感覺應該是中斷的抖動造成的!關于如何去抖,要看看!

        上面的應用程序用到了select,其實直接阻塞讀,就是直接read也可以得到按鍵值!我覺得select用在多輸入多輸出更有意義,也就是說用在多線程編程(例如聊天服務器里面的多點對多點,)。我不清楚用在這里是干什么!(貌似跟進程的效率有關系)、直接阻塞讀,就是進程來讀,當沒有讀到數據就一直阻塞,一直到讀取到數據才返回!

        按照網上的資料說的是:Select在Socket編程中還是比較重要的,可是對于初學Socket的人來說都不太愛用Select寫程序,他們只是習慣寫諸如connect、accept、recv或recvfrom這樣的阻塞程序(所謂阻塞方式block,顧名思義,就是進程或是線程執行到這些函數時必須等待某個事件的發生,如果事件沒有發生,進程或線程就被阻塞,函數不能立即返回)。可是使用Select就可以完成非阻塞(所謂非阻塞方式non-block,就是進程或線程執行此函數時不必非要等待事件的發生,一旦執行肯定返回,以返回值的不同來反映函數的執行情況,如果事件發生則與阻塞方式相同,若事件沒有發生則返回一個代碼來告知事件未發生,而進程或線程繼續執行,所以效率較高)方式工作的程序,它能夠監視我們需要監視的文件描述符的變化情況——讀寫或是異常。

        我覺得吧:像本例中在前面用到for循環,這樣就會照成select的效率低下!他也是一直循環的去檢查有沒有讀到數據。這豈不是跟阻塞讀差不多啦!

        阻塞read應用程序如下:

        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        #include

        int main(void)
        {
        int i;
        int buttons_fd;
        int key_value[4];
        buttons_fd=open("/dev/qjz_buttons",0);
        if(buttons_fd < 0)
        {
        perror("open buttons fail");
        exit(1);
        }
        for(;;)
        {
        read(buttons_fd,key_value,sizeof(key_value));

        for(i=0;i<4;i++)
        {
        if(key_value[i] !=0)
        printf("K%d pressd,key value=0x%dn",i+1,key_value[i]);}
        continue;

        }
        close(buttons_fd);
        return 0;
        }




        評論


        技術專區

        關閉
        主站蜘蛛池模板: 商南县| 高唐县| 涡阳县| 新乡县| 阿尔山市| 南阳市| 西乡县| 原平市| 韶关市| 弥渡县| 德令哈市| 夏河县| 马公市| 故城县| 山西省| 通许县| 邹城市| 武宁县| 庐江县| 台前县| 临猗县| 武隆县| 武陟县| 康乐县| 雷山县| 武乡县| 横山县| 泰顺县| 神木县| 安庆市| 林周县| 富蕴县| 普陀区| 巴南区| 南投县| 舒城县| 曲阜市| 临安市| 菏泽市| 永定县| 夏邑县|