zoukankan      html  css  js  c++  java
  • 嵌入式Linux驱动学习之路(十一)按键驱动-中断机制

    轮询方式:

      和led驱动不同的是在配置IO引脚的时候,把LED的输出引脚换成输入,在read函数中向外发送io的状态。必须由应用程序不断的来查询当前IO口的状态来判断。

    中断方式:

    /* file name: key.c */
    #include <linux/sched.h> #include <linux/signal.h> #include <linux/spinlock.h> #include <linux/errno.h> #include <linux/random.h> #include <linux/poll.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/wait.h> #include <linux/mutex.h> #include <linux/io.h> #include <asm/irq.h> #include <linux/irq.h> #include <linux/fs.h> #include <asm/arch/regs-gpio.h> #include <linux/interrupt.h> static struct class *key_class; //创建类 static struct class_device *key_class_devs; //创建类对应的设备 struct pin_desc{ unsigned int pin; unsigned int key_val; }; struct pin_desc pins_desc[4] = { {S3C2410_GPF0,0X01}, {S3C2410_GPF2,0X02}, {S3C2410_GPG3,0X03}, {S3C2410_GPG11,0X04}, }; unsigned char keyvals=0; static volatile int ev_press = 0; static DECLARE_WAIT_QUEUE_HEAD(button_waitq);     static irqreturn_t keys_irq(int irq, void *dev_id) { struct pin_desc *pindesc = (struct pin_desc *)dev_id; unsigned int pinval; pinval = s3c2410_gpio_getpin(pindesc->pin); if(pinval) { keyvals = pindesc->key_val|0x80; } else { keyvals = pindesc->key_val; } ev_press = 1; wake_up_interruptible(&button_waitq);    //休眠唤醒 return IRQ_HANDLED; } int key_open(struct inode *inode, struct file *fp) { request_irq( IRQ_EINT0, keys_irq, IRQT_BOTHEDGE, "key2", &pins_desc[0]);    //注册终端 linux会自己配置引脚 request_irq( IRQ_EINT2, keys_irq, IRQT_BOTHEDGE, "key3", &pins_desc[1]); request_irq( IRQ_EINT11, keys_irq, IRQT_BOTHEDGE, "key4", &pins_desc[2]); request_irq( IRQ_EINT19, keys_irq, IRQT_BOTHEDGE, "key5", &pins_desc[3]); return 0; } ssize_t key_read(struct file *fp, char __user *buff, size_t count, loff_t *offp){ if(count != 1) { return -EINVAL; } wait_event_interruptible(button_waitq,ev_press);  //休眠 copy_to_user(buff,&keyvals,1); ev_press = 0; return 0; } ssize_t key_write(struct file *fp, const char __user *buf, size_t count, loff_t *ppos){ } int key_close(struct inode *inode, struct file *file) { free_irq(IRQ_EINT0,&pins_desc[0]);    //释放中断源 free_irq(IRQ_EINT2,&pins_desc[1]); free_irq(IRQ_EINT11,&pins_desc[2]); free_irq(IRQ_EINT19,&pins_desc[3]); } struct file_operations led_fops={ .owner = THIS_MODULE, .open = key_open, .write = key_write, .read = key_read, .release = key_close, }; int major; static int key_init(void) { major = register_chrdev( 0,"key_drv", &led_fops ); key_class = class_create(THIS_MODULE,"key_class"); key_class_devs = class_device_create(key_class,NULL,MKDEV(major,0),NULL,"my_keys"); printk("key install Module "); return 0; } static void key_exit(void) { unregister_chrdev( major, "key_drv" ); class_device_unregister(key_class_devs); class_destroy(key_class); printk("key Module exit "); } module_init(key_init); module_exit(key_exit); MODULE_LICENSE("GPL");

    Makefile同led中的类似。

     应用程序:

    #include <stdio.h>
    #include <fcntl.h>
    
    
    int main()
    {
        int fd;
        unsigned char key_val;
        fd = open("/dev/my_keys",O_RDWR);
        if(fd<0)
        {
            printf("open failed
    ");
            return 0;
        }
        while(1)
        {
            read(fd, &key_val,1);
            printf("key:%x
    ",key_val);
        }
    }

    sd

  • 相关阅读:
    遍历数据类型数组方式
    for 循环 和for..in循环遍历数组 的区别
    多个区域内有相同属性名称子元素,同一区域内 操作DOM子集 使用$("选择器",context)方法
    CSS 使用技巧
    JavaScript 动态加载页面 js文件
    angular2环境配置
    在路上●我的年青●逐步前进
    ARM v8-A 系列CPU的MMU隐射分析
    ARM Cortex-A53 Cache与内存的映射关系以及Cache的一致性分析
    二维图像的投影和图像重建分析之傅里叶变换法
  • 原文地址:https://www.cnblogs.com/ynxf/p/5997591.html
Copyright © 2011-2022 走看看