驱动程序 本文引用地址:https://www.eepw.com.cn/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"//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; } |
评论