Linux按键驱动程序、定时器消抖
2014-04-07 23:07
323 查看
使用定时器可以防止因为按键抖动产生的多次响应函数~~
#include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/cdev.h> #include <asm/uaccess.h> #include <linux/timer.h> #include <linux/percpu.h> #include <asm/gpio.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #define BUT_NAME "buttons" #define DEVCOUNT 1 struct dev_button { dev_t dev; struct cdev *cdev_p; struct class * clz; struct class_device * clz_dev; struct timer_list timer; }; struct key_dev { char * name; const int irq_num; unsigned int pin; unsigned int key_status; }; struct dev_button button_device; struct key_dev keys[] = { {.name = "S2", .irq_num = IRQ_EINT0, .pin = S3C2410_GPF0, .key_status = 0}, {.name = "s3", .irq_num = IRQ_EINT2, .pin = S3C2410_GPF2, .key_status = 0}, {.name = "s4", .irq_num = IRQ_EINT11, .pin = S3C2410_GPG3, .key_status = 0}, }; void timer_function(unsigned long data) { struct key_dev * p_dev = (struct key_dev *)data; if(p_dev) { if(p_dev->key_status) printk("Key %s pressed!\n", p_dev->name); else printk("Key %s unpressed!\n", p_dev->name); } } irqreturn_t key_handler(int irq, void * param) { struct key_dev * p_dev = (struct key_dev *)param; if(p_dev) { button_device.timer.data = (unsigned long)p_dev; if(s3c2410_gpio_getpin(p_dev->pin)) p_dev->key_status = 0; else p_dev->key_status = 1; mod_timer(&(button_device.timer), jiffies + HZ/100); } return 0; } struct file_operations f_ops = { .owner = THIS_MODULE, }; static int __init buttons_init(void) { int error = 0; ssize_t i = 0; printk("Button's driver is installing...\n"); if ((error = alloc_chrdev_region(&(button_device.dev), 0, DEVCOUNT, BUT_NAME)) < 0) { printk(KERN_ERR "button: Couldn't alloc_chrdev_region, error=%d\n", error); goto ERR_REG_DEVT; } printk("Alloc character region(%d, %d).\n", MAJOR(button_device.dev), MINOR(button_device.dev)); button_device.cdev_p = cdev_alloc(); if(NULL == button_device.cdev_p) { printk(KERN_ERR "button: Couldn't cdev_alloc"); goto ERR_ALLOC; } printk("Alloc cdev struct.\n"); button_device.cdev_p->ops = &f_ops; error = cdev_add(button_device.cdev_p, button_device.dev, DEVCOUNT); if(error < 0) { printk(KERN_ERR "button: Couldn't cdev_add"); goto ERR_ADD_DEV; } printk("Add character device.\n"); button_device.clz = class_create(THIS_MODULE, BUT_NAME); if(button_device.clz == NULL) { printk(KERN_ERR "button: Couldn't class_create"); goto ERR_CLASS_CREATE; } printk("create class...\n"); button_device.clz_dev = class_device_create(button_device.clz, NULL, button_device.dev, NULL, BUT_NAME); if(NULL == button_device.clz_dev) { printk(KERN_ERR "button: Couldn't class_device_create"); goto ERR_DEV_CREATE; } printk("create device...\n"); printk("Button's driver installed successfully.\n"); for(i = 0; i < sizeof(keys)/sizeof(struct key_dev); i++) { if(0 != request_irq(keys[i].irq_num, key_handler, IRQT_BOTHEDGE, keys[i].name, (void*)(keys + i))) { printk(KERN_ERR "button: Couldn't request_irq %s\n", keys[i].name); goto ERR_REQUEST_IRQ; } printk("request_irq %d %s successfully\n", keys[i].irq_num, keys[i].name); } init_timer(&button_device.timer); button_device.timer.function = &timer_function; add_timer(&button_device.timer); return 0; ERR_REQUEST_IRQ: for( i-=1 ; i >= 0; i--) free_irq(keys[i].irq_num, NULL); ERR_DEV_CREATE: class_destroy(button_device.clz); ERR_CLASS_CREATE: cdev_del(button_device.cdev_p); ERR_ADD_DEV: kfree(button_device.cdev_p); ERR_ALLOC: unregister_chrdev_region(button_device.dev, DEVCOUNT); ERR_REG_DEVT: printk("Error happened!\n"); return -1; } static void __exit buttons_exit(void) { ssize_t i = 0; device_destroy(button_device.clz, button_device.dev); class_destroy(button_device.clz); kfree(button_device.cdev_p); unregister_chrdev_region(button_device.dev, DEVCOUNT); del_timer(&(button_device.timer)); for( i = 0 ; i < sizeof(keys) / sizeof(struct key_dev); i++) free_irq(keys[i].irq_num, (void*)(keys + i)); return ; } module_init(buttons_init); module_exit(buttons_exit); MODULE_LICENSE("GPL");
相关文章推荐
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-按键驱动程序之异步通知机制+原子操作+互斥信号量+阻塞与非阻塞+定时器去抖
- arm驱动程序——按键程序3_定时器消抖(韦东山的视频总结及针对linux-2.6.30)
- linux驱动程序之定时器防按键抖动
- 按键驱动程序(定时器去抖)
- linux 定时器去抖 按键驱动(转载)
- tiny6410按键驱动程序2.0(利用中断和定时器去抖)
- Linux_arm驱动之按键模拟脉冲实现定时器的精确计时 (实例)
- <2012 11 6 > linux设备驱动程序开发初探(4) linux的中断体系_按键中断驱动程序编写
- linux字符设备驱动-定时器按键去抖笔记
- linux字符驱动之定时器去抖动按键驱动
- linux2.6内核下的一个按键中断驱动程序示例[zz]
- linux字符设备驱动-定时器按键去抖笔记
- OK6410的6个按键驱动程序(Linux),测试通过
- LINUX下ADC按键驱动程序
- linux字符驱动之定时器去抖动按键驱动
- Linux 按键定时器去抖
- OK6410的单个按键驱动程序(Linux),测试通过
- 【ARM&Linux】按键中断驱动程序设计
- Linux字符设备驱动之定时器去抖动按键驱动
- OK6410按键驱动程序(Linux),测试通过后分享给大家